-fix tld guessing code
[oweals/gnunet.git] / src / gns / gnunet-service-gns_resolver.c
index c32aca84f82b56e5d6cc45642eb6d38e4e0e152a..11ea5a993d233e26b5a20f7b9a893aa158e373cc 100644 (file)
@@ -35,6 +35,7 @@
 #include "gnunet_dnsparser_lib.h"
 #include "gns_protocol.h"
 #include "gnunet_gns_service.h"
+#include "gns_common.h"
 #include "block_gns.h"
 #include "gns.h"
 #include "gnunet-service-gns_resolver.h"
@@ -176,38 +177,51 @@ is_srv (char* name)
 }
 
 /**
- * Determine if this name is canonical.
- * i.e.
+ * Determine if this name is canonical (is a legal name in a zone, without delegation);
+ * note that we do not test that the name does not contain illegal characters, we only
+ * test for delegation.  Note that service records (i.e. _foo._srv) are canonical names
+ * even though they consist of multiple labels.
+ *
+ * Examples:
  * a.b.gads  = not canonical
- * a           = canonical
+ * a         = canonical
+ * _foo._srv = canonical
+ * _f.bar    = not canonical
  *
  * @param name the name to test
  * @return GNUNET_YES if canonical
  */
 static int
-is_canonical (char* name)
+is_canonical (const char* name)
 {
-  char* ndup;
-  char* tok;
-
-  ndup = GNUNET_strdup (name);
-  strtok (ndup, ".");
+  const char *pos;
+  const char *dot;
 
-  for (tok = strtok (NULL, "."); tok != NULL; tok = strtok (NULL, "."))
-  {
-    /*
-     * probably srv
-     */
-    if (*tok == '_')
-      continue;
-    GNUNET_free (ndup);
+  if (NULL == strchr (name, '.'))
+    return GNUNET_YES;
+  if ('_' != name[0])
     return GNUNET_NO;
-  }
-  GNUNET_free (ndup);
+  pos = &name[1];
+  while (NULL != (dot = strchr (pos, '.')))    
+    if ('_' != dot[1])
+      return GNUNET_NO;
+    else
+      pos = dot + 1;
   return GNUNET_YES;
 }
 
 
+static void
+free_get_pseu_authority_handle (struct GetPseuAuthorityHandle *gph)
+{
+  gph->namestore_task = NULL;
+  GNUNET_free (gph->auth);
+  GNUNET_CRYPTO_rsa_key_free (gph->key);
+  GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
+  GNUNET_free (gph);
+}
+
+
 /**
  * Callback that shortens authorities
  *
@@ -228,13 +242,9 @@ static void
 create_pkey_cont (void* cls, int32_t success, const char* emsg)
 {
   //FIXME do sth with error
-  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+  struct GetPseuAuthorityHandle* gph = cls;
 
-  gph->namestore_task = NULL;
-  GNUNET_free (gph->auth);
-  GNUNET_CRYPTO_rsa_key_free (gph->key);
-  GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-  GNUNET_free (gph);
+  free_get_pseu_authority_handle (gph);
 }
 
 
@@ -252,13 +262,13 @@ create_pkey_cont (void* cls, int32_t success, const char* emsg)
  */
 static void
 process_pseu_lookup_ns (void* cls,
-                      const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
-                      struct GNUNET_TIME_Absolute expiration,
-                      const char *name, unsigned int rd_count,
-                      const struct GNUNET_NAMESTORE_RecordData *rd,
-                      const struct GNUNET_CRYPTO_RsaSignature *signature)
+                       const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
+                       struct GNUNET_TIME_Absolute expiration,
+                       const char *name, unsigned int rd_count,
+                       const struct GNUNET_NAMESTORE_RecordData *rd,
+                       const struct GNUNET_CRYPTO_RsaSignature *signature)
 {
-  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+  struct GetPseuAuthorityHandle* gph = cls;
   struct GNUNET_NAMESTORE_RecordData new_pkey;
 
   gph->namestore_task = NULL;
@@ -266,10 +276,7 @@ process_pseu_lookup_ns (void* cls,
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "GNS_AUTO_PSEU: Name %s already taken in NS!\n", name);
-    GNUNET_free (gph->auth);
-    GNUNET_CRYPTO_rsa_key_free (gph->key);
-    GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-    GNUNET_free (gph);
+    free_get_pseu_authority_handle (gph);
     return;
   }
 
@@ -285,11 +292,11 @@ process_pseu_lookup_ns (void* cls,
                  | GNUNET_NAMESTORE_RF_PRIVATE
                  | GNUNET_NAMESTORE_RF_PENDING;
   gph->namestore_task = GNUNET_NAMESTORE_record_create (namestore_handle,
-                                  gph->key,
-                                  gph->test_name,
-                                  &new_pkey,
-                                  &create_pkey_cont, //cont
-                                  gph); //cls
+                                                       gph->key,
+                                                       gph->test_name,
+                                                       &new_pkey,
+                                                       &create_pkey_cont, 
+                                                       gph);
 }
 
 /**
@@ -305,15 +312,11 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph, char* name)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "GNS_AUTO_PSEU: No PSEU, no shorten. Finished.\n");
-    GNUNET_free (gph->auth);
-    GNUNET_CRYPTO_rsa_key_free (gph->key);
-    GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-    GNUNET_free (gph);
+    free_get_pseu_authority_handle (gph);
     return;
   }
   
-  memcpy (gph->test_name, name, strlen(name)+1);
-
+  memcpy (gph->test_name, name, strlen(name) + 1);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "GNS_AUTO_PSEU: Checking %s for collision in NS\n",
               gph->test_name);
@@ -321,13 +324,14 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph, char* name)
    * Check for collision
    */
   gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
-                                  &gph->our_zone,
-                                  gph->test_name,
-                                  GNUNET_NAMESTORE_TYPE_ANY,
-                                  &process_pseu_lookup_ns,
-                                  gph);
+                                                       &gph->our_zone,
+                                                       gph->test_name,
+                                                       GNUNET_NAMESTORE_TYPE_ANY,
+                                                       &process_pseu_lookup_ns,
+                                                       gph);
 }
 
+
 /**
  * Handle timeout for dht request
  *
@@ -375,7 +379,7 @@ process_auth_discovery_dht_result (void* cls,
 {
   struct GetPseuAuthorityHandle* gph = cls;
   struct GNSNameRecordBlock *nrb;
-  char* rd_data = (char*)data;
+  const char* rd_data = data;
   char* name;
   int num_records;
   size_t rd_size;
@@ -389,14 +393,11 @@ process_auth_discovery_dht_result (void* cls,
   gph->get_handle = NULL;
   GNUNET_SCHEDULER_cancel (gph->timeout);
   
-  if (data == NULL)
+  if (NULL == data)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "GNS_GET_AUTH: got dht result null!\n", size);
-    GNUNET_free (gph->auth);
-    GNUNET_CRYPTO_rsa_key_free (gph->key);
-    GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-    GNUNET_free (gph);
+    free_get_pseu_authority_handle (gph);
     return;
   }
   
@@ -457,30 +458,19 @@ process_auth_discovery_ns_result (void* cls,
                       const struct GNUNET_CRYPTO_RsaSignature *signature)
 {
   struct GetPseuAuthorityHandle* gph = cls;
-  struct GNUNET_CRYPTO_ShortHashCode name_hash;
   struct GNUNET_HashCode lookup_key;
-  struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
-  struct GNUNET_HashCode name_hash_double;
-  struct GNUNET_HashCode zone_hash_double;
-  int i;
+  unsigned int i;
   uint32_t xquery;
   
   gph->namestore_task = NULL;
   /* no pseu found */
   if (0 == rd_count)
   {
-    /**
-     * check dht
-     */
-    GNUNET_CRYPTO_short_hash ("+", strlen ("+"), &name_hash);
-    GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
-    GNUNET_CRYPTO_short_hash_double (&gph->auth->zone, &zone_hash_double);
-    GNUNET_CRYPTO_hash_xor (&name_hash_double, &zone_hash_double, &lookup_key);
-    GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
-
+    GNUNET_GNS_get_key_for_record (GNUNET_GNS_TLD_PLUS, &gph->auth->zone, &lookup_key);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
-               "+", (char*)&lookup_key_string);
+               "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
+               GNUNET_GNS_TLD_PLUS, 
+               GNUNET_h2s (&lookup_key));
 
     gph->timeout = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
                                          &handle_auth_discovery_timeout, gph);
@@ -503,7 +493,7 @@ process_auth_discovery_ns_result (void* cls,
 
   for (i=0; i < rd_count; i++)
   {
-    if (0 != (strcmp (name, "+")))
+    if (0 != (strcmp (name, GNUNET_GNS_TLD_PLUS)))
       continue;
 
     if (rd[i].record_type != GNUNET_GNS_RECORD_PSEU)
@@ -553,12 +543,9 @@ process_zone_to_name_discover (void *cls,
     return;
   }
   /* we found a match in our own zone */
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
-  GNUNET_free (gph->auth);
-  GNUNET_CRYPTO_rsa_key_free (gph->key);
-  GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-  GNUNET_free (gph);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
+  free_get_pseu_authority_handle (gph);
 }
 
 
@@ -583,27 +570,25 @@ shorten_authority_chain (struct GetPseuAuthorityHandle *gph)
 
 }
 
+
 static void
 start_shorten (struct AuthorityChain *auth,
-               struct GNUNET_CRYPTO_RsaPrivateKey *key)
+               const struct GNUNET_CRYPTO_RsaPrivateKey *key)
 {
   struct GetPseuAuthorityHandle *gph;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pb_key;
   
   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
-  pb_key = GNUNET_CRYPTO_rsa_encode_key (key);
-
-  if (NULL == pb_key)
+  if (NULL == (pb_key = GNUNET_CRYPTO_rsa_encode_key (key)))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Failed to encode RSA key on shorten\n");
     return;
   }
-
   gph = GNUNET_malloc (sizeof (struct GetPseuAuthorityHandle));
-  gph->key = GNUNET_CRYPTO_rsa_decode_key ((char*)pb_key, ntohs (pb_key->len));
-
+  gph->key = GNUNET_CRYPTO_rsa_decode_key ((const char*) pb_key, ntohs (pb_key->len));
+  GNUNET_free (pb_key);
   if (NULL == gph->key)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -640,9 +625,8 @@ gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
                   unsigned long long max_bg_queries,
                   int ignore_pending)
 {
-  if (NULL == nh)
-    return GNUNET_SYSERR;
-  if (NULL == dh)
+  if ( (NULL == nh) ||
+       (NULL == dh) )
     return GNUNET_SYSERR;
   
   cfg = c;
@@ -655,16 +639,7 @@ gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
   max_allowed_background_queries = max_bg_queries;
   max_allowed_ns_tasks = GNUNET_GNS_MAX_NS_TASKS;
-  ignore_pending_records = ignore_pending;
-  gph_head = NULL;
-  gph_tail = NULL;
-  rlh_head = NULL;
-  rlh_tail = NULL;
-  nsh_head = NULL;
-  nsh_tail = NULL;
-  nah_head = NULL;
-  nah_tail = NULL;
-  
+  ignore_pending_records = ignore_pending; 
   GNUNET_RESOLVER_connect (cfg);
   return GNUNET_OK;
 }
@@ -686,17 +661,12 @@ cleanup_pending_ns_tasks (void* cls,
                           GNUNET_CONTAINER_HeapCostType cost)
 {
   struct NamestoreBGTask *nbg = element;
-  ResolverCleanupContinuation cont = cls;
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_CLEANUP: Terminating ns task\n");
   GNUNET_NAMESTORE_cancel (nbg->qe);
 
   GNUNET_CONTAINER_heap_remove_node (node);
-
-  if (0 == GNUNET_CONTAINER_heap_get_size (ns_task_heap))
-    cont ();
-
   return GNUNET_YES;
 }
 
@@ -733,7 +703,6 @@ cleanup_pending_background_queries (void* cls,
                                     GNUNET_CONTAINER_HeapCostType cost)
 {
   struct ResolverHandle *rh = element;
-  ResolverCleanupContinuation cont = cls;
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_CLEANUP-%llu: Terminating background lookup for %s\n",
@@ -741,17 +710,10 @@ cleanup_pending_background_queries (void* cls,
   GNUNET_CONTAINER_heap_remove_node (node);
   if (0 == GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
   {
-    if (GNUNET_CONTAINER_heap_get_size (ns_task_heap) == 0)
-      cont ();
-    else
-    {
-      GNUNET_CONTAINER_heap_iterate (ns_task_heap,
-                                     &cleanup_pending_ns_tasks,
-                                     cont);
-    }
+    GNUNET_CONTAINER_heap_iterate (ns_task_heap,
+                                  &cleanup_pending_ns_tasks,
+                                  NULL);    
   }
-
-
   return GNUNET_YES;
 }
 
@@ -824,33 +786,35 @@ finish_shorten (struct ResolverHandle *rh,
 static void
 finish_get_auth (struct ResolverHandle *rh,
                  struct GetNameAuthorityHandle* rlh);
+
+
 /**
  * Shutdown resolver
  */
 void
-gns_resolver_cleanup (ResolverCleanupContinuation cont)
+gns_resolver_cleanup ()
 {
   unsigned int s;
   struct GetPseuAuthorityHandle *tmp;
 
-  
-  tmp = gph_head;
-  for (tmp = gph_head; tmp != NULL; tmp = gph_head)
+  while (NULL != (tmp = gph_head))
   {
     if (tmp->get_handle != NULL)
+    {
       GNUNET_DHT_get_stop (tmp->get_handle);
-    tmp->get_handle = NULL;
+      tmp->get_handle = NULL;
+    }
     if (tmp->timeout != GNUNET_SCHEDULER_NO_TASK)
+    {
       GNUNET_SCHEDULER_cancel (tmp->timeout);
-    tmp->timeout = GNUNET_SCHEDULER_NO_TASK;
-
+      tmp->timeout = GNUNET_SCHEDULER_NO_TASK;
+    }
     if (NULL != tmp->namestore_task)
+    {
       GNUNET_NAMESTORE_cancel (tmp->namestore_task);
-    tmp->namestore_task = NULL;
-    GNUNET_free (tmp->auth);
-    GNUNET_CRYPTO_rsa_key_free (tmp->key);
-    GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, tmp);
-    GNUNET_free (tmp);
+      tmp->namestore_task = NULL;
+    }
+    free_get_pseu_authority_handle (tmp);
   }
 
   while (NULL != rlh_head)
@@ -872,15 +836,13 @@ gns_resolver_cleanup (ResolverCleanupContinuation cont)
   if (0 != s)
     GNUNET_CONTAINER_heap_iterate (dht_lookup_heap,
                                    &cleanup_pending_background_queries,
-                                   cont);
+                                   NULL);
   else if (0 != GNUNET_CONTAINER_heap_get_size (ns_task_heap))
   {
     GNUNET_CONTAINER_heap_iterate (ns_task_heap,
                                    &cleanup_pending_ns_tasks,
-                                   cont);
+                                   NULL);
   }
-  else
-    cont ();
 }
 
 
@@ -1151,23 +1113,14 @@ static void
 resolve_record_dht (struct ResolverHandle *rh)
 {
   uint32_t xquery;
-  struct GNUNET_CRYPTO_ShortHashCode name_hash;
   struct GNUNET_HashCode lookup_key;
-  struct GNUNET_HashCode name_hash_double;
-  struct GNUNET_HashCode zone_hash_double;
-  struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
   struct RecordLookupHandle *rlh = rh->proc_cls;
   struct ResolverHandle *rh_heap_root;
 
-  GNUNET_CRYPTO_short_hash (rh->name, strlen (rh->name), &name_hash);
-  GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
-  GNUNET_CRYPTO_short_hash_double (&rh->authority, &zone_hash_double);
-  GNUNET_CRYPTO_hash_xor (&name_hash_double, &zone_hash_double, &lookup_key);
-  GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
-
+  GNUNET_GNS_get_key_for_record (rh->name, &rh->authority, &lookup_key);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "GNS_PHASE_REC-%llu: starting dht lookup for %s with key: %s\n",
-              rh->id, rh->name, (char*)&lookup_key_string);
+              rh->id, rh->name, GNUNET_h2s (&lookup_key));
 
   //rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   rh->dht_heap_node = NULL;
@@ -2215,10 +2168,9 @@ process_delegation_result_dht(void* cls,
   uint32_t num_records;
   char* name = NULL;
   char* rd_data = (char*) data;
-  int i;
+  uint32_t i;
   int rd_size;
-  struct GNUNET_CRYPTO_ShortHashCode zone, name_hash;
-  struct GNUNET_HashCode zone_hash_double, name_hash_double;
+  struct GNUNET_CRYPTO_ShortHashCode zone;
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n", rh->id);
@@ -2325,13 +2277,9 @@ process_delegation_result_dht(void* cls,
       }
 
     }
+    GNUNET_GNS_get_zone_from_key (name, key, &zone);
 
 
-    GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
-    GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
-    GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double);
-    GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, &zone);
-
     /* Save to namestore
     if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
                                           &zone))
@@ -2826,21 +2774,12 @@ static void
 resolve_delegation_dht(struct ResolverHandle *rh)
 {
   uint32_t xquery;
-  struct GNUNET_CRYPTO_ShortHashCode name_hash;
-  struct GNUNET_HashCode name_hash_double;
-  struct GNUNET_HashCode zone_hash_double;
   struct GNUNET_HashCode lookup_key;
   struct ResolverHandle *rh_heap_root;
   
   pop_tld(rh->name, rh->authority_name);
 
-  //FIXME handle return values here
-  GNUNET_CRYPTO_short_hash(rh->authority_name,
-                     strlen(rh->authority_name),
-                     &name_hash);
-  GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
-  GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
-  GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
+  GNUNET_GNS_get_key_for_record (rh->authority_name, &rh->authority, &lookup_key);
   
   rh->dht_heap_node = NULL;
 
@@ -4217,9 +4156,9 @@ gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Cannot convert ZKEY %s to hash!\n", nzkey);
+      GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
       GNUNET_free (rh);
       GNUNET_free (nsh);
-      GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
       proc (proc_cls, name);
       return;
     }
@@ -4247,9 +4186,9 @@ gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
   else
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown TLD in %s\n", name);
+    GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
     GNUNET_free (rh);
     GNUNET_free (nsh);
-    GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
     proc (proc_cls, name);
     return;
   }