From dc7f9d7e2bf4e9c607738500051adab58b1bd2f3 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 9 Oct 2017 09:32:43 +0200 Subject: [PATCH] -add REST revoke API --- .../plugin_rest_identity_provider.c | 184 ++++++++++++++++-- src/identity-provider/test_idp_consume.sh | 2 +- 2 files changed, 172 insertions(+), 14 deletions(-) diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c index 43251d93d..bb9f210ef 100644 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ b/src/identity-provider/plugin_rest_identity_provider.c @@ -54,6 +54,11 @@ */ #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, diff --git a/src/identity-provider/test_idp_consume.sh b/src/identity-provider/test_idp_consume.sh index 81cd0b149..ab437c0e8 100755 --- a/src/identity-provider/test_idp_consume.sh +++ b/src/identity-provider/test_idp_consume.sh @@ -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 -- 2.25.1