X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fidentity-provider%2Fplugin_rest_identity_provider.c;h=5ea7b28219f97903f1407f9f8ca6ada23114cb75;hb=ab281595eeb270120f89ec954a572f4fcf78fc53;hp=b104950bab07bed9d677f0abc0acbd007a725a1b;hpb=29e6158507a0758192075ac6ece7ba8e75ddc49a;p=oweals%2Fgnunet.git diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c index b104950ba..5ea7b2821 100644 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ b/src/identity-provider/plugin_rest_identity_provider.c @@ -31,6 +31,8 @@ #include "gnunet_gnsrecord_lib.h" #include "gnunet_namestore_service.h" #include "gnunet_rest_lib.h" +#include "gnunet_jsonapi_lib.h" +#include "gnunet_jsonapi_util.h" #include "microhttpd.h" #include #include @@ -107,6 +109,12 @@ */ #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 */ @@ -198,7 +206,7 @@ struct RequestHandle /** * Handle to the rest connection */ - struct RestConnectionDataHandle *conndata_handle; + struct GNUNET_REST_RequestHandle *conndata_handle; /** * The processing state @@ -248,7 +256,7 @@ struct RequestHandle /** * ID of a task associated with the resolution process. */ - struct GNUNET_SCHEDULER_Task * timeout_task; + struct GNUNET_SCHEDULER_Task *timeout_task; /** * The plugin result processor @@ -270,10 +278,15 @@ struct RequestHandle */ char *emsg; + /** + * Reponse code + */ + int response_code; + /** * Response object */ - struct JsonApiObject *resp_object; + struct GNUNET_JSONAPI_Document *resp_object; }; @@ -290,7 +303,7 @@ cleanup_handle (struct RequestHandle *handle) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); if (NULL != handle->resp_object) - GNUNET_REST_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) @@ -321,9 +334,9 @@ cleanup_handle (struct RequestHandle *handle) /** - * Task run on shutdown. Cleans up everything. + * Task run on error, sends error message. Cleans up everything. * - * @param cls unused + * @param cls the `struct RequestHandle` */ static void do_error (void *cls) @@ -335,12 +348,27 @@ do_error (void *cls) GNUNET_asprintf (&json_error, "{Error while processing request: %s}", handle->emsg); - resp = GNUNET_REST_create_json_response (json_error); - handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); + resp = GNUNET_REST_create_response (json_error); + handle->proc (handle->proc_cls, resp, handle->response_code); cleanup_handle (handle); GNUNET_free (json_error); } +/** + * Task run on timeout, sends error message. Cleans up everything. + * + * @param cls the `struct RequestHandle` + */ +static void +do_timeout (void *cls) +{ + struct RequestHandle *handle = cls; + + handle->timeout_task = NULL; + do_error (handle); +} + + /** * Task run on shutdown. Cleans up everything. * @@ -350,7 +378,8 @@ static void do_cleanup_handle_delayed (void *cls) { struct RequestHandle *handle = cls; - cleanup_handle(handle); + + cleanup_handle (handle); } @@ -365,7 +394,7 @@ token_creat_cont (void *cls, const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, const struct GNUNET_IDENTITY_PROVIDER_Token *token) { - struct JsonApiResource *json_resource; + struct GNUNET_JSONAPI_Resource *json_resource; struct RequestHandle *handle = cls; struct MHD_Response *resp; json_t *ticket_json; @@ -381,35 +410,34 @@ token_creat_cont (void *cls, return; } - handle->resp_object = GNUNET_REST_jsonapi_object_new (); - json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, + 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); token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token); ticket_json = json_string (ticket_str); token_json = json_string (token_str); - GNUNET_REST_jsonapi_resource_add_attr (json_resource, + GNUNET_JSONAPI_resource_add_attr (json_resource, GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, ticket_json); - GNUNET_REST_jsonapi_resource_add_attr (json_resource, + GNUNET_JSONAPI_resource_add_attr (json_resource, GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN, token_json); GNUNET_free (ticket_str); GNUNET_free (token_str); json_decref (ticket_json); json_decref (token_json); - GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource); + GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); - GNUNET_REST_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); - - } + /** * Continueationf for token issue request * @@ -418,7 +446,7 @@ token_creat_cont (void *cls, * @param cls the request handle */ static void -issue_token_cont (struct RestConnectionDataHandle *con, +issue_token_cont (struct GNUNET_REST_RequestHandle *con, const char *url, void *cls) { @@ -438,6 +466,7 @@ issue_token_cont (struct RestConnectionDataHandle *con, char *exp_str; char *nonce_str; char *scopes; + char *vattrs; uint64_t time; uint64_t nonce; @@ -445,7 +474,7 @@ issue_token_cont (struct RestConnectionDataHandle *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; @@ -459,7 +488,8 @@ issue_token_cont (struct RestConnectionDataHandle *con, GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, &key) ) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Issuer not found\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Issuer not found\n"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -468,7 +498,9 @@ issue_token_cont (struct RestConnectionDataHandle *con, if (NULL == ego_val) { GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego invalid: %s\n", ego_val); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Ego invalid: %s\n", + ego_val); return; } for (ego_entry = handle->ego_head; @@ -480,13 +512,18 @@ issue_token_cont (struct RestConnectionDataHandle *con, egoname = ego_entry->identifier; break; } - if (NULL == egoname || NULL == ego_entry) + if ( (NULL == egoname) || + (NULL == ego_entry) ) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego not found: %s\n", ego_val); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Ego not found: %s\n", + ego_val); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego to issue token for: %s\n", egoname); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Ego to issue token for: %s\n", + egoname); //Meta info @@ -506,6 +543,21 @@ issue_token_cont (struct RestConnectionDataHandle *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, @@ -516,13 +568,16 @@ issue_token_cont (struct RestConnectionDataHandle *con, GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, &key) ) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Audience missing!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "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); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "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, @@ -547,8 +602,11 @@ issue_token_cont (struct RestConnectionDataHandle *con, } nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, &key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str); - sscanf (nonce_str, "%"SCNu64, &nonce); + GNUNET_assert (NULL != nonce_str); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "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, @@ -584,6 +642,7 @@ issue_token_cont (struct RestConnectionDataHandle *con, priv_key, &aud_key, scopes, + vattrs, exp_time, nonce, &token_creat_cont, @@ -604,14 +663,24 @@ return_token_list (void *cls) struct RequestHandle *handle = cls; struct MHD_Response *resp; - GNUNET_REST_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 * @@ -623,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 JsonApiResource *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); + 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; - } - - 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) @@ -670,20 +762,20 @@ token_collect (void *cls, rd[i].data, rd[i].data_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data); - json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN, - label); + json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN, + label); issuer = json_string (handle->ego_head->identifier); - GNUNET_REST_jsonapi_resource_add_attr (json_resource, - GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST, - issuer); + GNUNET_JSONAPI_resource_add_attr (json_resource, + GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST, + issuer); json_decref (issuer); token = json_string (data); - GNUNET_REST_jsonapi_resource_add_attr (json_resource, - GNUNET_REST_JSONAPI_IDENTITY_TOKEN, - token); + GNUNET_JSONAPI_resource_add_attr (json_resource, + GNUNET_REST_JSONAPI_IDENTITY_TOKEN, + token); json_decref (token); - GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource); + GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); GNUNET_free (data); } } @@ -701,7 +793,7 @@ token_collect (void *cls, * @param cls the RequestHandle */ static void -list_token_cont (struct RestConnectionDataHandle *con_handle, +list_token_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, void *cls) { @@ -726,6 +818,7 @@ list_token_cont (struct RestConnectionDataHandle *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;) @@ -742,7 +835,7 @@ list_token_cont (struct RestConnectionDataHandle *con_handle, GNUNET_free (ego_tmp); } } - handle->resp_object = GNUNET_REST_jsonapi_object_new (); + handle->resp_object = GNUNET_JSONAPI_document_new (); if (NULL == handle->ego_head) { //Done @@ -754,7 +847,11 @@ list_token_cont (struct RestConnectionDataHandle *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); } @@ -793,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); @@ -813,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); @@ -890,7 +988,7 @@ exchange_token_ticket_cb (void *cls, * @param cls the RequestHandle */ static void -exchange_token_ticket_cont (struct RestConnectionDataHandle *con_handle, +exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, void *cls) { @@ -911,7 +1009,7 @@ exchange_token_ticket_cont (struct RestConnectionDataHandle *con_handle, * @param cls the RequestHandle */ static void -options_cont (struct RestConnectionDataHandle *con_handle, +options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, void *cls) { @@ -919,7 +1017,7 @@ options_cont (struct RestConnectionDataHandle *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); @@ -936,7 +1034,8 @@ options_cont (struct RestConnectionDataHandle *con_handle, static void init_cont (struct RequestHandle *handle) { - static const struct GNUNET_REST_RestConnectionHandler handlers[] = { + struct GNUNET_REST_RequestHandlerError err; + static const struct GNUNET_REST_RequestHandler handlers[] = { {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont}, //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont}, {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont}, @@ -945,9 +1044,12 @@ init_cont (struct RequestHandle *handle) GNUNET_REST_HANDLER_END }; - if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle)) + if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, + handlers, + &err, + handle)) { - handle->emsg = GNUNET_strdup ("Request unsupported"); + handle->response_code = err.error_code; GNUNET_SCHEDULER_add_now (&do_error, handle); } } @@ -1007,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); } @@ -1025,7 +1127,7 @@ list_ego (void *cls, * @return GNUNET_OK if request accepted */ static void -rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle, +rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls) { @@ -1038,7 +1140,7 @@ rest_identity_process_request(struct RestConnectionDataHandle *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, @@ -1048,10 +1150,8 @@ rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle, handle); handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_error, + &do_timeout, handle); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); }