diff options
-rw-r--r-- | src/dns/dnsparser.c | 44 | ||||
-rw-r--r-- | src/dns/dnsparser.h | 2 | ||||
-rw-r--r-- | src/include/gnunet_dnsparser_lib.h | 13 | ||||
-rw-r--r-- | src/namestore/namestore_common.c | 101 |
4 files changed, 120 insertions, 40 deletions
diff --git a/src/dns/dnsparser.c b/src/dns/dnsparser.c index 8578e7572..cea9cd137 100644 --- a/src/dns/dnsparser.c +++ b/src/dns/dnsparser.c | |||
@@ -46,16 +46,58 @@ int | |||
46 | GNUNET_DNSPARSER_check_label (const char *label) | 46 | GNUNET_DNSPARSER_check_label (const char *label) |
47 | { | 47 | { |
48 | char *output; | 48 | char *output; |
49 | size_t slen; | ||
49 | 50 | ||
51 | if (NULL != strchr (label, ".")) | ||
52 | return GNUNET_SYSERR; /* not a label! Did you mean GNUNET_DNSPARSER_check_name? */ | ||
50 | if (IDNA_SUCCESS != | 53 | if (IDNA_SUCCESS != |
51 | idna_to_ascii_8z (label, &output, IDNA_USE_STD3_ASCII_RULES)) | 54 | idna_to_ascii_8z (label, &output, IDNA_USE_STD3_ASCII_RULES)) |
52 | return GNUNET_SYSERR; | 55 | return GNUNET_SYSERR; |
56 | slen = strlen (output); | ||
53 | #if WINDOWS | 57 | #if WINDOWS |
54 | idn_free (output); | 58 | idn_free (output); |
55 | #else | 59 | #else |
56 | free (output); | 60 | free (output); |
57 | #endif | 61 | #endif |
58 | return GNUNET_OK; | 62 | return (slen > 63) ? GNUNET_SYSERR : GNUNET_OK; |
63 | } | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Check if a label in UTF-8 format can be coded into valid IDNA. | ||
68 | * This can fail if the ASCII-conversion becomes longer than 253 characters. | ||
69 | * | ||
70 | * @param name name to check (UTF-8 string) | ||
71 | * @return GNUNET_OK if the label can be converted to IDNA, | ||
72 | * GNUNET_SYSERR if the label is not valid for DNS names | ||
73 | */ | ||
74 | int | ||
75 | GNUNET_DNSPARSER_check_name (const char *label) | ||
76 | { | ||
77 | char *ldup; | ||
78 | char *output; | ||
79 | size_t slen; | ||
80 | char *tok; | ||
81 | |||
82 | ldup = GNUNET_strdup (label); | ||
83 | for (tok = strtok (ldup, "."); NULL != tok; tok = strtok (NULL, ".")) | ||
84 | if (GNUNET_OK != | ||
85 | GNUNET_DNSPARSER_check_label (tok)) | ||
86 | { | ||
87 | GNUNET_free (ldup); | ||
88 | return GNUNET_SYSERR; | ||
89 | } | ||
90 | GNUNET_free (ldup); | ||
91 | if (IDNA_SUCCESS != | ||
92 | idna_to_ascii_8z (label, &output, IDNA_USE_STD3_ASCII_RULES)) | ||
93 | return GNUNET_SYSERR; | ||
94 | slen = strlen (output); | ||
95 | #if WINDOWS | ||
96 | idn_free (output); | ||
97 | #else | ||
98 | free (output); | ||
99 | #endif | ||
100 | return (slen > 253) ? GNUNET_SYSERR : GNUNET_OK; | ||
59 | } | 101 | } |
60 | 102 | ||
61 | 103 | ||
diff --git a/src/dns/dnsparser.h b/src/dns/dnsparser.h index e3ab622c7..9d2880a69 100644 --- a/src/dns/dnsparser.h +++ b/src/dns/dnsparser.h | |||
@@ -187,7 +187,7 @@ struct vpn_data | |||
187 | */ | 187 | */ |
188 | struct GNUNET_HashCode peer; | 188 | struct GNUNET_HashCode peer; |
189 | 189 | ||
190 | /* followed by the servicename */ | 190 | /* followed by the servicename / identifier / password (0-terminated) */ |
191 | }; | 191 | }; |
192 | 192 | ||
193 | GNUNET_NETWORK_STRUCT_END | 193 | GNUNET_NETWORK_STRUCT_END |
diff --git a/src/include/gnunet_dnsparser_lib.h b/src/include/gnunet_dnsparser_lib.h index 526c40ab2..daeb4208b 100644 --- a/src/include/gnunet_dnsparser_lib.h +++ b/src/include/gnunet_dnsparser_lib.h | |||
@@ -538,6 +538,19 @@ GNUNET_DNSPARSER_check_label (const char *label); | |||
538 | 538 | ||
539 | 539 | ||
540 | /** | 540 | /** |
541 | * Check if a hostname in UTF-8 format can be coded into valid IDNA. | ||
542 | * This can fail if a label becomes longer than 63 characters or if | ||
543 | * the entire name exceeds 253 characters. | ||
544 | * | ||
545 | * @param name name to check (UTF-8 string) | ||
546 | * @return GNUNET_OK if the label can be converted to IDNA, | ||
547 | * GNUNET_SYSERR if the label is not valid for DNS names | ||
548 | */ | ||
549 | int | ||
550 | GNUNET_DNSPARSER_check_name (const char *name); | ||
551 | |||
552 | |||
553 | /** | ||
541 | * Parse a UDP payload of a DNS packet in to a nice struct for further | 554 | * Parse a UDP payload of a DNS packet in to a nice struct for further |
542 | * processing and manipulation. | 555 | * processing and manipulation. |
543 | * | 556 | * |
diff --git a/src/namestore/namestore_common.c b/src/namestore/namestore_common.c index f81a287c3..632ca756a 100644 --- a/src/namestore/namestore_common.c +++ b/src/namestore/namestore_common.c | |||
@@ -348,18 +348,19 @@ GNUNET_NAMESTORE_value_to_string (uint32_t type, | |||
348 | size_t data_size) | 348 | size_t data_size) |
349 | { | 349 | { |
350 | uint16_t mx_pref; | 350 | uint16_t mx_pref; |
351 | struct soa_data *soa; | 351 | const struct soa_data *soa; |
352 | struct vpn_data *vpn; | 352 | const struct vpn_data *vpn; |
353 | struct srv_data *srv; | 353 | const struct srv_data *srv; |
354 | struct tlsa_data *tlsa; | 354 | const struct tlsa_data *tlsa; |
355 | struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc; | 355 | struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc; |
356 | struct GNUNET_CRYPTO_HashAsciiEncoded s_peer; | 356 | struct GNUNET_CRYPTO_HashAsciiEncoded s_peer; |
357 | const char *cdata; | ||
357 | char* vpn_str; | 358 | char* vpn_str; |
358 | char* srv_str; | 359 | char* srv_str; |
359 | char* tlsa_str; | 360 | char* tlsa_str; |
360 | char* result; | 361 | char* result; |
361 | char* soa_rname; | 362 | const char* soa_rname; |
362 | char* soa_mname; | 363 | const char* soa_mname; |
363 | char tmp[INET6_ADDRSTRLEN]; | 364 | char tmp[INET6_ADDRSTRLEN]; |
364 | 365 | ||
365 | switch (type) | 366 | switch (type) |
@@ -373,20 +374,32 @@ GNUNET_NAMESTORE_value_to_string (uint32_t type, | |||
373 | return NULL; | 374 | return NULL; |
374 | return GNUNET_strdup (tmp); | 375 | return GNUNET_strdup (tmp); |
375 | case GNUNET_DNSPARSER_TYPE_NS: | 376 | case GNUNET_DNSPARSER_TYPE_NS: |
376 | return GNUNET_strdup (data); | 377 | return GNUNET_strndup (data, data_size); |
377 | case GNUNET_DNSPARSER_TYPE_CNAME: | 378 | case GNUNET_DNSPARSER_TYPE_CNAME: |
378 | return GNUNET_strdup (data); | 379 | return GNUNET_strndup (data, data_size); |
379 | case GNUNET_DNSPARSER_TYPE_SOA: | 380 | case GNUNET_DNSPARSER_TYPE_SOA: |
380 | soa = (struct soa_data*)data; | 381 | if (data_size <= sizeof (struct soa_data)) |
381 | soa_rname = (char*)&soa[1]; | 382 | return NULL; |
382 | soa_mname = (char*)&soa[1]+strlen(soa_rname)+1; | 383 | soa = data; |
383 | if (0 == GNUNET_asprintf(&result, "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu", | 384 | soa_rname = (const char*) &soa[1]; |
384 | soa_rname, soa_mname, | 385 | soa_mname = memchr (soa_rname, 0, data_size - sizeof (struct soa_data) - 1); |
385 | ntohl (soa->serial), ntohl (soa->refresh), | 386 | if (NULL == soa_mname) |
386 | ntohl (soa->retry), ntohl (soa->expire), ntohl (soa->minimum))) | 387 | return NULL; |
388 | soa_mname++; | ||
389 | if (NULL == memchr (soa_mname, 0, | ||
390 | data_size - (sizeof (struct soa_data) + strlen (soa_rname) + 1))) | ||
391 | return NULL; | ||
392 | if (0 == GNUNET_asprintf (&result, | ||
393 | "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu", | ||
394 | soa_rname, soa_mname, | ||
395 | ntohl (soa->serial), | ||
396 | ntohl (soa->refresh), | ||
397 | ntohl (soa->retry), | ||
398 | ntohl (soa->expire), | ||
399 | ntohl (soa->minimum))) | ||
387 | { | 400 | { |
388 | GNUNET_free (result); | 401 | GNUNET_free (result); |
389 | return NULL; | 402 | return NULL; |
390 | } | 403 | } |
391 | return result; | 404 | return result; |
392 | case GNUNET_DNSPARSER_TYPE_PTR: | 405 | case GNUNET_DNSPARSER_TYPE_PTR: |
@@ -420,42 +433,54 @@ GNUNET_NAMESTORE_value_to_string (uint32_t type, | |||
420 | case GNUNET_NAMESTORE_TYPE_LEHO: | 433 | case GNUNET_NAMESTORE_TYPE_LEHO: |
421 | return GNUNET_strndup (data, data_size); | 434 | return GNUNET_strndup (data, data_size); |
422 | case GNUNET_NAMESTORE_TYPE_VPN: | 435 | case GNUNET_NAMESTORE_TYPE_VPN: |
423 | vpn = (struct vpn_data*)data; | 436 | cdata = data; |
424 | 437 | if ( (data_size <= sizeof (struct vpn_data)) || | |
438 | ('\0' != cdata[data_size - 1]) ) | ||
439 | return NULL; /* malformed */ | ||
440 | vpn = data; | ||
425 | GNUNET_CRYPTO_hash_to_enc (&vpn->peer, &s_peer); | 441 | GNUNET_CRYPTO_hash_to_enc (&vpn->peer, &s_peer); |
426 | if (0 == GNUNET_asprintf (&vpn_str, "%hu %s %s", | 442 | if (0 == GNUNET_asprintf (&vpn_str, "%hu %s %s", |
427 | vpn->proto, | 443 | vpn->proto, |
428 | (char*)&s_peer, | 444 | (const char*) &s_peer, |
429 | (char*)&vpn[1])) | 445 | (const char*) &vpn[1])) |
430 | { | 446 | { |
431 | GNUNET_free (vpn_str); | 447 | GNUNET_free (vpn_str); |
432 | return NULL; | 448 | return NULL; |
433 | } | 449 | } |
434 | return vpn_str; | 450 | return vpn_str; |
435 | case GNUNET_DNSPARSER_TYPE_SRV: | 451 | case GNUNET_DNSPARSER_TYPE_SRV: |
436 | srv = (struct srv_data*)data; | 452 | cdata = data; |
437 | 453 | if ( (data_size <= sizeof (struct srv_data)) || | |
438 | if (0 == GNUNET_asprintf (&srv_str, "%d %d %d %s", | 454 | ('\0' != cdata[data_size - 1]) ) |
439 | ntohs (srv->prio), | 455 | return NULL; /* malformed */ |
440 | ntohs (srv->weight), | 456 | srv = data; |
441 | ntohs (srv->port), | 457 | |
442 | (char*)&srv[1])) | 458 | if (0 == GNUNET_asprintf (&srv_str, |
459 | "%d %d %d %s", | ||
460 | ntohs (srv->prio), | ||
461 | ntohs (srv->weight), | ||
462 | ntohs (srv->port), | ||
463 | (const char *)&srv[1])) | ||
443 | { | 464 | { |
444 | GNUNET_free (srv_str); | 465 | GNUNET_free (srv_str); |
445 | return NULL; | 466 | return NULL; |
446 | } | 467 | } |
447 | return srv_str; | 468 | return srv_str; |
448 | case GNUNET_DNSPARSER_TYPE_TLSA: | 469 | case GNUNET_DNSPARSER_TYPE_TLSA: |
449 | tlsa = (struct tlsa_data*)data; | 470 | cdata = data; |
450 | 471 | if ( (data_size <= sizeof (struct tlsa_data)) || | |
451 | if (0 == GNUNET_asprintf (&tlsa_str, "%c %c %c %s", | 472 | ('\0' != cdata[data_size - 1]) ) |
452 | tlsa->usage, | 473 | return NULL; /* malformed */ |
453 | tlsa->selector, | 474 | tlsa = data; |
454 | tlsa->matching_type, | 475 | if (0 == GNUNET_asprintf (&tlsa_str, |
455 | tlsa[1])) | 476 | "%c %c %c %s", |
477 | tlsa->usage, | ||
478 | tlsa->selector, | ||
479 | tlsa->matching_type, | ||
480 | (const char *) &tlsa[1])) | ||
456 | { | 481 | { |
457 | GNUNET_free (tlsa_str); | 482 | GNUNET_free (tlsa_str); |
458 | return NULL; | 483 | return NULL; |
459 | } | 484 | } |
460 | return tlsa_str; | 485 | return tlsa_str; |
461 | default: | 486 | default: |