-remove debug output
[oweals/gnunet.git] / src / identity-provider / gnunet-service-identity-provider.c
index 10ecf95380b4023c09c7d896e6f4c8b77a8fb989..2a7316d17771410488a3fc3068b685f8da017065 100644 (file)
@@ -255,6 +255,11 @@ struct IssueHandle
    * QueueEntry
    */
   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * The label the token is stored under
+   */
+  char *label;
 };
 
 /**
@@ -327,7 +332,6 @@ handle_token_update (void *cls,
   char *token_metadata;
   char *write_ptr;
   char *enc_token_str;
-  char *val_str;
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
   struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
   struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey;
@@ -402,21 +406,15 @@ handle_token_update (void *cls,
   {
     if (0 == strcmp (attr->name, "exp"))
     {
-      GNUNET_asprintf (&val_str, "%ul", new_exp.abs_value_us);
-      token_add_attr (new_token, attr->name, val_str);
-      GNUNET_free (val_str);
+      token_add_attr_int (new_token, attr->name, new_exp.abs_value_us);
     }
     else if (0 == strcmp (attr->name, "nbf"))
     {
-      GNUNET_asprintf (&val_str, "%ul", new_nbf.abs_value_us);
-      token_add_attr (new_token, attr->name, val_str);
-      GNUNET_free (val_str);
+      token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us);
     }
     else if (0 == strcmp (attr->name, "iat"))
     {
-      GNUNET_asprintf (&val_str, "%ul", new_iat.abs_value_us);
-      token_add_attr (new_token, attr->name, val_str);
-      GNUNET_free (val_str);
+      token_add_attr_int (new_token, attr->name, new_iat.abs_value_us);
     }
     else if ((0 == strcmp (attr->name, "iss"))
              || (0 == strcmp (attr->name, "aud")))
@@ -534,7 +532,6 @@ clear_ego_attrs (void *cls,
   return GNUNET_YES;
 }
 
-
 /**
  *
  * Update all ID_TOKEN records for an identity and store them
@@ -894,14 +891,25 @@ create_exchange_result_message (const char* token,
 
 
 static struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage*
-create_issue_result_message (const char* ticket)
+create_issue_result_message (const char* label,
+                             const char* ticket,
+                             const char* token)
 {
   struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage *irm;
+  char *tmp_str;
 
-  irm = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage) + strlen(ticket) + 1);
+  irm = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage) 
+                       + strlen (label) + 1
+                       + strlen (ticket) + 1
+                       + strlen (token) + 1);
   irm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
-  irm->header.size = htons (sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage) + strlen (ticket) + 1);
-  memcpy (&irm[1], ticket, strlen (ticket) + 1);
+  irm->header.size = htons (sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage) 
+                            + strlen (label) + 1
+                            + strlen (ticket) + 1
+                            + strlen (token) + 1);
+  GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token);
+  memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1);
+  GNUNET_free (tmp_str);
   return irm;
 }
 
@@ -913,9 +921,11 @@ cleanup_issue_handle (struct IssueHandle *handle)
   if (NULL != handle->scopes)
     GNUNET_free (handle->scopes);
   if (NULL != handle->token)
-    token_destroy (handle->token);
+   token_destroy (handle->token);
   if (NULL != handle->ticket)
     ticket_destroy (handle->ticket);
+  if (NULL != handle->label)
+    GNUNET_free (handle->label);
   GNUNET_free (handle);
 }
 
@@ -926,7 +936,8 @@ store_token_issue_cont (void *cls,
 {
   struct IssueHandle *handle = cls;
   struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage *irm;
-  char* token_ticket_str;
+  char *ticket_str;
+  char *token_str;
   handle->ns_qe = NULL;
   if (GNUNET_SYSERR == success)
   {
@@ -938,7 +949,7 @@ store_token_issue_cont (void *cls,
   }
   if (GNUNET_OK != ticket_serialize (handle->ticket,
                                      &handle->iss_key,
-                                     &token_ticket_str))
+                                     &ticket_str))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
                 "Error serializing ticket\n");
@@ -946,7 +957,18 @@ store_token_issue_cont (void *cls,
     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 
     return;
   }
-  irm = create_issue_result_message (token_ticket_str);
+  if (GNUNET_OK != token_to_string (handle->token,
+                                    &handle->iss_key,
+                                    &token_str))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
+                "Error serializing token\n");
+    GNUNET_free (ticket_str);
+    cleanup_issue_handle (handle);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 
+    return;
+  }
+  irm = create_issue_result_message (handle->label, ticket_str, token_str);
   GNUNET_SERVER_notification_context_unicast (nc,
                                               handle->client,
                                               &irm->header,
@@ -954,7 +976,8 @@ store_token_issue_cont (void *cls,
   GNUNET_SERVER_client_set_user_context (handle->client, NULL);
   cleanup_issue_handle (handle);
   GNUNET_free (irm);
-  GNUNET_free (token_ticket_str);
+  GNUNET_free (ticket_str);
+  GNUNET_free (token_str);
 }
 
 /**
@@ -974,15 +997,12 @@ sign_and_return_token (void *cls,
   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
   struct IssueHandle *handle = cls;
   struct GNUNET_GNSRECORD_Data token_record[2];
-  char *lbl_str;
   char *nonce_str;
   char *enc_token_str;
   char *token_metadata;
   char* write_ptr;
-  char* attr_val;
   uint64_t time;
   uint64_t exp_time;
-  uint64_t rnd_key;
   size_t token_metadata_len;
 
   //Remote nonce 
@@ -990,29 +1010,19 @@ sign_and_return_token (void *cls,
   GNUNET_asprintf (&nonce_str, "%d", handle->nonce);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
 
-  //Label
-  rnd_key = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
-                                      UINT64_MAX);
-  GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
-                                sizeof (uint64_t),
-                                &lbl_str);
   GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
                                       &pub_key);
   handle->ticket = ticket_create (nonce_str,
                                   &pub_key,
-                                  lbl_str,
+                                  handle->label,
                                   &handle->aud_key);
 
   time = GNUNET_TIME_absolute_get().abs_value_us;
   exp_time = time + token_expiration_interval.rel_value_us;
 
-  GNUNET_asprintf (&attr_val, "%ul", time);
-  token_add_attr (handle->token, "nbf", attr_val);
-  token_add_attr (handle->token, "iat", attr_val);
-  GNUNET_free (attr_val);
-  GNUNET_asprintf (&attr_val, "%ul", exp_time);
-  token_add_attr (handle->token, "exp", attr_val);
-  GNUNET_free (attr_val);
+  token_add_attr_int (handle->token, "nbf", time);
+  token_add_attr_int (handle->token, "iat", time);
+  token_add_attr_int (handle->token, "exp", exp_time);
   token_add_attr (handle->token, "nonce", nonce_str);
 
   //Token in a serialized encrypted format 
@@ -1049,13 +1059,12 @@ sign_and_return_token (void *cls,
   //Persist token
   handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
                                                   &handle->iss_key,
-                                                  lbl_str,
+                                                  handle->label,
                                                   2,
                                                   token_record,
                                                   &store_token_issue_cont,
                                                   handle);
   GNUNET_free (ecdhe_privkey);
-  GNUNET_free (lbl_str);
   GNUNET_free (nonce_str);
   GNUNET_free (enc_token_str);
   GNUNET_free (token_metadata);
@@ -1195,6 +1204,8 @@ process_lookup_result (void *cls, uint32_t rd_count,
 
 }
 
+
+
 /**
  *
  * Handler for exchange message
@@ -1237,7 +1248,7 @@ handle_exchange_message (void *cls,
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
     return;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for token under %s\n",
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for token under %s\n",
               xchange_handle->ticket->payload->label);
   GNUNET_asprintf (&lookup_query,
                    "%s.gnu",
@@ -1258,6 +1269,137 @@ handle_exchange_message (void *cls,
 
 }
 
+
+/**
+ *
+ * Look for existing token
+ *
+ * @param cls the identity entry
+ * @param zone the identity
+ * @param lbl the name of the record
+ * @param rd_count number of records
+ * @param rd record data
+ *
+ */
+static void
+find_existing_token (void *cls,
+                     const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                     const char *lbl,
+                     unsigned int rd_count,
+                     const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct IssueHandle *handle = cls;
+  const struct GNUNET_GNSRECORD_Data *token_metadata_record;
+  struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
+  struct GNUNET_HashCode key;
+  int scope_count_token;
+  uint64_t rnd_key;
+  char *scope;
+  char *tmp_scopes;
+
+  if (NULL == lbl)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                ">>> No existing token found\n");
+    //Label
+    rnd_key = 
+      GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
+                                UINT64_MAX);
+    GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
+                                  sizeof (uint64_t),
+                                  &handle->label);
+    handle->ns_it = NULL;
+    handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                           &handle->iss_key,
+                                                           &attr_collect,
+                                                           handle);
+    return; 
+  }
+
+  //There should be only a single record for a token under a label
+  if (2 != rd_count)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+    return;
+  }
+
+  if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
+  {
+    token_metadata_record = &rd[0];
+  } else {
+    token_metadata_record = &rd[1];
+  }
+  if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+    return;
+  }
+  ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
+  aud_key = 
+    (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
+  tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  if (0 != memcmp (aud_key, &handle->aud_key,
+                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+  {
+    char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key,
+                                                      sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+    //Audience does not match!
+    char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA,
+                                                  token_metadata_record->data,
+                                                  token_metadata_record->data_size);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Token does not match audience %s vs %s. Moving on\n",
+                tmp2,
+                tmp);
+    GNUNET_free (tmp_scopes);
+    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+    return;
+  }
+
+  scope = strtok (tmp_scopes, ",");
+  scope_count_token = 0;
+  while (NULL != scope)
+  {
+    GNUNET_CRYPTO_hash (scope,
+                        strlen (scope),
+                        &key);
+
+    if ((NULL != handle->attr_map) &&
+        (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key)))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Issued token does not include `%s'. Moving on\n", scope);
+      GNUNET_free (tmp_scopes);
+      GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+      return;
+    }
+    scope_count_token++;
+    scope = strtok (NULL, ",");
+  }
+  GNUNET_free (tmp_scopes);
+  //All scopes in token are also in request. Now
+  //Check length
+  if (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == scope_count_token)
+  {
+    //We have an existing token
+    handle->label = GNUNET_strdup (lbl);
+    handle->ns_it = NULL;
+    handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                           &handle->iss_key,
+                                                           &attr_collect,
+                                                           handle);
+
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Nuber of attributes in token do not match request\n");
+  //No luck
+  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+}
+
+
 /**
  *
  * Handler for issue message
@@ -1311,21 +1453,21 @@ handle_issue_message (void *cls,
 
   issue_handle->aud_key = im->aud_key;
   issue_handle->iss_key = im->iss_key;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
+                                      &issue_handle->iss_pkey);
   issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
-  issue_handle->nonce = im->nonce;
+  issue_handle->nonce = ntohl (im->nonce);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
   GNUNET_SERVER_notification_context_add (nc, client);
   GNUNET_SERVER_client_set_user_context (client, issue_handle);
   issue_handle->client = client;
   issue_handle->scopes = GNUNET_strdup (scopes);
-  GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
-                                      &issue_handle->iss_pkey);
   issue_handle->token = token_create (&issue_handle->iss_pkey,
-                                      &im->aud_key);
+                                      &issue_handle->aud_key);
 
   issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
                                                                &im->iss_key,
-                                                               &attr_collect,
+                                                               &find_existing_token,
                                                                issue_handle);
 }