-add REST revoke API
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Mon, 9 Oct 2017 07:32:43 +0000 (09:32 +0200)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Mon, 9 Oct 2017 07:32:43 +0000 (09:32 +0200)
src/identity-provider/plugin_rest_identity_provider.c
src/identity-provider/test_idp_consume.sh

index 43251d93dd7de770ad2898b9f479a6ae96b00a63..bb9f210efde3aacc418b4fa7558fcac6f276f69f 100644 (file)
  */
 #define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets"
 
+/**
+ * Revoke namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke"
+
 /**
  * Attribute key
  */
@@ -153,11 +158,6 @@ struct RequestHandle
    */
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
 
-  /**
-   * Handle to the rest connection
-   */
-  struct GNUNET_REST_RequestHandle *conndata_handle;
-
   /**
    * The processing state
    */
@@ -168,6 +168,12 @@ struct RequestHandle
    */
   struct GNUNET_IDENTITY_Handle *identity_handle;
 
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+
   /**
    * IDENTITY Operation
    */
@@ -187,12 +193,12 @@ struct RequestHandle
    * Attribute iterator
    */
   struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
+
   /**
    * Ticket iterator
    */
   struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
-   
+
   /**
    * Desired timeout for the lookup (default is no timeout).
    */
@@ -232,7 +238,7 @@ struct RequestHandle
    * Response object
    */
   struct GNUNET_JSONAPI_Document *resp_object;
+
   /**
    * Resource object
    */
@@ -281,6 +287,13 @@ cleanup_handle (struct RequestHandle *handle)
   GNUNET_free (handle);
 }
 
+static void
+cleanup_handle_delayed (void *cls)
+{
+  cleanup_handle (cls);
+}
+
+
 /**
  * Task run on error, sends error message.  Cleans up everything.
  *
@@ -546,6 +559,151 @@ list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
+static void
+revoke_finished_cont (void *cls,
+                      int32_t success,
+                      const char *emsg)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  resp = GNUNET_REST_create_response (emsg);
+  if (GNUNET_OK != success)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+}
+
+static void
+revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity_str;
+  const char* audience_str;
+  const char* rnd_str;
+
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *rnd_json;
+  json_t *identity_json;
+  json_t *audience_json;
+  json_t *data_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "rnd");
+  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "identity");
+  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "audience");
+  rnd_str = json_string_value (rnd_json);
+  identity_str = json_string_value (identity_json);
+  audience_str = json_string_value (audience_json);
+
+  GNUNET_STRINGS_string_to_data (rnd_str,
+                                 strlen (rnd_str),
+                                 &ticket.rnd,
+                                 sizeof (uint64_t));
+  GNUNET_STRINGS_string_to_data (identity_str,
+                                 strlen (identity_str),
+                                 &ticket.identity,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  GNUNET_STRINGS_string_to_data (audience_str,
+                                 strlen (audience_str),
+                                 &ticket.audience,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                        &tmp_pk);
+    if (0 == memcmp (&ticket.identity,
+                     &tmp_pk,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+      break;
+  }
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity_str);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
+  handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp,
+                                                           identity_priv,
+                                                           &ticket,
+                                                           &revoke_finished_cont,
+                                                           handle);
+  GNUNET_JSONAPI_document_delete (json_obj);
+}
+
+
 /**
  * Respond to OPTIONS request
  *
@@ -583,12 +741,13 @@ init_cont (struct RequestHandle *handle)
   static const struct GNUNET_REST_RequestHandler handlers[] = {
     {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont},
     {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
     {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER,
       &options_cont},
     GNUNET_REST_HANDLER_END
   };
 
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle,
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
                                                handlers,
                                                &err,
                                                handle))
@@ -671,7 +830,7 @@ list_ego (void *cls,
  * @return GNUNET_OK if request accepted
  */
 static void
-rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
                               GNUNET_REST_ResultProcessor proc,
                               void *proc_cls)
 {
@@ -681,10 +840,9 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
   handle->proc_cls = proc_cls;
   handle->proc = proc;
   handle->state = ID_REST_STATE_INIT;
-  handle->conndata_handle = conndata_handle;
-
+  handle->rest_handle = rest_handle;
 
-  handle->url = GNUNET_strdup (conndata_handle->url);
+  handle->url = GNUNET_strdup (rest_handle->url);
   if (handle->url[strlen (handle->url)-1] == '/')
     handle->url[strlen (handle->url)-1] = '\0';
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
index 81cd0b1497b961dd5977a24fb6dc4a0acb80c08c..ab437c0e8538288259000ea2f5ef6866201def7b 100755 (executable)
@@ -35,4 +35,4 @@ TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf
 echo "Consuming ticket $TICKET"
 gnunet-idp -e rpego -C $TICKET -c test_idp.conf
 curl http://localhost:7776/idp/tickets/testego
-gnunet-arm -e -c test_idp.conf
+#gnunet-arm -e -c test_idp.conf