add logic to handle SRV/DANE names (#3003 and 2526) in GNS resolver
[oweals/gnunet.git] / src / gns / gnunet-service-gns_shorten.c
index 8b69e670cf2866dfd59d4d810e100fb68010c989..34dcd42f6bf1faebc580c16e553c693af49c88c9 100644 (file)
@@ -27,6 +27,7 @@
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_dht_service.h"
+#include "gnunet_gnsrecord_lib.h"
 #include "gnunet_namestore_service.h"
 #include "gnunet_resolver_service.h"
 #include "gnunet_gns_service.h"
@@ -65,7 +66,7 @@ struct GetPseuAuthorityHandle
    * Private key of the (shorten) zone to store the resulting
    * pseudonym in.
    */
-  struct GNUNET_CRYPTO_EccPrivateKey shorten_zone_key;
+  struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_zone_key;
 
   /**
    * Original label (used if no PSEU record is found).
@@ -73,25 +74,35 @@ struct GetPseuAuthorityHandle
   char label[GNUNET_DNSPARSER_MAX_LABEL_LENGTH + 1];
 
   /**
-   * Label we are currently trying out (during #perform_pseu_lookup).
+   * Suggested label based on NICK record
+   */
+  char * suggested_label;
+
+  /**
+   * Label we are currently trying out
    */
   char *current_label;
 
   /**
    * The zone for which we are trying to find the PSEU record.
    */
-  struct GNUNET_CRYPTO_EccPublicSignKey target_zone;
+  struct GNUNET_CRYPTO_EcdsaPublicKey target_zone;
 
   /**
-   * Handle for DHT lookups. Should be NULL if no lookups are in progress 
+   * Handle for DHT lookups. Should be NULL if no lookups are in progress
    */
   struct GNUNET_DHT_GetHandle *get_handle;
 
   /**
-   * Handle to namestore request 
+   * Handle to namestore request
    */
   struct GNUNET_NAMESTORE_QueueEntry *namestore_task;
 
+  /**
+   * Handle to namecache request
+   */
+  struct GNUNET_NAMECACHE_QueueEntry *namecache_task;
+
   /**
    * Task to abort DHT lookup operation.
    */
@@ -115,6 +126,11 @@ static struct GetPseuAuthorityHandle *gph_tail;
  */
 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
 
+/**
+ * Our handle to the namecache service
+ */
+static struct GNUNET_NAMECACHE_Handle *namecache_handle;
+
 /**
  * Resolver handle to the dht
  */
@@ -139,6 +155,11 @@ free_get_pseu_authority_handle (struct GetPseuAuthorityHandle *gph)
     GNUNET_NAMESTORE_cancel (gph->namestore_task);
     gph->namestore_task = NULL;
   }
+  if (NULL != gph->namecache_task)
+  {
+    GNUNET_NAMECACHE_cancel (gph->namecache_task);
+    gph->namecache_task = NULL;
+  }
   if (GNUNET_SCHEDULER_NO_TASK != gph->timeout_task)
   {
     GNUNET_SCHEDULER_cancel (gph->timeout_task);
@@ -158,8 +179,8 @@ free_get_pseu_authority_handle (struct GetPseuAuthorityHandle *gph)
  * @param emsg unused
  */
 static void
-create_pkey_cont (void* cls, 
-                 int32_t success, 
+create_pkey_cont (void* cls,
+                 int32_t success,
                  const char *emsg)
 {
   struct GetPseuAuthorityHandle* gph = cls;
@@ -180,7 +201,7 @@ create_pkey_cont (void* cls,
 static void
 process_pseu_lookup_ns (void *cls,
                        unsigned int rd_count,
-                       const struct GNUNET_NAMESTORE_RecordData *rd);
+                       const struct GNUNET_GNSRECORD_Data *rd);
 
 
 /**
@@ -192,21 +213,24 @@ process_pseu_lookup_ns (void *cls,
  */
 static void
 process_pseu_block_ns (void *cls,
-                      const struct GNUNET_NAMESTORE_Block *block)
+                      const struct GNUNET_GNSRECORD_Block *block)
 {
   struct GetPseuAuthorityHandle *gph = cls;
-  struct GNUNET_CRYPTO_EccPublicSignKey pub;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
 
-  gph->namestore_task = NULL;
+  gph->namecache_task = NULL;
   if (NULL == block)
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Namecache did not return information for label `%s' \n",
+                gph->current_label);
     process_pseu_lookup_ns (gph, 0, NULL);
     return;
   }
-  GNUNET_CRYPTO_ecc_key_get_public_for_signature (&gph->shorten_zone_key,
+  GNUNET_CRYPTO_ecdsa_key_get_public (&gph->shorten_zone_key,
                                    &pub);
-  if (GNUNET_OK != 
-      GNUNET_NAMESTORE_block_decrypt (block,
+  if (GNUNET_OK !=
+      GNUNET_GNSRECORD_block_decrypt (block,
                                      &pub,
                                      gph->current_label,
                                      &process_pseu_lookup_ns,
@@ -220,26 +244,26 @@ process_pseu_block_ns (void *cls,
 
 
 /**
- * Lookup in the namestore for the shorten zone the given label.
+ * Lookup in the namecache for the shorten zone the given label.
  *
  * @param gph the handle to our shorten operation
  * @param label the label to lookup
  */
-static void 
-perform_pseu_lookup (struct GetPseuAuthorityHandle *gph,
+static void
+perform_nick_lookup (struct GetPseuAuthorityHandle *gph,
                     const char *label)
-{ 
-  struct GNUNET_CRYPTO_EccPublicSignKey pub;
+{
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
   struct GNUNET_HashCode query;
 
-  GNUNET_CRYPTO_ecc_key_get_public_for_signature (&gph->shorten_zone_key,
+  GNUNET_CRYPTO_ecdsa_key_get_public (&gph->shorten_zone_key,
                                    &pub);
   GNUNET_free_non_null (gph->current_label);
   gph->current_label = GNUNET_strdup (label);
-  GNUNET_NAMESTORE_query_from_public_key (&pub,
+  GNUNET_GNSRECORD_query_from_public_key (&pub,
                                          label,
                                          &query);
-  gph->namestore_task = GNUNET_NAMESTORE_lookup_block (namestore_handle,
+  gph->namecache_task = GNUNET_NAMECACHE_lookup_block (namecache_handle,
                                                       &query,
                                                       &process_pseu_block_ns,
                                                       gph);
@@ -257,17 +281,17 @@ perform_pseu_lookup (struct GetPseuAuthorityHandle *gph,
 static void
 process_pseu_lookup_ns (void *cls,
                        unsigned int rd_count,
-                       const struct GNUNET_NAMESTORE_RecordData *rd)
+                       const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct GetPseuAuthorityHandle *gph = cls;
-  struct GNUNET_NAMESTORE_RecordData new_pkey;
+  struct GNUNET_GNSRECORD_Data new_pkey;
 
   gph->namestore_task = NULL;
   if (rd_count > 0)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Name `%s' already taken, cannot shorten.\n", 
-              gph->current_label);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Name `%s' already taken, cannot shorten.\n",
+                gph->current_label);
     /* if this was not yet the original label, try one more
        time, this time not using PSEU but the original label */
     if (0 == strcmp (gph->current_label,
@@ -277,23 +301,22 @@ process_pseu_lookup_ns (void *cls,
     }
     else
     {
-      perform_pseu_lookup (gph, gph->label);
+      perform_nick_lookup (gph, gph->label);
     }
     return;
   }
   /* name is available */
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Shortening `%s' to `%s'\n", 
-             GNUNET_NAMESTORE_z2s (&gph->target_zone),
+             "Shortening `%s' to `%s'\n",
+             GNUNET_GNSRECORD_z2s (&gph->target_zone),
              gph->current_label);
   new_pkey.expiration_time = UINT64_MAX;
-  new_pkey.data_size = sizeof (struct GNUNET_CRYPTO_EccPublicSignKey);
+  new_pkey.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
   new_pkey.data = &gph->target_zone;
-  new_pkey.record_type = GNUNET_NAMESTORE_TYPE_PKEY;
-  new_pkey.flags = GNUNET_NAMESTORE_RF_NONE
-                 | GNUNET_NAMESTORE_RF_PRIVATE
-                 | GNUNET_NAMESTORE_RF_PENDING;
-  gph->namestore_task 
+  new_pkey.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
+  new_pkey.flags = GNUNET_GNSRECORD_RF_NONE
+                 | GNUNET_GNSRECORD_RF_PRIVATE;
+  gph->namestore_task
     = GNUNET_NAMESTORE_records_store (namestore_handle,
                                      &gph->shorten_zone_key,
                                      gph->current_label,
@@ -302,164 +325,6 @@ process_pseu_lookup_ns (void *cls,
 }
 
 
-/**
- * Process result of a DHT lookup for a PSEU record.
- *
- * @param gph the handle to our shorten operation
- * @param pseu the pseu result or NULL
- */
-static void
-process_pseu_result (struct GetPseuAuthorityHandle* gph, 
-                    const char *pseu)
-{
-  if (NULL == pseu)
-  {
-    /* no PSEU found, try original label */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No PSEU found, trying original label `%s' instead.\n",
-               gph->label);
-    perform_pseu_lookup (gph, gph->label);
-    return;
-  }  
-  /* check if 'pseu' is taken */
-  perform_pseu_lookup (gph, pseu);
-}
-
-
-/**
- * Handle timeout for DHT request during shortening.
- *
- * @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 = cls;
-
-  gph->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "DHT lookup for PSEU query timed out.\n");
-  GNUNET_DHT_get_stop (gph->get_handle);
-  gph->get_handle = NULL;
-  process_pseu_result (gph, NULL);
-}
-
-
-/**
- * Handle decrypted records from DHT result.
- *
- * @param cls closure with our 'struct GetPseuAuthorityHandle'
- * @param rd_count number of entries in 'rd' array
- * @param rd array of records with data to store
- */
-static void
-process_auth_records (void *cls,
-                     unsigned int rd_count,
-                     const struct GNUNET_NAMESTORE_RecordData *rd)
-{
-  struct GetPseuAuthorityHandle *gph = cls;
-  unsigned int i;
-
-  for (i=0; i < rd_count; i++)
-  {
-    if (GNUNET_NAMESTORE_TYPE_PSEU == rd[i].record_type)
-    {
-      char pseu[rd[i].data_size + 1];
-
-      /* found pseu */
-      memcpy (pseu,
-             rd[i].data,
-             rd[i].data_size);
-      pseu[rd[i].data_size] = '\0';
-      process_pseu_result (gph, 
-                          pseu);
-      return;
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "No PSEU record found in DHT reply.\n");
-  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 struct 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 = cls;
-  const struct GNUNET_NAMESTORE_Block *block;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got DHT result for PSEU request\n");
-  GNUNET_DHT_get_stop (gph->get_handle);
-  gph->get_handle = NULL;
-  GNUNET_SCHEDULER_cancel (gph->timeout_task);
-  gph->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if (NULL == data)
-  {
-    /* is this allowed!? */
-    GNUNET_break (0);
-    process_pseu_result (gph, NULL);
-    return;
-  }
-  if (size < sizeof (struct GNUNET_NAMESTORE_Block))
-  {
-    /* how did this pass DHT block validation!? */
-    GNUNET_break (0);
-    process_pseu_result (gph, NULL);
-    return;   
-  }
-  block = data;
-  if (size !=
-      ntohl (block->purpose.size) + 
-      sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) +
-      sizeof (struct GNUNET_CRYPTO_EccSignature))
-  {
-    /* how did this pass DHT block validation!? */
-    GNUNET_break (0);
-    process_pseu_result (gph, NULL);
-    return;   
-  }
-  if (GNUNET_OK !=
-      GNUNET_NAMESTORE_block_decrypt (block,
-                                     &gph->target_zone,
-                                     GNUNET_GNS_TLD_PLUS,
-                                     &process_auth_records,
-                                     gph))
-  {
-    /* other peer encrypted invalid block, complain */
-    GNUNET_break_op (0);
-    process_pseu_result (gph, NULL);
-    return;   
-  }
-}
-
-
 /**
  * Callback called by namestore for a zone to name result.  We're
  * trying to see if a short name for a given zone already exists.
@@ -472,14 +337,16 @@ process_auth_discovery_dht_result (void* cls,
  */
 static void
 process_zone_to_name_discover (void *cls,
-                              const struct GNUNET_CRYPTO_EccPrivateKey *zone_key,
+                              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
                               const char *name,
                               unsigned int rd_len,
-                              const struct GNUNET_NAMESTORE_RecordData *rd)
+                              const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct GetPseuAuthorityHandle* gph = cls;
+#if 0
   struct GNUNET_HashCode lookup_key;
-  
+#endif
+
   gph->namestore_task = NULL;
   if (0 != rd_len)
   {
@@ -490,21 +357,13 @@ process_zone_to_name_discover (void *cls,
     free_get_pseu_authority_handle (gph);
     return;
   }
-  /* record does not yet exist, go into DHT to find PSEU record */
-  GNUNET_NAMESTORE_query_from_public_key (&gph->target_zone,
-                                         GNUNET_GNS_TLD_PLUS,                                    
-                                         &lookup_key);
-  gph->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
-                                                   &handle_auth_discovery_timeout, 
-                                                   gph);
-  gph->get_handle = GNUNET_DHT_get_start (dht_handle,
-                                         GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
-                                         &lookup_key,
-                                         DHT_GNS_REPLICATION_LEVEL,
-                                         GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
-                                         NULL, 0,
-                                         &process_auth_discovery_dht_result,
-                                         gph);
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Shortening continuing, no name not reserved in shorten zone\n");
+  }
+  /* record does not yet exist, check if suggested label is available */
+  perform_nick_lookup (gph, gph->suggested_label);
 }
 
 
@@ -514,29 +373,39 @@ process_zone_to_name_discover (void *cls,
  * @a original_label as one possible suggestion.
  *
  * @param original_label original label for the zone
+ * @param suggested_label suggested label for the zone
  * @param pub public key of the zone to shorten
  * @param shorten_zone private key of the target zone for the new record
  */
 void
 GNS_shorten_start (const char *original_label,
-                  const struct GNUNET_CRYPTO_EccPublicSignKey *pub,
-                  const struct GNUNET_CRYPTO_EccPrivateKey *shorten_zone)
+                   const char *suggested_label,
+                  const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
+                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone)
 {
   struct GetPseuAuthorityHandle *gph;
+  struct GNUNET_CRYPTO_EcdsaPublicKey shorten_pub;
 
-  // if (1) return;
   if (strlen (original_label) > GNUNET_DNSPARSER_MAX_LABEL_LENGTH)
   {
     GNUNET_break (0);
     return;
   }
+  GNUNET_CRYPTO_ecdsa_key_get_public (shorten_zone, &shorten_pub);
+  if (0 == memcmp (&shorten_pub, pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+  {
+    /* Do not shorten the shorten zone */
+    return;
+  }
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Starting shortening process for `%s' with old label `%s'\n",
-             GNUNET_NAMESTORE_z2s (pub),
-             original_label);
+             "Starting shortening process for `%s' with old label `%s' and suggested nickname `%s'\n",
+             GNUNET_GNSRECORD_z2s (pub),
+             original_label, suggested_label);
   gph = GNUNET_new (struct GetPseuAuthorityHandle);
   gph->shorten_zone_key = *shorten_zone;
   gph->target_zone = *pub;
+  gph->suggested_label = GNUNET_strdup (suggested_label);
   strcpy (gph->label, original_label);
   GNUNET_CONTAINER_DLL_insert (gph_head, gph_tail, gph);
   /* first, check if we *already* have a record for this zone */
@@ -552,13 +421,16 @@ GNS_shorten_start (const char *original_label,
  * Initialize the shortening subsystem
  *
  * @param nh the namestore handle
+ * @param nc the namecache handle
  * @param dht the dht handle
  */
 void
 GNS_shorten_init (struct GNUNET_NAMESTORE_Handle *nh,
+                  struct GNUNET_NAMECACHE_Handle *nc,
                  struct GNUNET_DHT_Handle *dht)
 {
   namestore_handle = nh;
+  namecache_handle = nc;
   dht_handle = dht;
 }
 
@@ -574,6 +446,7 @@ GNS_shorten_done ()
     free_get_pseu_authority_handle (gph_head);
   dht_handle = NULL;
   namestore_handle = NULL;
+  namecache_handle = NULL;
 }
 
 /* end of gnunet-service-gns_shorten.c */