2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 * @author Martin Schanzenbach
22 * @file identity/plugin_rest_identity.c
23 * @brief GNUnet Namestore REST plugin
28 #include "gnunet_rest_plugin.h"
29 #include "gnunet_identity_service.h"
30 #include "gnunet_gns_service.h"
31 #include "gnunet_gnsrecord_lib.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_rest_lib.h"
34 #include "microhttpd.h"
37 #include "gnunet_signatures.h"
38 #include "gnunet_identity_provider_service.h"
43 #define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp"
48 #define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/idp/issue"
51 * Check namespace TODO
53 #define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/idp/check"
58 #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token"
61 * The parameter name in which the ticket must be provided
63 #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket"
66 * The parameter name in which the expected nonce must be provided
68 #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce"
71 * The parameter name in which the ticket must be provided
73 #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token"
76 * The URL parameter name in which the nonce must be provided
78 #define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce"
81 * State while collecting all egos
83 #define ID_REST_STATE_INIT 0
86 * Done collecting egos
88 #define ID_REST_STATE_POST_INIT 1
93 #define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
96 * URL parameter to create a GNUid token for a specific audience
98 #define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
101 * URL parameter to create a GNUid token for a specific issuer (EGO)
103 #define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
106 * Attributes passed to issue request
108 #define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
111 * Token expiration string
113 #define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
118 #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
119 #define GNUNET_REST_ERROR_NO_DATA "No data"
122 * GNUid token lifetime
124 #define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
127 * The configuration handle
129 const struct GNUNET_CONFIGURATION_Handle *cfg;
132 * HTTP methods allows for this plugin
134 static char* allow_methods;
137 * @brief struct returned by the initialization function of the plugin
141 const struct GNUNET_CONFIGURATION_Handle *cfg;
152 struct EgoEntry *next;
157 struct EgoEntry *prev;
172 struct GNUNET_IDENTITY_Ego *ego;
181 struct EgoEntry *ego_head;
186 struct EgoEntry *ego_tail;
191 struct EgoEntry *ego_entry;
194 * Ptr to current ego private key
196 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
199 * Handle to the rest connection
201 struct RestConnectionDataHandle *conndata_handle;
204 * The processing state
209 * Handle to Identity service.
211 struct GNUNET_IDENTITY_Handle *identity_handle;
216 struct GNUNET_IDENTITY_Operation *op;
221 struct GNUNET_IDENTITY_PROVIDER_Handle *idp;
226 struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
229 * Handle to NS service
231 struct GNUNET_NAMESTORE_Handle *ns_handle;
236 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
241 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
244 * Desired timeout for the lookup (default is no timeout).
246 struct GNUNET_TIME_Relative timeout;
249 * ID of a task associated with the resolution process.
251 struct GNUNET_SCHEDULER_Task * timeout_task;
254 * The plugin result processor
256 GNUNET_REST_ResultProcessor proc;
259 * The closure of the result processor
269 * Error response message
276 struct JsonApiObject *resp_object;
282 * Cleanup lookup handle
283 * @param handle Handle to clean up
286 cleanup_handle (struct RequestHandle *handle)
288 struct EgoEntry *ego_entry;
289 struct EgoEntry *ego_tmp;
290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
292 if (NULL != handle->resp_object)
293 GNUNET_REST_jsonapi_object_delete (handle->resp_object);
294 if (NULL != handle->timeout_task)
295 GNUNET_SCHEDULER_cancel (handle->timeout_task);
296 if (NULL != handle->identity_handle)
297 GNUNET_IDENTITY_disconnect (handle->identity_handle);
298 if (NULL != handle->idp)
299 GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
300 if (NULL != handle->ns_it)
301 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
302 if (NULL != handle->ns_qe)
303 GNUNET_NAMESTORE_cancel (handle->ns_qe);
304 if (NULL != handle->ns_handle)
305 GNUNET_NAMESTORE_disconnect (handle->ns_handle);
306 if (NULL != handle->url)
307 GNUNET_free (handle->url);
308 if (NULL != handle->emsg)
309 GNUNET_free (handle->emsg);
310 for (ego_entry = handle->ego_head;
314 ego_entry = ego_entry->next;
315 GNUNET_free (ego_tmp->identifier);
316 GNUNET_free (ego_tmp->keystring);
317 GNUNET_free (ego_tmp);
319 GNUNET_free (handle);
324 * Task run on shutdown. Cleans up everything.
327 * @param tc scheduler context
331 const struct GNUNET_SCHEDULER_TaskContext *tc)
333 struct RequestHandle *handle = cls;
334 struct MHD_Response *resp;
337 GNUNET_asprintf (&json_error,
338 "{Error while processing request: %s}",
340 resp = GNUNET_REST_create_json_response (json_error);
341 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
342 cleanup_handle (handle);
343 GNUNET_free (json_error);
347 * Task run on shutdown. Cleans up everything.
350 * @param tc scheduler context
353 do_cleanup_handle_delayed (void *cls,
354 const struct GNUNET_SCHEDULER_TaskContext *tc)
356 struct RequestHandle *handle = cls;
357 cleanup_handle(handle);
362 * Get a ticket for identity
363 * @param cls the handle
364 * @param ticket the ticket returned from the idp
367 token_creat_cont (void *cls,
369 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
370 const struct GNUNET_IDENTITY_PROVIDER_Token *token)
372 struct JsonApiResource *json_resource;
373 struct RequestHandle *handle = cls;
374 struct MHD_Response *resp;
383 handle->emsg = GNUNET_strdup ("Error in token issue");
384 GNUNET_SCHEDULER_add_now (&do_error, handle);
388 handle->resp_object = GNUNET_REST_jsonapi_object_new ();
389 json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
391 ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
392 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
393 ticket_json = json_string (ticket_str);
394 token_json = json_string (token_str);
395 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
396 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
398 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
399 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN,
401 GNUNET_free (ticket_str);
402 GNUNET_free (token_str);
403 json_decref (ticket_json);
404 json_decref (token_json);
405 GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
407 GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result_str);
408 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
409 resp = GNUNET_REST_create_json_response (result_str);
410 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
411 GNUNET_free (result_str);
412 GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle);
418 * Continueationf for token issue request
420 * @param con the Rest handle
421 * @param url the requested url
422 * @param cls the request handle
425 issue_token_cont (struct RestConnectionDataHandle *con,
429 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
432 struct RequestHandle *handle = cls;
433 struct EgoEntry *ego_entry;
434 struct GNUNET_HashCode key;
435 struct MHD_Response *resp;
436 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
437 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
438 struct GNUNET_TIME_Relative etime_rel;
439 struct GNUNET_TIME_Absolute exp_time;
448 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
449 GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
451 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
452 resp = GNUNET_REST_create_json_response (NULL);
453 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
454 cleanup_handle (handle);
459 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
460 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
463 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
466 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Issuer not found\n");
467 GNUNET_SCHEDULER_add_now (&do_error, handle);
470 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
474 GNUNET_SCHEDULER_add_now (&do_error, handle);
475 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego invalid: %s\n", ego_val);
478 for (ego_entry = handle->ego_head;
480 ego_entry = ego_entry->next)
482 if (0 != strcmp (ego_val, ego_entry->identifier))
484 egoname = ego_entry->identifier;
487 if (NULL == egoname || NULL == ego_entry)
489 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego not found: %s\n", ego_val);
490 GNUNET_SCHEDULER_add_now (&do_error, handle);
493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego to issue token for: %s\n", egoname);
497 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST,
498 strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST),
503 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
506 handle->emsg = GNUNET_strdup ("Scopes missing!\n");
507 GNUNET_SCHEDULER_add_now (&do_error, handle);
510 scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
515 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
516 strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
520 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
523 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Audience missing!\n");
524 GNUNET_SCHEDULER_add_now (&do_error, handle);
527 audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audience to issue token for: %s\n", audience);
531 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
532 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
534 GNUNET_STRINGS_string_to_data (audience,
537 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
541 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
542 strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
545 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
548 handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
549 GNUNET_SCHEDULER_add_now (&do_error, handle);
552 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
555 sscanf (nonce_str, "%"SCNu64, &nonce);
557 //Get expiration for token from URL parameter
558 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
559 strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING),
563 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
566 exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
569 if (NULL == exp_str) {
570 handle->emsg = GNUNET_strdup ("No expiration given!\n");
571 GNUNET_SCHEDULER_add_now (&do_error, handle);
576 GNUNET_STRINGS_fancy_time_to_relative (exp_str,
579 handle->emsg = GNUNET_strdup ("Expiration invalid!\n");
580 GNUNET_SCHEDULER_add_now (&do_error, handle);
583 time = GNUNET_TIME_absolute_get().abs_value_us;
584 exp_time.abs_value_us = time + etime_rel.rel_value_us;
586 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
587 handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp,
600 * Build a GNUid token for identity
602 * @param cls the request handle
603 * @param tc task context
606 return_token_list (void *cls,
607 const struct GNUNET_SCHEDULER_TaskContext *tc)
610 struct RequestHandle *handle = cls;
611 struct MHD_Response *resp;
613 GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result_str);
614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
615 resp = GNUNET_REST_create_json_response (result_str);
616 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
617 GNUNET_free (result_str);
618 cleanup_handle (handle);
622 * Collect all tokens for an ego
624 * TODO move this into the identity-provider service
628 token_collect (void *cls,
629 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
631 unsigned int rd_count,
632 const struct GNUNET_GNSRECORD_Data *rd)
636 struct RequestHandle *handle = cls;
637 struct EgoEntry *ego_tmp;
638 struct JsonApiResource *json_resource;
639 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
645 ego_tmp = handle->ego_head;
646 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
649 GNUNET_free (ego_tmp->identifier);
650 GNUNET_free (ego_tmp->keystring);
651 GNUNET_free (ego_tmp);
653 if (NULL == handle->ego_head)
656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
657 handle->ns_it = NULL;
658 GNUNET_SCHEDULER_add_now (&return_token_list, handle);
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Next ego: %s\n", handle->ego_head->identifier);
663 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
664 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
671 for (i = 0; i < rd_count; i++)
673 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
675 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
679 json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
681 issuer = json_string (handle->ego_head->identifier);
682 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
683 GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
685 json_decref (issuer);
686 token = json_string (data);
687 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
688 GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
692 GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
697 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
703 * Respond to OPTIONS request
705 * @param con_handle the connection handle
707 * @param cls the RequestHandle
710 list_token_cont (struct RestConnectionDataHandle *con_handle,
715 struct GNUNET_HashCode key;
716 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
717 struct RequestHandle *handle = cls;
718 struct EgoEntry *ego_entry;
719 struct EgoEntry *ego_tmp;
721 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
722 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
726 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No issuer given.\n");
730 GNUNET_SCHEDULER_add_now (&do_error, handle);
733 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
735 //Remove non-matching egos
736 for (ego_entry = handle->ego_head;
740 ego_entry = ego_entry->next;
741 if (0 != strcmp (ego_val, ego_tmp->identifier))
743 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
746 GNUNET_free (ego_tmp->identifier);
747 GNUNET_free (ego_tmp->keystring);
748 GNUNET_free (ego_tmp);
751 handle->resp_object = GNUNET_REST_jsonapi_object_new ();
752 if (NULL == handle->ego_head)
755 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n");
756 GNUNET_SCHEDULER_add_now (&return_token_list, handle);
759 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
760 handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
761 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
769 * Return token to requestor
771 * @param cls request handle
772 * @param token the token
775 exchange_cont (void *cls,
776 const struct GNUNET_IDENTITY_PROVIDER_Token *token,
777 uint64_t ticket_nonce)
780 struct RequestHandle *handle = cls;
781 struct MHD_Response *resp;
782 struct GNUNET_HashCode key;
786 uint64_t expected_nonce;
789 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE,
790 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE),
794 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
797 handle->emsg = GNUNET_strdup ("No nonce given.");
798 GNUNET_SCHEDULER_add_now (&do_error, handle);
801 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
803 GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
805 if (ticket_nonce != expected_nonce)
807 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
808 "Ticket nonce %lu does not match expected nonce %lu\n",
809 ticket_nonce, expected_nonce);
810 handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n");
811 GNUNET_SCHEDULER_add_now (&do_error, handle);
815 root = json_object ();
816 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
817 json_object_set_new (root, "token", json_string (token_str));
818 json_object_set_new (root, "token_type", json_string ("jwt"));
819 GNUNET_free (token_str);
821 result = json_dumps (root, JSON_INDENT(1));
822 resp = GNUNET_REST_create_json_response (result);
823 GNUNET_free (result);
824 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
825 cleanup_handle (handle);
832 * Callback called when identity for token exchange has been found
834 * @param cls request handle
835 * @param ego the identity to use as issuer
836 * @param ctx user context
837 * @param name identity name
841 exchange_token_ticket_cb (void *cls,
842 struct GNUNET_IDENTITY_Ego *ego,
846 struct RequestHandle *handle = cls;
847 struct GNUNET_HashCode key;
848 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
855 handle->emsg = GNUNET_strdup ("No identity found.");
856 GNUNET_SCHEDULER_add_now (&do_error, handle);
861 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
862 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET),
866 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
869 handle->emsg = GNUNET_strdup ("No ticket given.");
870 GNUNET_SCHEDULER_add_now (&do_error, handle);
873 ticket_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
875 handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego);
876 GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str,
879 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
880 handle->idp_op = GNUNET_IDENTITY_PROVIDER_exchange_ticket (handle->idp,
885 GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket);
892 * Respond to issue request
894 * @param con_handle the connection handle
896 * @param cls the RequestHandle
899 exchange_token_ticket_cont (struct RestConnectionDataHandle *con_handle,
903 struct RequestHandle *handle = cls;
906 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
908 &exchange_token_ticket_cb,
913 * Respond to OPTIONS request
915 * @param con_handle the connection handle
917 * @param cls the RequestHandle
920 options_cont (struct RestConnectionDataHandle *con_handle,
924 struct MHD_Response *resp;
925 struct RequestHandle *handle = cls;
927 //For now, independent of path return all options
928 resp = GNUNET_REST_create_json_response (NULL);
929 MHD_add_response_header (resp,
930 "Access-Control-Allow-Methods",
932 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
933 cleanup_handle (handle);
938 * Handle rest request
940 * @param handle the request handle
943 init_cont (struct RequestHandle *handle)
945 static const struct GNUNET_REST_RestConnectionHandler handlers[] = {
946 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont},
947 //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont},
948 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont},
949 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &options_cont},
950 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont},
951 GNUNET_REST_HANDLER_END
954 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
956 handle->emsg = GNUNET_strdup ("Request unsupported");
957 GNUNET_SCHEDULER_add_now (&do_error, handle);
962 * If listing is enabled, prints information about the egos.
964 * This function is initially called for all egos and then again
965 * whenever a ego's identifier changes or if it is deleted. At the
966 * end of the initial pass over all egos, the function is once called
967 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
968 * be invoked in the future or that there was an error.
970 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
971 * this function is only called ONCE, and 'NULL' being passed in
972 * 'ego' does indicate an error (i.e. name is taken or no default
973 * value is known). If 'ego' is non-NULL and if '*ctx'
974 * is set in those callbacks, the value WILL be passed to a subsequent
975 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
976 * that one was not NULL).
978 * When an identity is renamed, this function is called with the
979 * (known) ego but the NEW identifier.
981 * When an identity is deleted, this function is called with the
982 * (known) ego and "NULL" for the 'identifier'. In this case,
983 * the 'ego' is henceforth invalid (and the 'ctx' should also be
987 * @param ego ego handle
988 * @param ctx context for application to store data for this ego
989 * (during the lifetime of this process, initially NULL)
990 * @param identifier identifier assigned by the user for this ego,
991 * NULL if the user just deleted the ego and it
992 * must thus no longer be used
996 struct GNUNET_IDENTITY_Ego *ego,
998 const char *identifier)
1000 struct RequestHandle *handle = cls;
1001 struct EgoEntry *ego_entry;
1002 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1004 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1006 handle->state = ID_REST_STATE_POST_INIT;
1010 if (ID_REST_STATE_INIT == handle->state) {
1011 ego_entry = GNUNET_new (struct EgoEntry);
1012 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1013 ego_entry->keystring =
1014 GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
1015 ego_entry->ego = ego;
1016 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
1017 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
1023 * Function processing the REST call
1025 * @param method HTTP method
1026 * @param url URL of the HTTP request
1027 * @param data body of the HTTP request (optional)
1028 * @param data_size length of the body
1029 * @param proc callback function for the result
1030 * @param proc_cls closure for callback function
1031 * @return GNUNET_OK if request accepted
1034 rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
1035 GNUNET_REST_ResultProcessor proc,
1038 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1040 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1041 handle->proc_cls = proc_cls;
1042 handle->proc = proc;
1043 handle->state = ID_REST_STATE_INIT;
1044 handle->conndata_handle = conndata_handle;
1047 GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
1048 if (handle->url[strlen (handle->url)-1] == '/')
1049 handle->url[strlen (handle->url)-1] = '\0';
1050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1052 handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
1055 handle->timeout_task =
1056 GNUNET_SCHEDULER_add_delayed (handle->timeout,
1061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1066 * Entry point for the plugin.
1068 * @param cls Config info
1069 * @return NULL on error, otherwise the plugin context
1072 libgnunet_plugin_rest_identity_provider_init (void *cls)
1074 static struct Plugin plugin;
1075 struct GNUNET_REST_Plugin *api;
1078 if (NULL != plugin.cfg)
1079 return NULL; /* can only initialize once! */
1080 memset (&plugin, 0, sizeof (struct Plugin));
1082 api = GNUNET_new (struct GNUNET_REST_Plugin);
1084 api->name = GNUNET_REST_API_NS_IDENTITY_PROVIDER;
1085 api->process_request = &rest_identity_process_request;
1086 GNUNET_asprintf (&allow_methods,
1087 "%s, %s, %s, %s, %s",
1088 MHD_HTTP_METHOD_GET,
1089 MHD_HTTP_METHOD_POST,
1090 MHD_HTTP_METHOD_PUT,
1091 MHD_HTTP_METHOD_DELETE,
1092 MHD_HTTP_METHOD_OPTIONS);
1094 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1095 _("Identity Token REST API initialized\n"));
1101 * Exit point from the plugin.
1103 * @param cls the plugin context (as returned by "init")
1104 * @return always NULL
1107 libgnunet_plugin_rest_identity_provider_done (void *cls)
1109 struct GNUNET_REST_Plugin *api = cls;
1110 struct Plugin *plugin = api->cls;
1113 GNUNET_free_non_null (allow_methods);
1115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1116 "Identity Token REST plugin is finished\n");
1120 /* end of plugin_rest_gns.c */