gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r25222 - in gnunet/src: dns include namestore


From: gnunet
Subject: [GNUnet-SVN] r25222 - in gnunet/src: dns include namestore
Date: Tue, 4 Dec 2012 14:12:42 +0100

Author: grothoff
Date: 2012-12-04 14:12:42 +0100 (Tue, 04 Dec 2012)
New Revision: 25222

Modified:
   gnunet/src/dns/dnsparser.c
   gnunet/src/dns/dnsparser.h
   gnunet/src/include/gnunet_dnsparser_lib.h
   gnunet/src/namestore/namestore_common.c
Log:
-ensure labels are less than 64 chars, add test for full DNS names

Modified: gnunet/src/dns/dnsparser.c
===================================================================
--- gnunet/src/dns/dnsparser.c  2012-12-04 12:39:47 UTC (rev 25221)
+++ gnunet/src/dns/dnsparser.c  2012-12-04 13:12:42 UTC (rev 25222)
@@ -46,20 +46,62 @@
 GNUNET_DNSPARSER_check_label (const char *label)
 {
   char *output;
+  size_t slen;
   
+  if (NULL != strchr (label, "."))
+    return GNUNET_SYSERR; /* not a label! Did you mean 
GNUNET_DNSPARSER_check_name? */
   if (IDNA_SUCCESS != 
       idna_to_ascii_8z (label, &output, IDNA_USE_STD3_ASCII_RULES))
     return GNUNET_SYSERR;
+  slen = strlen (output);
 #if WINDOWS
   idn_free (output);
 #else
   free (output);
 #endif
-  return GNUNET_OK;
+  return (slen > 63) ? GNUNET_SYSERR : GNUNET_OK;
 }
 
 
 /**
+ * Check if a label in UTF-8 format can be coded into valid IDNA.
+ * This can fail if the ASCII-conversion becomes longer than 253 characters.
+ *
+ * @param name name to check (UTF-8 string)
+ * @return GNUNET_OK if the label can be converted to IDNA,
+ *         GNUNET_SYSERR if the label is not valid for DNS names
+ */
+int
+GNUNET_DNSPARSER_check_name (const char *label)
+{
+  char *ldup;
+  char *output;
+  size_t slen;
+  char *tok;
+  
+  ldup = GNUNET_strdup (label);
+  for (tok = strtok (ldup, "."); NULL != tok; tok = strtok (NULL, "."))
+    if (GNUNET_OK !=
+       GNUNET_DNSPARSER_check_label (tok))
+    {
+      GNUNET_free (ldup);
+      return GNUNET_SYSERR;
+    }
+  GNUNET_free (ldup);
+  if (IDNA_SUCCESS != 
+      idna_to_ascii_8z (label, &output, IDNA_USE_STD3_ASCII_RULES))
+    return GNUNET_SYSERR;
+  slen = strlen (output);
+#if WINDOWS
+  idn_free (output);
+#else
+  free (output);
+#endif
+  return (slen > 253) ? GNUNET_SYSERR : GNUNET_OK;
+}
+
+
+/**
  * Parse name inside of a DNS query or record.
  *
  * @param udp_payload entire UDP payload

Modified: gnunet/src/dns/dnsparser.h
===================================================================
--- gnunet/src/dns/dnsparser.h  2012-12-04 12:39:47 UTC (rev 25221)
+++ gnunet/src/dns/dnsparser.h  2012-12-04 13:12:42 UTC (rev 25222)
@@ -187,7 +187,7 @@
    */
   struct GNUNET_HashCode peer;
 
-  /* followed by the servicename */
+  /* followed by the servicename / identifier / password (0-terminated) */
 };
 
 GNUNET_NETWORK_STRUCT_END

Modified: gnunet/src/include/gnunet_dnsparser_lib.h
===================================================================
--- gnunet/src/include/gnunet_dnsparser_lib.h   2012-12-04 12:39:47 UTC (rev 
25221)
+++ gnunet/src/include/gnunet_dnsparser_lib.h   2012-12-04 13:12:42 UTC (rev 
25222)
@@ -538,6 +538,19 @@
 
 
 /**
+ * Check if a hostname in UTF-8 format can be coded into valid IDNA.
+ * This can fail if a label becomes longer than 63 characters or if
+ * the entire name exceeds 253 characters.
+ *
+ * @param name name to check (UTF-8 string)
+ * @return GNUNET_OK if the label can be converted to IDNA,
+ *         GNUNET_SYSERR if the label is not valid for DNS names
+ */
+int
+GNUNET_DNSPARSER_check_name (const char *name);
+
+
+/**
  * Parse a UDP payload of a DNS packet in to a nice struct for further
  * processing and manipulation.
  *

Modified: gnunet/src/namestore/namestore_common.c
===================================================================
--- gnunet/src/namestore/namestore_common.c     2012-12-04 12:39:47 UTC (rev 
25221)
+++ gnunet/src/namestore/namestore_common.c     2012-12-04 13:12:42 UTC (rev 
25222)
@@ -348,18 +348,19 @@
                                  size_t data_size)
 {
   uint16_t mx_pref;
-  struct soa_data *soa;
-  struct vpn_data *vpn;
-  struct srv_data *srv;
-  struct tlsa_data *tlsa;
+  const struct soa_data *soa;
+  const struct vpn_data *vpn;
+  const struct srv_data *srv;
+  const struct tlsa_data *tlsa;
   struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
   struct GNUNET_CRYPTO_HashAsciiEncoded s_peer;
+  const char *cdata;
   char* vpn_str;
   char* srv_str;
   char* tlsa_str;
   char* result;
-  char* soa_rname;
-  char* soa_mname;
+  const char* soa_rname;
+  const char* soa_mname;
   char tmp[INET6_ADDRSTRLEN];
 
   switch (type)
@@ -373,20 +374,32 @@
       return NULL;
     return GNUNET_strdup (tmp);
   case GNUNET_DNSPARSER_TYPE_NS:
-    return GNUNET_strdup (data);
+    return GNUNET_strndup (data, data_size);
   case GNUNET_DNSPARSER_TYPE_CNAME:
-    return GNUNET_strdup (data);
+    return GNUNET_strndup (data, data_size);
   case GNUNET_DNSPARSER_TYPE_SOA:
-    soa = (struct soa_data*)data;
-    soa_rname = (char*)&soa[1];
-    soa_mname = (char*)&soa[1]+strlen(soa_rname)+1;
-    if (0 == GNUNET_asprintf(&result, "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu",
-                     soa_rname, soa_mname,
-                     ntohl (soa->serial), ntohl (soa->refresh),
-                     ntohl (soa->retry), ntohl (soa->expire), ntohl 
(soa->minimum)))
+    if (data_size <= sizeof (struct soa_data))
+      return NULL;
+    soa = data;
+    soa_rname = (const char*) &soa[1];
+    soa_mname = memchr (soa_rname, 0, data_size - sizeof (struct soa_data) - 
1);
+    if (NULL == soa_mname)
+      return NULL;
+    soa_mname++;
+    if (NULL == memchr (soa_mname, 0, 
+                       data_size - (sizeof (struct soa_data) + strlen 
(soa_rname) + 1)))
+      return NULL;
+    if (0 == GNUNET_asprintf (&result, 
+                             "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu",
+                             soa_rname, soa_mname,
+                             ntohl (soa->serial), 
+                             ntohl (soa->refresh),
+                             ntohl (soa->retry), 
+                             ntohl (soa->expire),
+                             ntohl (soa->minimum)))
     {
-        GNUNET_free (result);
-        return NULL;
+      GNUNET_free (result);
+      return NULL;
     }
     return result;
   case GNUNET_DNSPARSER_TYPE_PTR:
@@ -420,42 +433,54 @@
   case GNUNET_NAMESTORE_TYPE_LEHO:
     return GNUNET_strndup (data, data_size);
   case GNUNET_NAMESTORE_TYPE_VPN:
-    vpn = (struct vpn_data*)data;
-
+    cdata = data;
+    if ( (data_size <= sizeof (struct vpn_data)) ||
+        ('\0' != cdata[data_size - 1]) )
+      return NULL; /* malformed */
+    vpn = data;
     GNUNET_CRYPTO_hash_to_enc (&vpn->peer, &s_peer);
     if (0 == GNUNET_asprintf (&vpn_str, "%hu %s %s",
-                                      vpn->proto,
-                                      (char*)&s_peer,
-                                      (char*)&vpn[1]))
+                             vpn->proto,
+                             (const char*) &s_peer,
+                             (const char*) &vpn[1]))
     {
         GNUNET_free (vpn_str);
         return NULL;
     }
     return vpn_str;
   case GNUNET_DNSPARSER_TYPE_SRV:
-    srv = (struct srv_data*)data;
+    cdata = data;
+    if ( (data_size <= sizeof (struct srv_data)) ||
+        ('\0' != cdata[data_size - 1]) )
+      return NULL; /* malformed */
+    srv = data;
 
-    if (0 == GNUNET_asprintf (&srv_str, "%d %d %d %s",
-                                      ntohs (srv->prio),
-                                      ntohs (srv->weight),
-                                      ntohs (srv->port),
-                                      (char*)&srv[1]))
+    if (0 == GNUNET_asprintf (&srv_str, 
+                             "%d %d %d %s",
+                             ntohs (srv->prio),
+                             ntohs (srv->weight),
+                             ntohs (srv->port),
+                             (const char *)&srv[1]))
     {
       GNUNET_free (srv_str);
       return NULL;
     }
     return srv_str;
   case GNUNET_DNSPARSER_TYPE_TLSA:
-    tlsa = (struct tlsa_data*)data;
-
-    if (0 == GNUNET_asprintf (&tlsa_str, "%c %c %c %s",
-                                      tlsa->usage,
-                                      tlsa->selector,
-                                      tlsa->matching_type,
-                                      tlsa[1]))
+    cdata = data;
+    if ( (data_size <= sizeof (struct tlsa_data)) ||
+        ('\0' != cdata[data_size - 1]) )
+      return NULL; /* malformed */
+    tlsa = data;
+    if (0 == GNUNET_asprintf (&tlsa_str, 
+                             "%c %c %c %s",
+                             tlsa->usage,
+                             tlsa->selector,
+                             tlsa->matching_type,
+                             (const char *) &tlsa[1]))
     {
-        GNUNET_free (tlsa_str);
-        return NULL;
+      GNUNET_free (tlsa_str);
+      return NULL;
     }
     return tlsa_str;
   default:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]