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 "gnunet_jsonapi_lib.h"
35 #include "microhttpd.h"
38 #include "gnunet_signatures.h"
39 #include "gnunet_identity_provider_service.h"
44 #define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp"
49 #define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/idp/issue"
52 * Check namespace TODO
54 #define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/idp/check"
59 #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token"
62 * The parameter name in which the ticket must be provided
64 #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket"
67 * The parameter name in which the expected nonce must be provided
69 #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce"
72 * The parameter name in which the ticket must be provided
74 #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token"
77 * The URL parameter name in which the nonce must be provided
79 #define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce"
82 * State while collecting all egos
84 #define ID_REST_STATE_INIT 0
87 * Done collecting egos
89 #define ID_REST_STATE_POST_INIT 1
94 #define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
97 * URL parameter to create a GNUid token for a specific audience
99 #define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
102 * URL parameter to create a GNUid token for a specific issuer (EGO)
104 #define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
107 * Attributes passed to issue request
109 #define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
112 * Token expiration string
114 #define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
119 #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
120 #define GNUNET_REST_ERROR_NO_DATA "No data"
123 * GNUid token lifetime
125 #define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
128 * The configuration handle
130 const struct GNUNET_CONFIGURATION_Handle *cfg;
133 * HTTP methods allows for this plugin
135 static char* allow_methods;
138 * @brief struct returned by the initialization function of the plugin
142 const struct GNUNET_CONFIGURATION_Handle *cfg;
153 struct EgoEntry *next;
158 struct EgoEntry *prev;
173 struct GNUNET_IDENTITY_Ego *ego;
182 struct EgoEntry *ego_head;
187 struct EgoEntry *ego_tail;
192 struct EgoEntry *ego_entry;
195 * Ptr to current ego private key
197 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
200 * Handle to the rest connection
202 struct GNUNET_REST_RequestHandle *conndata_handle;
205 * The processing state
210 * Handle to Identity service.
212 struct GNUNET_IDENTITY_Handle *identity_handle;
217 struct GNUNET_IDENTITY_Operation *op;
222 struct GNUNET_IDENTITY_PROVIDER_Handle *idp;
227 struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
230 * Handle to NS service
232 struct GNUNET_NAMESTORE_Handle *ns_handle;
237 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
242 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
245 * Desired timeout for the lookup (default is no timeout).
247 struct GNUNET_TIME_Relative timeout;
250 * ID of a task associated with the resolution process.
252 struct GNUNET_SCHEDULER_Task *timeout_task;
255 * The plugin result processor
257 GNUNET_REST_ResultProcessor proc;
260 * The closure of the result processor
270 * Error response message
282 struct GNUNET_JSONAPI_Object *resp_object;
288 * Cleanup lookup handle
289 * @param handle Handle to clean up
292 cleanup_handle (struct RequestHandle *handle)
294 struct EgoEntry *ego_entry;
295 struct EgoEntry *ego_tmp;
296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
298 if (NULL != handle->resp_object)
299 GNUNET_JSONAPI_object_delete (handle->resp_object);
300 if (NULL != handle->timeout_task)
301 GNUNET_SCHEDULER_cancel (handle->timeout_task);
302 if (NULL != handle->identity_handle)
303 GNUNET_IDENTITY_disconnect (handle->identity_handle);
304 if (NULL != handle->idp)
305 GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
306 if (NULL != handle->ns_it)
307 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
308 if (NULL != handle->ns_qe)
309 GNUNET_NAMESTORE_cancel (handle->ns_qe);
310 if (NULL != handle->ns_handle)
311 GNUNET_NAMESTORE_disconnect (handle->ns_handle);
312 if (NULL != handle->url)
313 GNUNET_free (handle->url);
314 if (NULL != handle->emsg)
315 GNUNET_free (handle->emsg);
316 for (ego_entry = handle->ego_head;
320 ego_entry = ego_entry->next;
321 GNUNET_free (ego_tmp->identifier);
322 GNUNET_free (ego_tmp->keystring);
323 GNUNET_free (ego_tmp);
325 GNUNET_free (handle);
330 * Task run on error, sends error message. Cleans up everything.
332 * @param cls the `struct RequestHandle`
337 struct RequestHandle *handle = cls;
338 struct MHD_Response *resp;
341 GNUNET_asprintf (&json_error,
342 "{Error while processing request: %s}",
344 resp = GNUNET_REST_create_json_response (json_error);
345 handle->proc (handle->proc_cls, resp, handle->response_code);
346 cleanup_handle (handle);
347 GNUNET_free (json_error);
351 * Task run on timeout, sends error message. Cleans up everything.
353 * @param cls the `struct RequestHandle`
356 do_timeout (void *cls)
358 struct RequestHandle *handle = cls;
360 handle->timeout_task = NULL;
366 * Task run on shutdown. Cleans up everything.
371 do_cleanup_handle_delayed (void *cls)
373 struct RequestHandle *handle = cls;
375 cleanup_handle (handle);
380 * Get a ticket for identity
381 * @param cls the handle
382 * @param ticket the ticket returned from the idp
385 token_creat_cont (void *cls,
387 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
388 const struct GNUNET_IDENTITY_PROVIDER_Token *token)
390 struct GNUNET_JSONAPI_Resource *json_resource;
391 struct RequestHandle *handle = cls;
392 struct MHD_Response *resp;
401 handle->emsg = GNUNET_strdup ("Error in token issue");
402 GNUNET_SCHEDULER_add_now (&do_error, handle);
406 handle->resp_object = GNUNET_JSONAPI_object_new ();
407 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
409 ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
410 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
411 ticket_json = json_string (ticket_str);
412 token_json = json_string (token_str);
413 GNUNET_JSONAPI_resource_add_attr (json_resource,
414 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
416 GNUNET_JSONAPI_resource_add_attr (json_resource,
417 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN,
419 GNUNET_free (ticket_str);
420 GNUNET_free (token_str);
421 json_decref (ticket_json);
422 json_decref (token_json);
423 GNUNET_JSONAPI_object_resource_add (handle->resp_object, json_resource);
425 GNUNET_JSONAPI_data_serialize (handle->resp_object, &result_str);
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
427 resp = GNUNET_REST_create_json_response (result_str);
428 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
429 GNUNET_free (result_str);
430 GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle);
435 * Continueationf for token issue request
437 * @param con the Rest handle
438 * @param url the requested url
439 * @param cls the request handle
442 issue_token_cont (struct GNUNET_REST_RequestHandle *con,
446 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
449 struct RequestHandle *handle = cls;
450 struct EgoEntry *ego_entry;
451 struct GNUNET_HashCode key;
452 struct MHD_Response *resp;
453 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
454 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
455 struct GNUNET_TIME_Relative etime_rel;
456 struct GNUNET_TIME_Absolute exp_time;
465 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
466 GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
468 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
469 resp = GNUNET_REST_create_json_response (NULL);
470 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
471 cleanup_handle (handle);
476 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
477 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
480 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
483 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
484 "Issuer not found\n");
485 GNUNET_SCHEDULER_add_now (&do_error, handle);
488 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
492 GNUNET_SCHEDULER_add_now (&do_error, handle);
493 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
498 for (ego_entry = handle->ego_head;
500 ego_entry = ego_entry->next)
502 if (0 != strcmp (ego_val, ego_entry->identifier))
504 egoname = ego_entry->identifier;
507 if ( (NULL == egoname) ||
508 (NULL == ego_entry) )
510 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
511 "Ego not found: %s\n",
513 GNUNET_SCHEDULER_add_now (&do_error, handle);
516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
517 "Ego to issue token for: %s\n",
522 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST,
523 strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST),
528 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
531 handle->emsg = GNUNET_strdup ("Scopes missing!\n");
532 GNUNET_SCHEDULER_add_now (&do_error, handle);
535 scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
540 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
541 strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
545 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
548 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
549 "Audience missing!\n");
550 GNUNET_SCHEDULER_add_now (&do_error, handle);
553 audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
556 "Audience to issue token for: %s\n",
559 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
560 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
562 GNUNET_STRINGS_string_to_data (audience,
565 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
569 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
570 strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
573 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
576 handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
577 GNUNET_SCHEDULER_add_now (&do_error, handle);
580 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
582 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
583 "Request nonce: %s\n",
585 sscanf (nonce_str, "%"SCNu64, &nonce);
587 //Get expiration for token from URL parameter
588 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
589 strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING),
593 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
596 exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
599 if (NULL == exp_str) {
600 handle->emsg = GNUNET_strdup ("No expiration given!\n");
601 GNUNET_SCHEDULER_add_now (&do_error, handle);
606 GNUNET_STRINGS_fancy_time_to_relative (exp_str,
609 handle->emsg = GNUNET_strdup ("Expiration invalid!\n");
610 GNUNET_SCHEDULER_add_now (&do_error, handle);
613 time = GNUNET_TIME_absolute_get().abs_value_us;
614 exp_time.abs_value_us = time + etime_rel.rel_value_us;
616 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
617 handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp,
630 * Build a GNUid token for identity
632 * @param cls the request handle
635 return_token_list (void *cls)
638 struct RequestHandle *handle = cls;
639 struct MHD_Response *resp;
641 GNUNET_JSONAPI_data_serialize (handle->resp_object, &result_str);
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
643 resp = GNUNET_REST_create_json_response (result_str);
644 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
645 GNUNET_free (result_str);
646 cleanup_handle (handle);
650 * Collect all tokens for an ego
652 * TODO move this into the identity-provider service
656 token_collect (void *cls,
657 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
659 unsigned int rd_count,
660 const struct GNUNET_GNSRECORD_Data *rd)
664 struct RequestHandle *handle = cls;
665 struct EgoEntry *ego_tmp;
666 struct GNUNET_JSONAPI_Resource *json_resource;
667 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
673 ego_tmp = handle->ego_head;
674 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
677 GNUNET_free (ego_tmp->identifier);
678 GNUNET_free (ego_tmp->keystring);
679 GNUNET_free (ego_tmp);
681 if (NULL == handle->ego_head)
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
685 handle->ns_it = NULL;
686 GNUNET_SCHEDULER_add_now (&return_token_list, handle);
690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Next ego: %s\n", handle->ego_head->identifier);
691 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
692 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
699 for (i = 0; i < rd_count; i++)
701 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
703 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
707 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
709 issuer = json_string (handle->ego_head->identifier);
710 GNUNET_JSONAPI_resource_add_attr (json_resource,
711 GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
713 json_decref (issuer);
714 token = json_string (data);
715 GNUNET_JSONAPI_resource_add_attr (json_resource,
716 GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
720 GNUNET_JSONAPI_object_resource_add (handle->resp_object, json_resource);
725 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
731 * Respond to OPTIONS request
733 * @param con_handle the connection handle
735 * @param cls the RequestHandle
738 list_token_cont (struct GNUNET_REST_RequestHandle *con_handle,
743 struct GNUNET_HashCode key;
744 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
745 struct RequestHandle *handle = cls;
746 struct EgoEntry *ego_entry;
747 struct EgoEntry *ego_tmp;
749 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
750 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
754 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No issuer given.\n");
758 GNUNET_SCHEDULER_add_now (&do_error, handle);
761 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
763 //Remove non-matching egos
764 for (ego_entry = handle->ego_head;
768 ego_entry = ego_entry->next;
769 if (0 != strcmp (ego_val, ego_tmp->identifier))
771 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
774 GNUNET_free (ego_tmp->identifier);
775 GNUNET_free (ego_tmp->keystring);
776 GNUNET_free (ego_tmp);
779 handle->resp_object = GNUNET_JSONAPI_object_new ();
780 if (NULL == handle->ego_head)
783 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n");
784 GNUNET_SCHEDULER_add_now (&return_token_list, handle);
787 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
788 handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
789 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
797 * Return token to requestor
799 * @param cls request handle
800 * @param token the token
803 exchange_cont (void *cls,
804 const struct GNUNET_IDENTITY_PROVIDER_Token *token,
805 uint64_t ticket_nonce)
808 struct RequestHandle *handle = cls;
809 struct MHD_Response *resp;
810 struct GNUNET_HashCode key;
814 uint64_t expected_nonce;
817 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE,
818 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE),
822 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
825 handle->emsg = GNUNET_strdup ("No nonce given.");
826 GNUNET_SCHEDULER_add_now (&do_error, handle);
829 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
831 GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
833 if (ticket_nonce != expected_nonce)
835 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
836 "Ticket nonce %lu does not match expected nonce %lu\n",
837 ticket_nonce, expected_nonce);
838 handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n");
839 GNUNET_SCHEDULER_add_now (&do_error, handle);
843 root = json_object ();
844 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
845 json_object_set_new (root, "token", json_string (token_str));
846 json_object_set_new (root, "token_type", json_string ("jwt"));
847 GNUNET_free (token_str);
849 result = json_dumps (root, JSON_INDENT(1));
850 resp = GNUNET_REST_create_json_response (result);
851 GNUNET_free (result);
852 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
853 cleanup_handle (handle);
860 * Callback called when identity for token exchange has been found
862 * @param cls request handle
863 * @param ego the identity to use as issuer
864 * @param ctx user context
865 * @param name identity name
869 exchange_token_ticket_cb (void *cls,
870 struct GNUNET_IDENTITY_Ego *ego,
874 struct RequestHandle *handle = cls;
875 struct GNUNET_HashCode key;
876 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
883 handle->emsg = GNUNET_strdup ("No identity found.");
884 GNUNET_SCHEDULER_add_now (&do_error, handle);
889 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
890 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET),
894 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
897 handle->emsg = GNUNET_strdup ("No ticket given.");
898 GNUNET_SCHEDULER_add_now (&do_error, handle);
901 ticket_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
903 handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego);
904 GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str,
907 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
908 handle->idp_op = GNUNET_IDENTITY_PROVIDER_exchange_ticket (handle->idp,
913 GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket);
920 * Respond to issue request
922 * @param con_handle the connection handle
924 * @param cls the RequestHandle
927 exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
931 struct RequestHandle *handle = cls;
934 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
936 &exchange_token_ticket_cb,
941 * Respond to OPTIONS request
943 * @param con_handle the connection handle
945 * @param cls the RequestHandle
948 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
952 struct MHD_Response *resp;
953 struct RequestHandle *handle = cls;
955 //For now, independent of path return all options
956 resp = GNUNET_REST_create_json_response (NULL);
957 MHD_add_response_header (resp,
958 "Access-Control-Allow-Methods",
960 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
961 cleanup_handle (handle);
966 * Handle rest request
968 * @param handle the request handle
971 init_cont (struct RequestHandle *handle)
973 struct GNUNET_REST_RequestHandlerError err;
974 static const struct GNUNET_REST_RequestHandler handlers[] = {
975 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont},
976 //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont},
977 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont},
978 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &options_cont},
979 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont},
980 GNUNET_REST_HANDLER_END
983 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle,
988 handle->response_code = err.error_code;
989 GNUNET_SCHEDULER_add_now (&do_error, handle);
994 * If listing is enabled, prints information about the egos.
996 * This function is initially called for all egos and then again
997 * whenever a ego's identifier changes or if it is deleted. At the
998 * end of the initial pass over all egos, the function is once called
999 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
1000 * be invoked in the future or that there was an error.
1002 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
1003 * this function is only called ONCE, and 'NULL' being passed in
1004 * 'ego' does indicate an error (i.e. name is taken or no default
1005 * value is known). If 'ego' is non-NULL and if '*ctx'
1006 * is set in those callbacks, the value WILL be passed to a subsequent
1007 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
1008 * that one was not NULL).
1010 * When an identity is renamed, this function is called with the
1011 * (known) ego but the NEW identifier.
1013 * When an identity is deleted, this function is called with the
1014 * (known) ego and "NULL" for the 'identifier'. In this case,
1015 * the 'ego' is henceforth invalid (and the 'ctx' should also be
1018 * @param cls closure
1019 * @param ego ego handle
1020 * @param ctx context for application to store data for this ego
1021 * (during the lifetime of this process, initially NULL)
1022 * @param identifier identifier assigned by the user for this ego,
1023 * NULL if the user just deleted the ego and it
1024 * must thus no longer be used
1027 list_ego (void *cls,
1028 struct GNUNET_IDENTITY_Ego *ego,
1030 const char *identifier)
1032 struct RequestHandle *handle = cls;
1033 struct EgoEntry *ego_entry;
1034 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1036 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1038 handle->state = ID_REST_STATE_POST_INIT;
1042 if (ID_REST_STATE_INIT == handle->state) {
1043 ego_entry = GNUNET_new (struct EgoEntry);
1044 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1045 ego_entry->keystring =
1046 GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
1047 ego_entry->ego = ego;
1048 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
1049 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
1055 * Function processing the REST call
1057 * @param method HTTP method
1058 * @param url URL of the HTTP request
1059 * @param data body of the HTTP request (optional)
1060 * @param data_size length of the body
1061 * @param proc callback function for the result
1062 * @param proc_cls closure for callback function
1063 * @return GNUNET_OK if request accepted
1066 rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1067 GNUNET_REST_ResultProcessor proc,
1070 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1072 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1073 handle->proc_cls = proc_cls;
1074 handle->proc = proc;
1075 handle->state = ID_REST_STATE_INIT;
1076 handle->conndata_handle = conndata_handle;
1079 GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
1080 if (handle->url[strlen (handle->url)-1] == '/')
1081 handle->url[strlen (handle->url)-1] = '\0';
1082 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1084 handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
1087 handle->timeout_task =
1088 GNUNET_SCHEDULER_add_delayed (handle->timeout,
1091 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1096 * Entry point for the plugin.
1098 * @param cls Config info
1099 * @return NULL on error, otherwise the plugin context
1102 libgnunet_plugin_rest_identity_provider_init (void *cls)
1104 static struct Plugin plugin;
1105 struct GNUNET_REST_Plugin *api;
1108 if (NULL != plugin.cfg)
1109 return NULL; /* can only initialize once! */
1110 memset (&plugin, 0, sizeof (struct Plugin));
1112 api = GNUNET_new (struct GNUNET_REST_Plugin);
1114 api->name = GNUNET_REST_API_NS_IDENTITY_PROVIDER;
1115 api->process_request = &rest_identity_process_request;
1116 GNUNET_asprintf (&allow_methods,
1117 "%s, %s, %s, %s, %s",
1118 MHD_HTTP_METHOD_GET,
1119 MHD_HTTP_METHOD_POST,
1120 MHD_HTTP_METHOD_PUT,
1121 MHD_HTTP_METHOD_DELETE,
1122 MHD_HTTP_METHOD_OPTIONS);
1124 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1125 _("Identity Token REST API initialized\n"));
1131 * Exit point from the plugin.
1133 * @param cls the plugin context (as returned by "init")
1134 * @return always NULL
1137 libgnunet_plugin_rest_identity_provider_done (void *cls)
1139 struct GNUNET_REST_Plugin *api = cls;
1140 struct Plugin *plugin = api->cls;
1143 GNUNET_free_non_null (allow_methods);
1145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1146 "Identity Token REST plugin is finished\n");
1150 /* end of plugin_rest_gns.c */