-fixes, auto_import_pkey imlpl
[oweals/gnunet.git] / src / gns / gnunet-service-gns_resolver.c
index 3a94556b734262a135533b452a65d8e8420e33cd..e95030db670589c81401c16c625be65d96a5cbf0 100644 (file)
 /**
  * Our handle to the namestore service
  */
-struct GNUNET_NAMESTORE_Handle *namestore_handle;
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
 
 /**
  * Resolver handle to the dht
  */
-struct GNUNET_DHT_Handle *dht_handle;
+static struct GNUNET_DHT_Handle *dht_handle;
 
 /**
- * Connects resolver to the dht
+ * Namestore calls this function if we have record for this name.
+ * (or with rd_count=0 to indicate no matches)
  *
+ * @param cls the pending query
+ * @param key the key of the zone we did the lookup
+ * @param expiration expiration date of the namestore entry
+ * @param name the name for which we need an authority
+ * @param rd_count the number of records with 'name'
+ * @param rd the record data
+ * @param signature the signature of the authority for the record data
+ */
 static void
-connect_to_dht()
+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)
 {
-  //FIXME
+  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+  struct GNUNET_NAMESTORE_RecordData new_pkey;
+
+  if (rd_count > 0)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "Name %s already taken in NS!\n", name);
+    if (0 == strcmp(gph->name, name))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "Intelligent replacement not implemented\n", name);
+      GNUNET_free(gph);
+      return;
+    }
+
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "Trying delegated name %s\n", gph->name);
+    memcpy(gph->new_name, gph->name, strlen(gph->name)+1);
+    GNUNET_NAMESTORE_lookup_record(namestore_handle,
+                                   &gph->zone,
+                                   gph->new_name,
+                                   GNUNET_GNS_RECORD_PSEU,
+                                   &process_pseu_lookup_ns,
+                                   gph);
+    return;
+  }
+
+  /** name is free */
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "Name %s not taken in NS! Adding\n", gph->new_name);
+
+  new_pkey.expiration = GNUNET_TIME_absolute_get_forever ();
+  new_pkey.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+  new_pkey.data = &gph->new_zone;
+  new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
+  GNUNET_NAMESTORE_record_create (namestore_handle,
+                                  gph->key,
+                                  gph->new_name,
+                                  &new_pkey,
+                                  NULL, //cont
+                                  NULL); //cls
+  GNUNET_free(gph);
+
+}
+
+/**
+ * process result of a dht pseu lookup
+ *
+ * @param gph the handle
+ * @param name the pseu result or NULL
+ */
+static void
+process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name)
+{
+  if (NULL == name)
+  {
+    memcpy(gph->new_name, name, strlen(gph->name)+1);
+  }
+  else
+  {
+    memcpy(gph->new_name, name, strlen(name)+1);
+  }
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "Checking %s for collision in NS\n", gph->new_name);
+
+  /**
+   * Check for collision
+   */
+  GNUNET_NAMESTORE_lookup_record(namestore_handle,
+                                 &gph->zone,
+                                 gph->new_name,
+                                 GNUNET_GNS_RECORD_PSEU,
+                                 &process_pseu_lookup_ns,
+                                 gph);
 }
-*/
+
+/**
+ * Handle timeout for dht request
+ *
+ * @param cls the request handle as closure
+ * @param tc the task context
+ */
+static void
+handle_auth_discovery_timeout(void *cls,
+                              const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "dht lookup for query PSEU timed out.\n");
+  GNUNET_DHT_get_stop (gph->get_handle);
+  process_pseu_result(gph, NULL);
+}
+
+/**
+ * Function called when we find a PSEU entry in the DHT
+ *
+ * @param cls the request handle
+ * @param exp lifetime
+ * @param key the key the record was stored under
+ * @param get_path get path
+ * @param get_path_length get path length
+ * @param put_path put path
+ * @param put_path_length put path length
+ * @param type the block type
+ * @param size the size of the record
+ * @param data the record data
+ */
+static void
+process_auth_discovery_dht_result(void* cls,
+                                  struct GNUNET_TIME_Absolute exp,
+                                  const GNUNET_HashCode * key,
+                                  const struct GNUNET_PeerIdentity *get_path,
+                                  unsigned int get_path_length,
+                                  const struct GNUNET_PeerIdentity *put_path,
+                                  unsigned int put_path_length,
+                                  enum GNUNET_BLOCK_Type type,
+                                  size_t size, const void *data)
+{
+  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+  struct GNSNameRecordBlock *nrb;
+  char* rd_data = (char*)data;
+  char* name;
+  int num_records;
+  size_t rd_size;
+  int i;
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
+
+  if (data == NULL)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "got dht result null!\n", size);
+    GNUNET_break(0);
+    GNUNET_free(gph);
+    return;
+  }
+  
+  nrb = (struct GNSNameRecordBlock*)data;
+
+  /* stop lookup and timeout task */
+  GNUNET_DHT_get_stop (gph->get_handle);
+  GNUNET_SCHEDULER_cancel(gph->dht_timeout);
+
+  gph->get_handle = NULL;
+
+  nrb = (struct GNSNameRecordBlock*)data;
+  
+  name = (char*)&nrb[1];
+  num_records = ntohl(nrb->rd_count);
+  {
+    struct GNUNET_NAMESTORE_RecordData rd[num_records];
+
+    rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
+    rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
+
+    if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
+                                                               rd_data,
+                                                               num_records,
+                                                               rd))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
+      GNUNET_break(0);
+      GNUNET_free(gph);
+      return;
+    }
+
+    for (i=0; i<num_records; i++)
+    {
+      if ((strcmp(name, "+") == 0) &&
+          (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
+      {
+        /* found pseu */
+        process_pseu_result(gph, (char*)rd[i].data);
+        return;
+      }
+    }
+  }
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "no pseu in dht!\n");
+  process_pseu_result(gph, NULL);
+}
+
+/**
+ * Callback called by namestore for a zone to name
+ * result
+ *
+ * @param cls the closure
+ * @param zone_key the zone we queried
+ * @param expire the expiration time of the name
+ * @param name the name found or NULL
+ * @param rd_len number of records for the name
+ * @param rd the record data (PKEY) for the name
+ * @param signature the signature for the record data
+ */
+static void
+process_zone_to_name_discover(void *cls,
+                 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+                 struct GNUNET_TIME_Absolute expire,
+                 const char *name,
+                 unsigned int rd_len,
+                 const struct GNUNET_NAMESTORE_RecordData *rd,
+                 const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+
+  /* we found a match in our own zone */
+  if (rd_len != 0)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "name for zone in our root %d\n", strlen(name));
+    GNUNET_free(gph);
+  }
+  else
+  {
+    /**
+     * No name found.
+     * check dht
+     */
+    uint32_t xquery;
+    struct GNUNET_CRYPTO_ShortHashCode name_hash;
+    GNUNET_HashCode lookup_key;
+    struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
+    GNUNET_HashCode name_hash_double;
+    GNUNET_HashCode zone_hash_double;
+
+    GNUNET_CRYPTO_short_hash("+", strlen("+"), &name_hash);
+    GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
+    GNUNET_CRYPTO_short_hash_double (&gph->new_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_log(GNUNET_ERROR_TYPE_DEBUG,
+               "starting dht lookup for %s with key: %s\n",
+               "+", (char*)&lookup_key_string);
+
+    gph->dht_timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
+                                         &handle_auth_discovery_timeout, gph);
+
+    xquery = htonl(GNUNET_GNS_RECORD_PSEU);
+
+    gph->get_handle = GNUNET_DHT_get_start(dht_handle,
+                                           DHT_OPERATION_TIMEOUT,
+                                           GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+                                           &lookup_key,
+                                           DHT_GNS_REPLICATION_LEVEL,
+                                           GNUNET_DHT_RO_NONE,
+                                           &xquery,
+                                           sizeof(xquery),
+                                           &process_auth_discovery_dht_result,
+                                           gph);
+
+  }
+}
+
+
+/**
+ * Callback for new authories
+ *
+ * @param name the name given by delegation
+ * @param zone the authority
+ * @param the private key of our authority
+ */
+static void process_discovered_authority(char* name,
+                                    struct GNUNET_CRYPTO_ShortHashCode zone,
+                                    struct GNUNET_CRYPTO_ShortHashCode our_zone,
+                                    struct GNUNET_CRYPTO_RsaPrivateKey *key)
+{
+  struct GetPseuAuthorityHandle *gph;
+  size_t namelen;
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New authority %s discovered\n",
+             name);
+
+  gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle));
+  namelen = strlen(name) + 1;
+  memcpy(gph->name, name, namelen);
+  
+  gph->new_zone = zone;
+  gph->zone = our_zone;
+  gph->key = key;
+
+  GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+                                 &our_zone,
+                                 &gph->new_zone,
+                                 &process_zone_to_name_discover,
+                                 gph);
+
+}
+
+/**
+ * Initialize the resolver
+ *
+ * @param nh the namestore handle
+ * @param dh the dht handle
+ * @return GNUNET_OK on success
+ */
+int
+gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
+                  struct GNUNET_DHT_Handle *dh)
+{
+  namestore_handle = nh;
+  dht_handle = dh;
+  if ((namestore_handle != NULL) && (dht_handle != NULL))
+  {
+    return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
 
 /**
  * Helper function to free resolver handle
@@ -78,15 +399,11 @@ free_resolver_handle(struct ResolverHandle* rh)
   if (NULL == rh)
     return;
 
-  GNUNET_free_non_null (rh->name);
-  GNUNET_free_non_null (rh->authority_name);
-
   ac = rh->authority_chain_head;
 
   while (NULL != ac)
   {
     ac_next = ac->next;
-    GNUNET_free_non_null (ac->name);
     GNUNET_free(ac);
     ac = ac_next;
   }
@@ -178,7 +495,6 @@ process_record_result_dht(void* cls,
   int i;
   int rd_size;
   
-  GNUNET_HashCode zone, name_hash;
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
   
   if (data == NULL)
@@ -232,9 +548,6 @@ process_record_result_dht(void* cls,
 
     }
 
-    GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
-    GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
-  
     /**
      * FIXME check pubkey against existing key in namestore?
      * https://gnunet.org/bugs/view.php?id=2179
@@ -270,13 +583,17 @@ static void
 resolve_record_dht(struct ResolverHandle *rh)
 {
   uint32_t xquery;
-  GNUNET_HashCode name_hash;
+  struct GNUNET_CRYPTO_ShortHashCode name_hash;
   GNUNET_HashCode lookup_key;
+  GNUNET_HashCode name_hash_double;
+  GNUNET_HashCode zone_hash_double;
   struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
   struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
-
-  GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash);
-  GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
+  
+  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_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -324,11 +641,11 @@ process_record_result_ns(void* cls,
   struct ResolverHandle *rh;
   struct RecordLookupHandle *rlh;
   struct GNUNET_TIME_Relative remaining_time;
-  GNUNET_HashCode zone;
+  struct GNUNET_CRYPTO_ShortHashCode zone;
 
   rh = (struct ResolverHandle *) cls;
   rlh = (struct RecordLookupHandle *)rh->proc_cls;
-  GNUNET_CRYPTO_hash(key,
+  GNUNET_CRYPTO_short_hash(key,
                      sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                      &zone);
   remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
@@ -371,7 +688,7 @@ process_record_result_ns(void* cls,
     int i;
     for (i=0; i<rd_count;i++)
     {
-      
+
       if (rd[i].record_type != rlh->record_type)
         continue;
       
@@ -497,7 +814,8 @@ process_delegation_result_dht(void* cls,
   char* rd_data = (char*) data;
   int i;
   int rd_size;
-  GNUNET_HashCode zone, name_hash;
+  struct GNUNET_CRYPTO_ShortHashCode zone, name_hash;
+  GNUNET_HashCode zone_hash_double, name_hash_double;
   
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n");
 
@@ -551,26 +869,34 @@ process_delegation_result_dht(void* cls,
       {
         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
         rh->answered = 1;
-        memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
+        memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
         struct AuthorityChain *auth =
           GNUNET_malloc(sizeof(struct AuthorityChain));
         auth->zone = rh->authority;
-        auth->name = GNUNET_malloc(strlen(rh->authority_name)+1);
         memset(auth->name, 0, strlen(rh->authority_name)+1);
         strcpy(auth->name, rh->authority_name);
         GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
                                      rh->authority_chain_tail,
                                      auth);
+
+        /** try to import pkey if private key available */
+        if (rh->priv_key)
+          process_discovered_authority(name, auth->zone,
+                                       rh->authority_chain_tail->zone,
+                                       rh->priv_key);
       }
 
     }
 
 
-    GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
-    GNUNET_CRYPTO_hash_xor(key, &name_hash, &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_hash_cmp(&rh->authority_chain_tail->zone, &zone))
+    if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone,
+                                          &zone))
     {
       GNUNET_NAMESTORE_record_put (namestore_handle,
                                  &nrb->public_key,
@@ -597,15 +923,118 @@ process_delegation_result_dht(void* cls,
       resolve_delegation_dht(rh);
     return;
   }
-
+  
   /**
-   * should never get here unless false dht key/put
-   * block plugin should handle this
-   **/
-  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "DHT authority lookup error!\n");
-  GNUNET_break(0);
+   * No pkey but name exists
+   */
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup found no match!\n");
+  rh->proc(rh->proc_cls, rh, 0, NULL);
 }
 
+/**
+ * finish lookup
+ */
+static void
+finish_lookup(struct ResolverHandle *rh,
+              struct RecordLookupHandle* rlh,
+              unsigned int rd_count,
+              const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+  int i;
+  char* s_value;
+  char new_s_value[256];
+  char new_mx_value[sizeof(struct GNUNET_DNSPARSER_MxRecord)+256];
+  int s_len;
+  struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
+  char* pos;
+  char* trailer;
+  struct GNUNET_DNSPARSER_MxRecord *mx;
+
+  if (rd_count > 0)
+    memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
+
+  for (i = 0; i < rd_count; i++)
+  {
+
+    if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
+        rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
+        rd[i].record_type != GNUNET_GNS_RECORD_MX)
+    {
+      p_rd[i].data = rd[i].data;
+      continue;
+    }
+
+    /**
+     * for all those records we 'should'
+     * also try to resolve the A/AAAA records (RFC1035)
+     * FIXME
+     */
+    if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
+    {
+      mx = (struct GNUNET_DNSPARSER_MxRecord*)rd[i].data;
+      s_value = (char*)&mx[1];
+    }
+    else
+    {
+      s_value = (char*)rd[i].data;
+    }
+    
+    s_len = strlen(s_value)+1;
+
+    if (s_len < 3)
+    {
+      /* no postprocessing */
+      p_rd[i].data = rd[i].data;
+      continue;
+    }
+
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "Postprocessing %s\n", s_value);
+
+    if (0 == strcmp(s_value+s_len-3, ".+"))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "Expanding .+ in %s\n", s_value);
+      if (strcmp(rh->name, "+") == 0)
+      {
+        trailer = rlh->name;
+      }
+      else
+      {
+        trailer = rlh->name+strlen(rh->name)+1;
+      }
+      memset(new_s_value, 0, s_len+strlen(trailer)+strlen(GNUNET_GNS_TLD));
+      strcpy(new_s_value, s_value);
+      pos = new_s_value+s_len-2;
+      strcpy(pos, trailer);
+      pos += strlen(trailer);
+      if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
+      {
+
+        p_rd[i].data_size = sizeof(struct GNUNET_DNSPARSER_MxRecord)
+          +strlen(new_s_value)+1;
+        
+        p_rd[i].data = new_mx_value;
+        mx = (struct GNUNET_DNSPARSER_MxRecord*)p_rd[i].data;
+        mx->preference =
+          ((struct GNUNET_DNSPARSER_MxRecord*)rd[i].data)->preference;
+        memcpy((char*)&mx[1], new_s_value, strlen(new_s_value)+1);
+        mx->mxhost = (char*)&mx[1];
+      }
+      else
+      {
+        p_rd[i].data = new_s_value;
+        p_rd[i].data_size = strlen(new_s_value)+1;
+      }
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "Expanded to %s\n", new_s_value);
+    }
+  }
+
+  rlh->proc(rlh->proc_cls, rd_count, p_rd);
+  GNUNET_free(rlh);
+  
+}
 
 /**
  * Process DHT lookup result for record.
@@ -621,6 +1050,7 @@ handle_record_dht(void* cls, struct ResolverHandle *rh,
                        const struct GNUNET_NAMESTORE_RecordData *rd)
 {
   struct RecordLookupHandle* rlh;
+
   rlh = (struct RecordLookupHandle*)cls;
   if (rd_count == 0)
   {
@@ -628,9 +1058,7 @@ handle_record_dht(void* cls, struct ResolverHandle *rh,
                "No records for %s found in DHT. Aborting\n",
                rh->name);
     /* give up, cannot resolve */
-    rlh->proc(rlh->proc_cls, 0, NULL);
-    GNUNET_free(rlh->name);
-    GNUNET_free(rlh);
+    finish_lookup(rh, rlh, 0, NULL);
     free_resolver_handle(rh);
     return;
   }
@@ -638,9 +1066,8 @@ handle_record_dht(void* cls, struct ResolverHandle *rh,
   /* results found yay */
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "Record resolved from DHT!");
-  rlh->proc(rlh->proc_cls, rd_count, rd);
-  GNUNET_free(rlh->name);
-  GNUNET_free(rlh);
+
+  finish_lookup(rh, rlh, rd_count, rd);
   free_resolver_handle(rh);
 
 }
@@ -665,17 +1092,15 @@ handle_record_ns(void* cls, struct ResolverHandle *rh,
   {
     /* ns entry expired and not ours. try dht */
     if (rh->status & (EXPIRED | !EXISTS) &&
-        GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
-                               &rh->authority_chain_tail->zone))
+        GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+                                     &rh->authority_chain_tail->zone))
     {
       rh->proc = &handle_record_dht;
       resolve_record_dht(rh);
       return;
     }
     /* give up, cannot resolve */
-    rlh->proc(rlh->proc_cls, 0, NULL);
-    GNUNET_free(rlh->name);
-    GNUNET_free(rlh);
+    finish_lookup(rh, rlh, 0, NULL);
     free_resolver_handle(rh);
     return;
   }
@@ -683,9 +1108,8 @@ handle_record_ns(void* cls, struct ResolverHandle *rh,
   /* results found yay */
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "Record resolved from namestore!");
-  rlh->proc(rlh->proc_cls, rd_count, rd);
-  GNUNET_free(rlh->name);
-  GNUNET_free(rlh);
+
+  finish_lookup(rh, rlh, rd_count, rd);
   free_resolver_handle(rh);
 
 }
@@ -748,6 +1172,32 @@ pop_tld(char* name, char* dest)
   strcpy(dest, (name+len+1));
 }
 
+/**
+ * Checks if name is in tld
+ *
+ * @param name the name to check
+ * @return GNUNET_YES or GNUNET_NO
+ */
+int
+is_tld(const char* name, const char* tld)
+{
+  int offset = 0;
+
+  if (strlen(name) <= strlen(tld))
+  {
+    return GNUNET_NO;
+  }
+  
+  offset = strlen(name)-strlen(tld);
+  if (strcmp(name+offset, tld) != 0)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+               "%s is not in .%s TLD\n", name, tld);
+    return GNUNET_NO;
+  }
+  return GNUNET_YES;
+}
+
 /**
  * DHT resolution for delegation finished. Processing result.
  *
@@ -766,9 +1216,18 @@ handle_delegation_dht(void* cls, struct ResolverHandle *rh,
   
   if (strcmp(rh->name, "") == 0)
   {
+    if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "Resolved queried PKEY via DHT.\n");
+      finish_lookup(rh, rlh, rd_count, rd);
+      free_resolver_handle(rh);
+      return;
+    }
     /* We resolved full name for delegation. resolving record */
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
       "Resolved full name for delegation via DHT. resolving record '' in ns\n");
+    strcpy(rh->name, "+\0");
     rh->proc = &handle_record_ns;
     resolve_record_ns(rh);
     return;
@@ -789,9 +1248,7 @@ handle_delegation_dht(void* cls, struct ResolverHandle *rh,
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "Cannot fully resolve delegation for %s via DHT!\n",
              rh->name);
-  rlh->proc(rlh->proc_cls, 0, NULL);
-  GNUNET_free(rlh->name);
-  GNUNET_free(rlh);
+  finish_lookup(rh, rlh, 0, NULL);
   free_resolver_handle(rh);
 }
 
@@ -806,13 +1263,17 @@ static void
 resolve_delegation_dht(struct ResolverHandle *rh)
 {
   uint32_t xquery;
-  GNUNET_HashCode name_hash;
+  struct GNUNET_CRYPTO_ShortHashCode name_hash;
+  GNUNET_HashCode name_hash_double;
+  GNUNET_HashCode zone_hash_double;
   GNUNET_HashCode lookup_key;
-
-  GNUNET_CRYPTO_hash(rh->authority_name,
+  
+  GNUNET_CRYPTO_short_hash(rh->authority_name,
                      strlen(rh->authority_name),
                      &name_hash);
-  GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
+  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);
 
   rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
                                                   &dht_authority_lookup_timeout,
@@ -852,9 +1313,18 @@ handle_delegation_ns(void* cls, struct ResolverHandle *rh,
   
   if (strcmp(rh->name, "") == 0)
   {
+    if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "Resolved queried PKEY in NS.\n");
+      finish_lookup(rh, rlh, rd_count, rd);
+      free_resolver_handle(rh);
+      return;
+    }
     /* We resolved full name for delegation. resolving record */
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Resolved full name for delegation. resolving record ''\n");
+               "Resolved full name for delegation. resolving record '+'\n");
+    strcpy(rh->name, "+\0");
     rh->proc = &handle_record_ns;
     resolve_record_ns(rh);
     return;
@@ -867,7 +1337,7 @@ handle_delegation_ns(void* cls, struct ResolverHandle *rh,
    * or we are authority
    **/
   if ((rh->status & (EXISTS | !EXPIRED)) ||
-      !GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
+      !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
                              &rh->authority_chain_tail->zone))
   {
     if (is_canonical(rh->name))
@@ -924,14 +1394,14 @@ process_delegation_result_ns(void* cls,
 {
   struct ResolverHandle *rh;
   struct GNUNET_TIME_Relative remaining_time;
-  GNUNET_HashCode zone;
-  char* new_name;
+  struct GNUNET_CRYPTO_ShortHashCode zone;
+  char new_name[MAX_DNS_NAME_LENGTH];
   
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n",
              rd_count);
 
   rh = (struct ResolverHandle *)cls;
-  GNUNET_CRYPTO_hash(key,
+  GNUNET_CRYPTO_short_hash(key,
                      sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                      &zone);
   remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
@@ -975,14 +1445,11 @@ process_delegation_result_ns(void* cls,
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                  "Adding %s back to %s\n",
                  rh->authority_name, rh->name);
-      new_name = GNUNET_malloc(strlen(rh->name)
-                               + strlen(rh->authority_name) + 2);
       memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
       strcpy(new_name, rh->name);
       strcpy(new_name+strlen(new_name)+1, ".");
       strcpy(new_name+strlen(new_name)+2, rh->authority_name);
-      GNUNET_free(rh->name);
-      rh->name = new_name;
+      strcpy(rh->name, new_name);
     }
     rh->proc(rh->proc_cls, rh, 0, NULL);
     return;
@@ -1020,10 +1487,9 @@ process_delegation_result_ns(void* cls,
      * Resolve rest of query with new authority
      */
     GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
-    memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
+    memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
     struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
     auth->zone = rh->authority;
-    auth->name = GNUNET_malloc(strlen(rh->authority_name)+1);
     memset(auth->name, 0, strlen(rh->authority_name)+1);
     strcpy(auth->name, rh->authority_name);
     GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
@@ -1082,41 +1548,106 @@ resolve_delegation_ns(struct ResolverHandle *rh)
  * @param cls the closure to pass to proc
  */
 void
-gns_resolver_lookup_record(GNUNET_HashCode zone,
+gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
                            uint32_t record_type,
                            const char* name,
+                           struct GNUNET_CRYPTO_RsaPrivateKey *key,
                            RecordLookupProcessor proc,
                            void* cls)
 {
   struct ResolverHandle *rh;
   struct RecordLookupHandle* rlh;
+  char string_hash[MAX_DNS_NAME_LENGTH]; //FIXME name len as soon as shorthash
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Starting resolution for %s (type=%d)!\n",
               name, record_type);
 
+  
+  if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "%s is canonical and not gnunet -> cannot resolve!\n", name);
+    proc(cls, 0, NULL);
+    return;
+  }
+  
   rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
   rh = GNUNET_malloc(sizeof (struct ResolverHandle));
 
   rh->authority = zone;
   rh->proc_cls = rlh;
-  rh->name = GNUNET_malloc(strlen(name)
-                           - strlen(GNUNET_GNS_TLD));
-  memset(rh->name, 0,
-         strlen(name)-strlen(GNUNET_GNS_TLD));
-  memcpy(rh->name, name,
-         strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
-  rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
+  rh->priv_key = key;
+  
+  if (strcmp(GNUNET_GNS_TLD, name) == 0)
+  {
+    /**
+     * Only 'gnunet' given
+     */
+    strcpy(rh->name, "\0");
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Checking for TLD...\n");
+    if (is_zkey_tld(name) == GNUNET_YES)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "TLD is zkey\n");
+      /**
+       * This is a zkey tld
+       * build hash and use as initial authority
+       */
+      memset(rh->name, 0,
+             strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
+      memcpy(rh->name, name,
+             strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
+      pop_tld(rh->name, string_hash);
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "ZKEY is %s!\n", string_hash);
+
+      if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(string_hash,
+                                                      &rh->authority))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Cannot convert ZKEY %s to hash!\n", string_hash);
+        GNUNET_free(rh);
+        GNUNET_free(rlh);
+        proc(cls, 0, NULL);
+        return;
+      }
+
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "TLD is gnunet\n");
+      /**
+       * Presumably GNUNET tld
+       */
+      memset(rh->name, 0,
+             strlen(name)-strlen(GNUNET_GNS_TLD));
+      memcpy(rh->name, name,
+             strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
+    }
+  }
+  
+  /**
+   * Initialize authority chain
+   */
   rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
   rh->authority_chain_head->prev = NULL;
   rh->authority_chain_head->next = NULL;
   rh->authority_chain_tail = rh->authority_chain_head;
-  rh->authority_chain_head->zone = zone;
-
+  rh->authority_chain_head->zone = rh->authority;
+  
+  /**
+   * Copy original query into lookup handle
+   */
   rlh->record_type = record_type;
-  rlh->name = GNUNET_malloc(strlen(name) + 1);
   memset(rlh->name, 0, strlen(name) + 1);
-  strcpy(rlh->name, name); //FIXME
+  strcpy(rlh->name, name);
   rlh->proc = proc;
   rlh->proc_cls = cls;
 
@@ -1152,8 +1683,8 @@ process_zone_to_name_shorten(void *cls,
   struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
   struct AuthorityChain *next_authority;
 
-  char* result;
-  char* next_authority_name;
+  char result[MAX_DNS_NAME_LENGTH];
+  char next_authority_name[MAX_DNS_LABEL_LENGTH];
   size_t answer_len;
   
   /* we found a match in our own zone */
@@ -1162,13 +1693,16 @@ process_zone_to_name_shorten(void *cls,
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "result strlen %d\n", strlen(name));
     answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
-    result = GNUNET_malloc(answer_len);
     memset(result, 0, answer_len);
-    strcpy(result, rh->name);
-    strcpy(result+strlen(rh->name), ".");
-    strcpy(result+strlen(rh->name)+1, name);
-    strcpy(result+strlen(rh->name)+strlen(name)+1, ".");
-    strcpy(result+strlen(rh->name)+strlen(name)+2, GNUNET_GNS_TLD);
+    if (strlen(rh->name) > 0)
+    {
+      strcpy(result, rh->name);
+      strcpy(result+strlen(rh->name), ".");
+    }
+    
+    strcpy(result+strlen(result), name);
+    strcpy(result+strlen(result), ".");
+    strcpy(result+strlen(result), GNUNET_GNS_TLD);
     
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "Sending shorten result %s\n", result);
@@ -1176,14 +1710,12 @@ process_zone_to_name_shorten(void *cls,
     nsh->proc(nsh->proc_cls, result);
     GNUNET_free(nsh);
     free_resolver_handle(rh);
-    GNUNET_free(result);
   }
-  else if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
-                                  &rh->authority_chain_tail->zone))
+  else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+                                        &rh->authority_chain_tail->zone))
   {
     /* our zone, just append .gnunet */
     answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
-    result = GNUNET_malloc(answer_len);
     memset(result, 0, answer_len);
     strcpy(result, rh->name);
     strcpy(result+strlen(rh->name), ".");
@@ -1195,7 +1727,6 @@ process_zone_to_name_shorten(void *cls,
     nsh->proc(nsh->proc_cls, result);
     GNUNET_free(nsh);
     free_resolver_handle(rh);
-    GNUNET_free(result);
   }
   else
   {
@@ -1204,16 +1735,14 @@ process_zone_to_name_shorten(void *cls,
      * continue with next authority
      */
     next_authority = rh->authority_chain_head;
-    next_authority_name = GNUNET_malloc(strlen(rh->name)+
-                             strlen(next_authority->name) + 2);
+    //                         strlen(next_authority->name) + 2);
     memset(next_authority_name, 0, strlen(rh->name)+
                       strlen(next_authority->name) + 2);
     strcpy(next_authority_name, rh->name);
     strcpy(next_authority_name+strlen(rh->name)+1, ".");
     strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name);
   
-    GNUNET_free(rh->name);
-    rh->name = next_authority_name;
+    strcpy(rh->name, next_authority_name);
     GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
                               rh->authority_chain_tail,
                               next_authority);
@@ -1243,7 +1772,7 @@ handle_delegation_ns_shorten(void* cls,
                       const struct GNUNET_NAMESTORE_RecordData *rd)
 {
   struct NameShortenHandle *nsh;
-  char* result;
+  char result[MAX_DNS_NAME_LENGTH];
   size_t answer_len;
 
   nsh = (struct NameShortenHandle *)cls;
@@ -1258,17 +1787,16 @@ handle_delegation_ns_shorten(void* cls,
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
 
-  if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
-                             &rh->authority_chain_tail->zone) == 0)
+  if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+                                   &rh->authority_chain_tail->zone) == 0)
   {
     /**
      * This is our zone append .gnunet unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
-     **/
+     */
     
     answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
-    result = GNUNET_malloc(answer_len);
     memset(result, 0, answer_len);
     strcpy(result, rh->name);
     strcpy(result+strlen(rh->name), ".");
@@ -1280,7 +1808,6 @@ handle_delegation_ns_shorten(void* cls,
     nsh->proc(nsh->proc_cls, result);
     GNUNET_free(nsh);
     free_resolver_handle(rh);
-    GNUNET_free(result);
     return;
   }
   
@@ -1302,36 +1829,84 @@ handle_delegation_ns_shorten(void* cls,
  * @param cls closure to pass to proc
  */
 void
-gns_resolver_shorten_name(GNUNET_HashCode zone,
+gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone,
                           const char* name,
                           ShortenResultProcessor proc,
                           void* cls)
 {
   struct ResolverHandle *rh;
   struct NameShortenHandle *nsh;
+  char string_hash[MAX_DNS_NAME_LENGTH]; //FIXME LABEL length when shorthash
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Starting shorten for %s!\n", name);
   
+  if (is_canonical((char*)name))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "%s is canonical. Returning verbatim\n", name);
+    proc(cls, name);
+    return;
+  }
+
   nsh = GNUNET_malloc(sizeof (struct NameShortenHandle));
+  
+
+  nsh->proc = proc;
+  nsh->proc_cls = cls;
+  
   rh = GNUNET_malloc(sizeof (struct ResolverHandle));
   rh->authority = zone;
-  rh->name = GNUNET_malloc(strlen(name)
-                           - strlen(GNUNET_GNS_TLD));
-  memset(rh->name, 0,
-         strlen(name)-strlen(GNUNET_GNS_TLD));
-  memcpy(rh->name, name,
-         strlen(name)-strlen(GNUNET_GNS_TLD)-1);
-
-  rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
+  
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Checking for TLD...\n");
+  if (is_zkey_tld(name) == GNUNET_YES)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "TLD is zkey\n");
+    /**
+     * This is a zkey tld
+     * build hash and use as initial authority
+     */
+    memset(rh->name, 0,
+           strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
+    memcpy(rh->name, name,
+           strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
+    pop_tld(rh->name, string_hash);
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "ZKEY is %s!\n", string_hash);
+
+    if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(string_hash,
+                                                          &rh->authority))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Cannot convert ZKEY %s to hash!\n", string_hash);
+      GNUNET_free(rh);
+      GNUNET_free(nsh);
+      proc(cls, name);
+      return;
+    }
+
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "TLD is gnunet\n");
+    /**
+     * Presumably GNUNET tld
+     */
+    memset(rh->name, 0,
+           strlen(name)-strlen(GNUNET_GNS_TLD));
+    memcpy(rh->name, name,
+           strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
+  }
+
   rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
   rh->authority_chain_tail = rh->authority_chain_head;
   rh->authority_chain_head->zone = zone;
   rh->proc = &handle_delegation_ns_shorten;
   rh->proc_cls = nsh;
-
-  nsh->proc = proc;
-  nsh->proc_cls = cls;
   
   /* Start delegation resolution in our namestore */
   resolve_delegation_ns(rh);
@@ -1356,7 +1931,7 @@ handle_delegation_result_ns_get_auth(void* cls,
                       const struct GNUNET_NAMESTORE_RecordData *rd)
 {
   struct GetNameAuthorityHandle* nah;
-  char* result;
+  char result[MAX_DNS_NAME_LENGTH];
   size_t answer_len;
 
   nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
@@ -1390,7 +1965,6 @@ handle_delegation_result_ns_get_auth(void* cls,
 
     answer_len = strlen(nah->name) - strlen(rh->name)
       + strlen(GNUNET_GNS_TLD) + 1;
-    result = GNUNET_malloc(answer_len);
     memset(result, 0, answer_len);
     strcpy(result, nah->name + strlen(rh->name) + 1);
 
@@ -1398,17 +1972,14 @@ handle_delegation_result_ns_get_auth(void* cls,
                "Got authority result %s\n", result);
     
     nah->proc(nah->proc_cls, result);
-    GNUNET_free(nah->name);
     GNUNET_free(nah);
     free_resolver_handle(rh);
-    GNUNET_free(result);
   }
   else
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "Unable to resolve authority for remaining %s!\n", rh->name);
     nah->proc(nah->proc_cls, "");
-    GNUNET_free(nah->name);
     GNUNET_free(nah);
     free_resolver_handle(rh);
   }
@@ -1427,7 +1998,7 @@ handle_delegation_result_ns_get_auth(void* cls,
  * @param cls the closure to pass to the processor
  */
 void
-gns_resolver_get_authority(GNUNET_HashCode zone,
+gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
                            const char* name,
                            GetAuthorityResultProcessor proc,
                            void* cls)
@@ -1441,21 +2012,23 @@ gns_resolver_get_authority(GNUNET_HashCode zone,
   nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
   rh = GNUNET_malloc(sizeof (struct ResolverHandle));
   rh->authority = zone;
+  
+  if (strcmp(GNUNET_GNS_TLD, name) == 0)
+  {
+    strcpy(rh->name, "\0");
+  }
+  else
+  {
+    memset(rh->name, 0,
+           strlen(name)-strlen(GNUNET_GNS_TLD));
+    memcpy(rh->name, name,
+           strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
+  }
 
-  rh->name = GNUNET_malloc(strlen(name)
-                           - strlen(GNUNET_GNS_TLD));
-  memset(rh->name, 0,
-         strlen(name)-strlen(GNUNET_GNS_TLD));
-  memcpy(rh->name, name,
-         strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
-
-  nah->name = GNUNET_malloc(strlen(name)+1);
   memset(nah->name, 0,
          strlen(name)+1);
   strcpy(nah->name, name);
   
-  rh->authority_name = GNUNET_malloc(MAX_DNS_LABEL_LENGTH);
-
   rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
   rh->authority_chain_tail = rh->authority_chain_head;
   rh->authority_chain_head->zone = zone;