- merge with master
[oweals/gnunet.git] / src / identity-provider / plugin_rest_identity_provider.c
index 1e1878cadc713a836a78994a1d2e4bb15f0f89a2..5ea7b28219f97903f1407f9f8ca6ada23114cb75 100644 (file)
@@ -32,6 +32,7 @@
 #include "gnunet_namestore_service.h"
 #include "gnunet_rest_lib.h"
 #include "gnunet_jsonapi_lib.h"
+#include "gnunet_jsonapi_util.h"
 #include "microhttpd.h"
 #include <jansson.h>
 #include <inttypes.h>
  */
 #define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
 
+/**
+ * Attributes passed to issue request
+ */
+#define GNUNET_IDENTITY_TOKEN_V_ATTR_LIST "requested_verified_attrs"
+
+
 /**
  * Token expiration string
  */
@@ -279,7 +286,7 @@ struct RequestHandle
   /**
    * Response object
    */
-  struct GNUNET_JSONAPI_Object *resp_object;
+  struct GNUNET_JSONAPI_Document *resp_object;
 
 };
 
@@ -296,7 +303,7 @@ cleanup_handle (struct RequestHandle *handle)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Cleaning up\n");
   if (NULL != handle->resp_object)
-    GNUNET_JSONAPI_object_delete (handle->resp_object);
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
   if (NULL != handle->timeout_task)
     GNUNET_SCHEDULER_cancel (handle->timeout_task);
   if (NULL != handle->identity_handle)
@@ -341,7 +348,7 @@ do_error (void *cls)
   GNUNET_asprintf (&json_error,
                    "{Error while processing request: %s}",
                    handle->emsg);
-  resp = GNUNET_REST_create_json_response (json_error);
+  resp = GNUNET_REST_create_response (json_error);
   handle->proc (handle->proc_cls, resp, handle->response_code);
   cleanup_handle (handle);
   GNUNET_free (json_error);
@@ -403,7 +410,7 @@ token_creat_cont (void *cls,
     return;
   }
 
-  handle->resp_object = GNUNET_JSONAPI_object_new ();
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
   json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
                                                     label);
   ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
@@ -420,11 +427,11 @@ token_creat_cont (void *cls,
   GNUNET_free (token_str);
   json_decref (ticket_json);
   json_decref (token_json);
-  GNUNET_JSONAPI_object_resource_add (handle->resp_object, json_resource);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
 
-  GNUNET_JSONAPI_data_serialize (handle->resp_object, &result_str);
+  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_json_response (result_str);
+  resp = GNUNET_REST_create_response (result_str);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result_str);
   GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle);
@@ -459,6 +466,7 @@ issue_token_cont (struct GNUNET_REST_RequestHandle *con,
   char *exp_str;
   char *nonce_str;
   char *scopes;
+  char *vattrs;
   uint64_t time;
   uint64_t nonce;
 
@@ -466,7 +474,7 @@ issue_token_cont (struct GNUNET_REST_RequestHandle *con,
                                                 GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
-    resp = GNUNET_REST_create_json_response (NULL);
+    resp = GNUNET_REST_create_response (NULL);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
     cleanup_handle (handle);
     return;
@@ -535,6 +543,21 @@ issue_token_cont (struct GNUNET_REST_RequestHandle *con,
   scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                               &key);
 
+  //vattrs
+  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_V_ATTR_LIST,
+                      strlen (GNUNET_IDENTITY_TOKEN_V_ATTR_LIST),
+                      &key);
+
+  vattrs = NULL;
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    vattrs = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                &key);
+  }
+
+
 
   //Token audience
   GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
@@ -546,15 +569,15 @@ issue_token_cont (struct GNUNET_REST_RequestHandle *con,
                                                &key) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Audience missing!\n");
+                "Audience missing!\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                                 &key);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Audience to issue token for: %s\n",
-             audience);
+              "Audience to issue token for: %s\n",
+              audience);
 
   priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
   GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
@@ -579,10 +602,11 @@ issue_token_cont (struct GNUNET_REST_RequestHandle *con,
   }
   nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                                  &key);
+  GNUNET_assert (NULL != nonce_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Request nonce: %s\n",
-             nonce_str);
-  sscanf (nonce_str, "%"SCNu64, &nonce);
+              "Request nonce: %s\n",
+              nonce_str);
+  GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce));
 
   //Get expiration for token from URL parameter
   GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
@@ -618,6 +642,7 @@ issue_token_cont (struct GNUNET_REST_RequestHandle *con,
                                                          priv_key,
                                                          &aud_key,
                                                          scopes,
+                                                         vattrs,
                                                          exp_time,
                                                          nonce,
                                                          &token_creat_cont,
@@ -638,14 +663,24 @@ return_token_list (void *cls)
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
 
-  GNUNET_JSONAPI_data_serialize (handle->resp_object, &result_str);
+  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_json_response (result_str);
+  resp = GNUNET_REST_create_response (result_str);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result_str);
   cleanup_handle (handle);
 }
 
+
+static void
+token_collect_error_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  do_error (handle);
+}
+
+
 /**
  * Collect all tokens for an ego
  *
@@ -657,45 +692,68 @@ token_collect (void *cls,
                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
                const char *label,
                unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
+               const struct GNUNET_GNSRECORD_Data *rd);
+
+
+static void
+token_collect_finished_cb (void *cls)
 {
-  int i;
-  char* data;
   struct RequestHandle *handle = cls;
   struct EgoEntry *ego_tmp;
-  struct GNUNET_JSONAPI_Resource *json_resource;
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  json_t *issuer;
-  json_t *token;
-
-  if (NULL == label)
-  {
-    ego_tmp = handle->ego_head;
-    GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                                 handle->ego_tail,
-                                 ego_tmp);
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
 
-    if (NULL == handle->ego_head)
-    {
-      //Done
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
-      handle->ns_it = NULL;
-      GNUNET_SCHEDULER_add_now (&return_token_list, handle);
-      return;
-    }
+  ego_tmp = handle->ego_head;
+  GNUNET_CONTAINER_DLL_remove (handle->ego_head,
+                               handle->ego_tail,
+                               ego_tmp);
+  GNUNET_free (ego_tmp->identifier);
+  GNUNET_free (ego_tmp->keystring);
+  GNUNET_free (ego_tmp);
 
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Next ego: %s\n", handle->ego_head->identifier);
-    priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
-    handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                                           priv_key,
-                                                           &token_collect,
-                                                           handle);
+  if (NULL == handle->ego_head)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
+    handle->ns_it = NULL;
+    GNUNET_SCHEDULER_add_now (&return_token_list, handle);
     return;
   }
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Next ego: %s\n",
+              handle->ego_head->identifier);
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
+  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
+                                                         priv_key,
+                                                         &token_collect_error_cb,
+                                                         handle,
+                                                         &token_collect,
+                                                         handle,
+                                                         &token_collect_finished_cb,
+                                                         handle);
+}
+
+
+/**
+ * Collect all tokens for an ego
+ *
+ * TODO move this into the identity-provider service
+ *
+ */
+static void
+token_collect (void *cls,
+               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+               const char *label,
+               unsigned int rd_count,
+               const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  int i;
+  char* data;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  json_t *issuer;
+  json_t *token;
+
   for (i = 0; i < rd_count; i++)
   {
     if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
@@ -705,19 +763,19 @@ token_collect (void *cls,
                                                rd[i].data_size);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
       json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                                        label);
+                                                   label);
       issuer = json_string (handle->ego_head->identifier);
       GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                             GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                                             issuer);
+                                        GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
+                                        issuer);
       json_decref (issuer);
       token = json_string (data);
       GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                             GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                             token);
+                                        GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+                                        token);
       json_decref (token);
 
-      GNUNET_JSONAPI_object_resource_add (handle->resp_object, json_resource);
+      GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
       GNUNET_free (data);
     }
   }
@@ -760,6 +818,7 @@ list_token_cont (struct GNUNET_REST_RequestHandle *con_handle,
   }
   ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                                &key);
+  GNUNET_assert (NULL != ego_val);
   //Remove non-matching egos
   for (ego_entry = handle->ego_head;
        NULL != ego_entry;)
@@ -776,7 +835,7 @@ list_token_cont (struct GNUNET_REST_RequestHandle *con_handle,
       GNUNET_free (ego_tmp);
     }
   }
-  handle->resp_object = GNUNET_JSONAPI_object_new ();
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
   if (NULL == handle->ego_head)
   {
     //Done
@@ -788,7 +847,11 @@ list_token_cont (struct GNUNET_REST_RequestHandle *con_handle,
   handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
   handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
                                                          priv_key,
+                                                         &token_collect_error_cb,
+                                                         handle,
                                                          &token_collect,
+                                                         handle,
+                                                         &token_collect_finished_cb,
                                                          handle);
 
 }
@@ -827,13 +890,14 @@ exchange_cont (void *cls,
     return;
   }
   nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
-                                                  &key);
+                                                 &key);
+  GNUNET_assert (NULL != nonce_str);
   GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
 
   if (ticket_nonce != expected_nonce)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Ticket nonce %lu does not match expected nonce %lu\n",
+                "Ticket nonce %"SCNu64" does not match expected nonce %"SCNu64"\n",
                 ticket_nonce, expected_nonce);
     handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -847,7 +911,7 @@ exchange_cont (void *cls,
   GNUNET_free (token_str);
 
   result = json_dumps (root, JSON_INDENT(1));
-  resp = GNUNET_REST_create_json_response (result);
+  resp = GNUNET_REST_create_response (result);
   GNUNET_free (result);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   cleanup_handle (handle);
@@ -953,7 +1017,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
   struct RequestHandle *handle = cls;
 
   //For now, independent of path return all options
-  resp = GNUNET_REST_create_json_response (NULL);
+  resp = GNUNET_REST_create_response (NULL);
   MHD_add_response_header (resp,
                            "Access-Control-Allow-Methods",
                            allow_methods);
@@ -1045,7 +1109,7 @@ list_ego (void *cls,
     ego_entry->keystring =
       GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
     ego_entry->ego = ego;
-    GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
+    ego_entry->identifier = GNUNET_strdup (identifier);
     GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
   }
 
@@ -1076,7 +1140,7 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
   handle->conndata_handle = conndata_handle;
 
 
-  GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
+  handle->url = GNUNET_strdup (conndata_handle->url);
   if (handle->url[strlen (handle->url)-1] == '/')
     handle->url[strlen (handle->url)-1] = '\0';
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,