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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @author Martin Schanzenbach
22 * @author Philippe Buschmann
23 * @file reclaim/plugin_rest_reclaim.c
24 * @brief GNUnet reclaim REST plugin
28 #include "microhttpd.h"
31 #include "gnunet_gns_service.h"
32 #include "gnunet_gnsrecord_lib.h"
33 #include "gnunet_identity_service.h"
34 #include "gnunet_reclaim_attribute_lib.h"
35 #include "gnunet_reclaim_service.h"
36 #include "gnunet_rest_lib.h"
37 #include "gnunet_rest_plugin.h"
38 #include "gnunet_signatures.h"
39 #include "json_reclaim.h"
43 #define GNUNET_REST_API_NS_RECLAIM "/reclaim"
48 #define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
51 * Attestation namespace
53 #define GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE "/reclaim/attestation"
58 #define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
63 #define GNUNET_REST_API_NS_IDENTITY_REVOKE "/reclaim/revoke"
68 #define GNUNET_REST_API_NS_IDENTITY_CONSUME "/reclaim/consume"
71 * State while collecting all egos
73 #define ID_REST_STATE_INIT 0
76 * Done collecting egos
78 #define ID_REST_STATE_POST_INIT 1
81 * The configuration handle
83 const struct GNUNET_CONFIGURATION_Handle *cfg;
86 * HTTP methods allows for this plugin
88 static char *allow_methods;
91 * @brief struct returned by the initialization function of the plugin
95 const struct GNUNET_CONFIGURATION_Handle *cfg;
106 struct EgoEntry *next;
111 struct EgoEntry *prev;
126 struct GNUNET_IDENTITY_Ego *ego;
135 struct EgoEntry *ego_head;
140 struct EgoEntry *ego_tail;
145 struct EgoEntry *ego_entry;
148 * Pointer to ego private key
150 struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
153 * The processing state
158 * Handle to Identity service.
160 struct GNUNET_IDENTITY_Handle *identity_handle;
165 struct GNUNET_REST_RequestHandle *rest_handle;
168 * Attribute claim list
170 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
175 struct GNUNET_IDENTITY_Operation *op;
180 struct GNUNET_RECLAIM_Handle *idp;
185 struct GNUNET_RECLAIM_Operation *idp_op;
190 struct GNUNET_RECLAIM_AttributeIterator *attr_it;
195 struct GNUNET_RECLAIM_TicketIterator *ticket_it;
200 struct GNUNET_RECLAIM_Ticket ticket;
203 * Desired timeout for the lookup (default is no timeout).
205 struct GNUNET_TIME_Relative timeout;
208 * ID of a task associated with the resolution process.
210 struct GNUNET_SCHEDULER_Task *timeout_task;
213 * The plugin result processor
215 GNUNET_REST_ResultProcessor proc;
218 * The closure of the result processor
228 * Error response message
244 * Cleanup lookup handle
245 * @param handle Handle to clean up
248 cleanup_handle (struct RequestHandle *handle)
250 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
251 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
252 struct EgoEntry *ego_entry;
253 struct EgoEntry *ego_tmp;
255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
256 if (NULL != handle->resp_object)
257 json_decref (handle->resp_object);
258 if (NULL != handle->timeout_task)
259 GNUNET_SCHEDULER_cancel (handle->timeout_task);
260 if (NULL != handle->identity_handle)
261 GNUNET_IDENTITY_disconnect (handle->identity_handle);
262 if (NULL != handle->attr_it)
263 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
264 if (NULL != handle->ticket_it)
265 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
266 if (NULL != handle->idp)
267 GNUNET_RECLAIM_disconnect (handle->idp);
268 if (NULL != handle->url)
269 GNUNET_free (handle->url);
270 if (NULL != handle->emsg)
271 GNUNET_free (handle->emsg);
272 if (NULL != handle->attr_list)
274 for (claim_entry = handle->attr_list->list_head; NULL != claim_entry;)
276 claim_tmp = claim_entry;
277 claim_entry = claim_entry->next;
278 GNUNET_free (claim_tmp->claim);
279 GNUNET_free (claim_tmp->attest);
280 GNUNET_free (claim_tmp->reference);
281 GNUNET_free (claim_tmp);
283 GNUNET_free (handle->attr_list);
285 for (ego_entry = handle->ego_head; NULL != ego_entry;)
288 ego_entry = ego_entry->next;
289 GNUNET_free (ego_tmp->identifier);
290 GNUNET_free (ego_tmp->keystring);
291 GNUNET_free (ego_tmp);
293 GNUNET_free (handle);
298 cleanup_handle_delayed (void *cls)
300 cleanup_handle (cls);
305 * Task run on error, sends error message. Cleans up everything.
307 * @param cls the `struct RequestHandle`
312 struct RequestHandle *handle = cls;
313 struct MHD_Response *resp;
316 GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", handle->emsg);
317 if (0 == handle->response_code)
319 handle->response_code = MHD_HTTP_BAD_REQUEST;
321 resp = GNUNET_REST_create_response (json_error);
322 MHD_add_response_header (resp, "Content-Type", "application/json");
323 handle->proc (handle->proc_cls, resp, handle->response_code);
324 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
325 GNUNET_free (json_error);
330 * Task run on timeout, sends error message. Cleans up everything.
332 * @param cls the `struct RequestHandle`
335 do_timeout (void *cls)
337 struct RequestHandle *handle = cls;
339 handle->timeout_task = NULL;
345 collect_error_cb (void *cls)
347 struct RequestHandle *handle = cls;
354 finished_cont (void *cls, int32_t success, const char *emsg)
356 struct RequestHandle *handle = cls;
357 struct MHD_Response *resp;
359 resp = GNUNET_REST_create_response (emsg);
360 if (GNUNET_OK != success)
362 GNUNET_SCHEDULER_add_now (&do_error, handle);
365 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
366 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
370 delete_finished_cb (void *cls, int32_t success, const char *emsg)
372 struct RequestHandle *handle = cls;
373 struct MHD_Response *resp;
375 resp = GNUNET_REST_create_response (emsg);
376 if (GNUNET_OK != success)
378 GNUNET_SCHEDULER_add_now (&do_error, handle);
381 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
382 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
386 * Return attributes for identity
388 * @param cls the request handle
391 return_response (void *cls)
394 struct RequestHandle *handle = cls;
395 struct MHD_Response *resp;
397 result_str = json_dumps (handle->resp_object, 0);
398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
399 resp = GNUNET_REST_create_response (result_str);
400 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
401 GNUNET_free (result_str);
402 cleanup_handle (handle);
407 collect_finished_cb (void *cls)
409 struct RequestHandle *handle = cls;
412 handle->attr_it = NULL;
413 handle->ticket_it = NULL;
414 GNUNET_SCHEDULER_add_now (&return_response, handle);
419 * Collect all attributes for an ego
423 ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
425 json_t *json_resource;
426 struct RequestHandle *handle = cls;
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
431 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(uint64_t));
432 json_resource = json_object ();
434 json_array_append (handle->resp_object, json_resource);
437 GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
439 GNUNET_CRYPTO_EcdsaPublicKey));
440 value = json_string (tmp);
441 json_object_set_new (json_resource, "issuer", value);
444 GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
446 GNUNET_CRYPTO_EcdsaPublicKey));
447 value = json_string (tmp);
448 json_object_set_new (json_resource, "audience", value);
450 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(uint64_t));
451 value = json_string (tmp);
452 json_object_set_new (json_resource, "rnd", value);
454 GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
459 add_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
463 struct RequestHandle *handle = cls;
464 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
465 const char *identity;
466 struct EgoEntry *ego_entry;
467 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attribute;
468 struct GNUNET_TIME_Relative exp;
469 char term_data[handle->rest_handle->data_size + 1];
472 struct GNUNET_JSON_Specification attrspec[] =
473 { GNUNET_RECLAIM_JSON_spec_claim_attest_ref (&attribute),
474 GNUNET_JSON_spec_end () };
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Adding an attestation reference for %s.\n",
478 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
479 "reference/") + 1 >= strlen (
482 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
483 GNUNET_SCHEDULER_add_now (&do_error, handle);
486 identity = handle->url + strlen (
487 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/")
489 for (ego_entry = handle->ego_head; NULL != ego_entry;
490 ego_entry = ego_entry->next)
491 if (0 == strcmp (identity, ego_entry->identifier))
493 if (NULL == ego_entry)
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
498 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
499 if (0 >= handle->rest_handle->data_size)
501 GNUNET_SCHEDULER_add_now (&do_error, handle);
505 term_data[handle->rest_handle->data_size] = '\0';
506 GNUNET_memcpy (term_data,
507 handle->rest_handle->data,
508 handle->rest_handle->data_size);
509 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
510 GNUNET_assert (GNUNET_OK ==
511 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
512 json_decref (data_json);
513 if (NULL == attribute)
515 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
516 "Unable to parse attestation reference from %s\n",
518 GNUNET_SCHEDULER_add_now (&do_error, handle);
522 * New ID for attribute
524 if (0 == attribute->id)
525 attribute->id = attribute->id_attest;
526 handle->idp = GNUNET_RECLAIM_connect (cfg);
527 exp = GNUNET_TIME_UNIT_HOURS;
528 handle->idp_op = GNUNET_RECLAIM_attestation_reference_store (handle->idp,
534 GNUNET_JSON_parse_free (attrspec);
538 parse_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
542 struct RequestHandle *handle = cls;
544 char term_data[handle->rest_handle->data_size + 1];
548 struct MHD_Response *resp;
549 char *val_str = NULL;
550 const char *type_str = NULL;
551 term_data[handle->rest_handle->data_size] = '\0';
552 GNUNET_memcpy (term_data,
553 handle->rest_handle->data,
554 handle->rest_handle->data_size);
555 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
556 GNUNET_assert (NULL != data_json);
557 if (! json_is_object (data_json))
559 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560 "Error json is not array nor object!\n");
561 GNUNET_SCHEDULER_add_now (&do_error, handle);
564 unpack_state = json_unpack (data_json,
570 if ((0 != unpack_state) || (NULL == val_str) || (NULL == type_str))
572 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
573 "Error json object has a wrong format!\n");
574 GNUNET_SCHEDULER_add_now (&do_error, handle);
577 if (0 == strcmp (type_str, "JWT"))
579 // The value is a JWT
582 char *jwt_body = strtok (val_str, delim);
583 jwt_body = strtok (NULL, delim);
584 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
585 (void **) &decoded_jwt);
586 resp = GNUNET_REST_create_response (decoded_jwt);
587 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
588 GNUNET_free (decoded_jwt);
592 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
593 "Error requested parsing type not supported!\n");
594 GNUNET_SCHEDULER_add_now (&do_error, handle);
597 cleanup_handle (handle);
598 json_decref (data_json);
602 add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
606 struct RequestHandle *handle = cls;
607 /* Check for substring "reference" */
608 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
611 if ( strncmp ("reference/", (handle->url + strlen (
612 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
616 add_attestation_ref_cont (con_handle,url,cls);
620 /* Check for substring "parse" */
621 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
624 if ( strncmp ("parse", (handle->url + strlen (
625 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
629 parse_attestation_cont (con_handle,url,cls);
633 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
634 const char *identity;
635 struct EgoEntry *ego_entry;
636 struct GNUNET_RECLAIM_ATTESTATION_Claim *attribute;
637 struct GNUNET_TIME_Relative exp;
638 char term_data[handle->rest_handle->data_size + 1];
641 struct GNUNET_JSON_Specification attrspec[] =
642 { GNUNET_RECLAIM_JSON_spec_claim_attest (&attribute),
643 GNUNET_JSON_spec_end () };
645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
646 "Adding an attestation for %s.\n",
648 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
651 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
652 GNUNET_SCHEDULER_add_now (&do_error, handle);
655 identity = handle->url + strlen (
656 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1;
658 for (ego_entry = handle->ego_head; NULL != ego_entry;
659 ego_entry = ego_entry->next)
660 if (0 == strcmp (identity, ego_entry->identifier))
663 if (NULL == ego_entry)
665 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
668 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
670 if (0 >= handle->rest_handle->data_size)
672 GNUNET_SCHEDULER_add_now (&do_error, handle);
676 term_data[handle->rest_handle->data_size] = '\0';
677 GNUNET_memcpy (term_data,
678 handle->rest_handle->data,
679 handle->rest_handle->data_size);
680 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
681 GNUNET_assert (GNUNET_OK ==
682 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
683 json_decref (data_json);
684 if (NULL == attribute)
686 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
687 "Unable to parse attestation from %s\n",
689 GNUNET_SCHEDULER_add_now (&do_error, handle);
693 * New ID for attribute
695 if (0 == attribute->id)
697 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
698 handle->idp = GNUNET_RECLAIM_connect (cfg);
699 exp = GNUNET_TIME_UNIT_HOURS;
700 handle->idp_op = GNUNET_RECLAIM_attestation_store (handle->idp,
706 GNUNET_JSON_parse_free (attrspec);
710 * Collect all references for an ego
714 ref_collect (void *cls,
715 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
716 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
717 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
718 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
720 struct RequestHandle *handle = cls;
725 if (NULL == reference)
727 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
731 if ((NULL == reference->name) || (NULL == reference->reference_value))
736 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference: %s\n",
738 attr_obj = json_object ();
739 json_object_set_new (attr_obj, "name", json_string (reference->name));
740 json_object_set_new (attr_obj, "ref_value", json_string (
741 reference->reference_value));
742 id_str = GNUNET_STRINGS_data_to_string_alloc (&reference->id,
744 id_attest_str = GNUNET_STRINGS_data_to_string_alloc (&reference->id_attest,
746 json_object_set_new (attr_obj, "id", json_string (id_str));
747 json_object_set_new (attr_obj, "ref_id", json_string (id_attest_str));
748 json_array_append (handle->resp_object, attr_obj);
749 json_decref (attr_obj);
753 * Lists references for identity request
755 * @param con_handle the connection handle
757 * @param cls the RequestHandle
760 list_reference_cont (struct GNUNET_REST_RequestHandle *con_handle,
764 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
765 struct RequestHandle *handle = cls;
766 struct EgoEntry *ego_entry;
769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
770 "Getting references for %s.\n",
772 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
773 "reference/") + 1 >= strlen (
776 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
777 GNUNET_SCHEDULER_add_now (&do_error, handle);
780 identity = handle->url + strlen (
781 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/")
783 for (ego_entry = handle->ego_head; NULL != ego_entry;
784 ego_entry = ego_entry->next)
785 if (0 == strcmp (identity, ego_entry->identifier))
787 handle->resp_object = json_array ();
789 if (NULL == ego_entry)
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
793 GNUNET_SCHEDULER_add_now (&return_response, handle);
796 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
797 handle->idp = GNUNET_RECLAIM_connect (cfg);
798 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
804 &collect_finished_cb,
809 * Collect all attestations for an ego
813 attest_collect (void *cls,
814 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
815 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
816 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
817 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
819 struct RequestHandle *handle = cls;
826 if (NULL != reference)
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829 "Attestation Collection with Reference\n");
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
835 "Attestation Collection with empty Attestation\n");
836 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
840 if ((NULL == attest->name) || (NULL == attest->data))
842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
843 "Attestation Collection with empty Name/Value\n");
844 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
848 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation: %s\n",
851 tmp_value = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
854 attr_obj = json_object ();
855 json_object_set_new (attr_obj, "value", json_string (tmp_value));
856 json_object_set_new (attr_obj, "name", json_string (attest->name));
857 type = GNUNET_RECLAIM_ATTESTATION_number_to_typename (attest->type);
858 json_object_set_new (attr_obj, "type", json_string (type));
859 id_str = GNUNET_STRINGS_data_to_string_alloc (&attest->id, sizeof(uint64_t));
860 json_object_set_new (attr_obj, "id", json_string (id_str));
861 json_array_append (handle->resp_object, attr_obj);
862 json_decref (attr_obj);
863 GNUNET_free (tmp_value);
864 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
869 * Lists attestation for identity request
871 * @param con_handle the connection handle
873 * @param cls the RequestHandle
876 list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
880 struct RequestHandle *handle = cls;
881 /* Check for substring "reference" */
882 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
885 if ( strncmp ("reference/", (handle->url + strlen (
886 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
890 list_reference_cont (con_handle,url,cls);
894 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
895 struct EgoEntry *ego_entry;
898 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
899 "Getting attestations for %s.\n",
901 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
904 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
905 GNUNET_SCHEDULER_add_now (&do_error, handle);
908 identity = handle->url + strlen (
909 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1;
911 for (ego_entry = handle->ego_head; NULL != ego_entry;
912 ego_entry = ego_entry->next)
913 if (0 == strcmp (identity, ego_entry->identifier))
915 handle->resp_object = json_array ();
918 if (NULL == ego_entry)
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
922 GNUNET_SCHEDULER_add_now (&return_response, handle);
925 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
926 handle->idp = GNUNET_RECLAIM_connect (cfg);
927 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
933 &collect_finished_cb,
938 * Deletes reference from an identity
940 * @param con_handle the connection handle
942 * @param cls the RequestHandle
945 delete_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
949 struct RequestHandle *handle = cls;
950 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
951 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
952 struct EgoEntry *ego_entry;
954 char *identity_id_str;
956 char term_data[handle->rest_handle->data_size + 1];
960 struct GNUNET_JSON_Specification attrspec[] =
961 { GNUNET_RECLAIM_JSON_spec_claim_attest_ref (&attr),
962 GNUNET_JSON_spec_end () };
963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
964 "Deleting attestation reference.\n");
965 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
966 "reference/") + 1 >= strlen (
969 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
970 GNUNET_SCHEDULER_add_now (&do_error, handle);
973 identity_id_str = strdup (handle->url + strlen (
974 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
975 + strlen ("reference/")
977 identity = strtok (identity_id_str, "/");
978 id = strtok (NULL, "/");
980 if ((NULL == identity) || (NULL == id))
982 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
983 GNUNET_SCHEDULER_add_now (&do_error, handle);
986 for (ego_entry = handle->ego_head; NULL != ego_entry;
987 ego_entry = ego_entry->next)
988 if (0 == strcmp (identity, ego_entry->identifier))
990 handle->resp_object = json_array ();
991 if (NULL == ego_entry)
993 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
994 GNUNET_SCHEDULER_add_now (&return_response, handle);
997 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
998 if (0 >= handle->rest_handle->data_size)
1000 GNUNET_SCHEDULER_add_now (&do_error, handle);
1004 term_data[handle->rest_handle->data_size] = '\0';
1005 GNUNET_memcpy (term_data,
1006 handle->rest_handle->data,
1007 handle->rest_handle->data_size);
1008 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1009 GNUNET_assert (GNUNET_OK ==
1010 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
1011 json_decref (data_json);
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1015 "Unable to parse attestation reference from %s\n",
1017 GNUNET_SCHEDULER_add_now (&do_error, handle);
1020 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr->id, sizeof(uint64_t));
1022 handle->idp = GNUNET_RECLAIM_connect (cfg);
1023 handle->idp_op = GNUNET_RECLAIM_attestation_reference_delete (handle->idp,
1029 GNUNET_JSON_parse_free (attrspec);
1034 * Deletes attestation from an identity
1036 * @param con_handle the connection handle
1037 * @param url the url
1038 * @param cls the RequestHandle
1041 delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
1045 struct RequestHandle *handle = cls;
1046 /* Check for substring "reference" */
1047 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
1050 if ( strncmp ("reference", (handle->url + strlen (
1051 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
1055 delete_attestation_ref_cont (con_handle,url,cls);
1059 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1060 struct GNUNET_RECLAIM_ATTESTATION_Claim attr;
1061 struct EgoEntry *ego_entry;
1062 char *identity_id_str;
1066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attestation.\n");
1067 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
1070 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1071 GNUNET_SCHEDULER_add_now (&do_error, handle);
1075 strdup (handle->url + strlen (
1076 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1);
1077 identity = strtok (identity_id_str, "/");
1078 id = strtok (NULL, "/");
1079 if ((NULL == identity) || (NULL == id))
1081 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
1082 GNUNET_free (identity_id_str);
1083 GNUNET_SCHEDULER_add_now (&do_error, handle);
1087 for (ego_entry = handle->ego_head; NULL != ego_entry;
1088 ego_entry = ego_entry->next)
1089 if (0 == strcmp (identity, ego_entry->identifier))
1091 handle->resp_object = json_array ();
1092 if (NULL == ego_entry)
1095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1096 GNUNET_free (identity_id_str);
1097 GNUNET_SCHEDULER_add_now (&return_response, handle);
1100 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1101 handle->idp = GNUNET_RECLAIM_connect (cfg);
1102 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim));
1103 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(uint64_t));
1105 handle->idp_op = GNUNET_RECLAIM_attestation_delete (handle->idp,
1108 &delete_finished_cb,
1110 GNUNET_free (identity_id_str);
1114 * List tickets for identity request
1116 * @param con_handle the connection handle
1117 * @param url the url
1118 * @param cls the RequestHandle
1121 list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
1125 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1126 struct RequestHandle *handle = cls;
1127 struct EgoEntry *ego_entry;
1130 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1131 "Getting tickets for %s.\n",
1133 if (strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= strlen (handle->url))
1135 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1136 GNUNET_SCHEDULER_add_now (&do_error, handle);
1139 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
1141 for (ego_entry = handle->ego_head; NULL != ego_entry;
1142 ego_entry = ego_entry->next)
1143 if (0 == strcmp (identity, ego_entry->identifier))
1145 handle->resp_object = json_array ();
1147 if (NULL == ego_entry)
1150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1151 GNUNET_SCHEDULER_add_now (&return_response, handle);
1154 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1155 handle->idp = GNUNET_RECLAIM_connect (cfg);
1157 GNUNET_RECLAIM_ticket_iteration_start (handle->idp,
1163 &collect_finished_cb,
1169 add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1173 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
1174 const char *identity;
1175 struct RequestHandle *handle = cls;
1176 struct EgoEntry *ego_entry;
1177 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attribute;
1178 struct GNUNET_TIME_Relative exp;
1179 char term_data[handle->rest_handle->data_size + 1];
1182 struct GNUNET_JSON_Specification attrspec[] =
1183 { GNUNET_RECLAIM_JSON_spec_claim (&attribute), GNUNET_JSON_spec_end () };
1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1186 "Adding an attribute for %s.\n",
1188 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1190 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1191 GNUNET_SCHEDULER_add_now (&do_error, handle);
1194 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
1196 for (ego_entry = handle->ego_head; NULL != ego_entry;
1197 ego_entry = ego_entry->next)
1198 if (0 == strcmp (identity, ego_entry->identifier))
1201 if (NULL == ego_entry)
1203 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
1206 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1208 if (0 >= handle->rest_handle->data_size)
1210 GNUNET_SCHEDULER_add_now (&do_error, handle);
1214 term_data[handle->rest_handle->data_size] = '\0';
1215 GNUNET_memcpy (term_data,
1216 handle->rest_handle->data,
1217 handle->rest_handle->data_size);
1218 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1219 GNUNET_assert (GNUNET_OK ==
1220 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
1221 json_decref (data_json);
1222 if (NULL == attribute)
1224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1225 "Unable to parse attribute from %s\n",
1227 GNUNET_SCHEDULER_add_now (&do_error, handle);
1231 * New ID for attribute
1233 if (0 == attribute->id)
1235 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
1236 handle->idp = GNUNET_RECLAIM_connect (cfg);
1237 exp = GNUNET_TIME_UNIT_HOURS;
1238 handle->idp_op = GNUNET_RECLAIM_attribute_store (handle->idp,
1244 GNUNET_JSON_parse_free (attrspec);
1248 * Parse a JWT and return the respective claim value as Attribute
1250 * @param attest the jwt attestation
1251 * @param claim the name of the claim in the JWT
1253 * @return a GNUNET_RECLAIM_ATTRIBUTE_Claim, containing the new value
1255 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
1256 parse_jwt (const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1260 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
1262 const char *type_str = NULL;
1263 const char *val_str = NULL;
1267 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
1270 json_error_t *json_err = NULL;
1272 jwt_string = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
1275 char *jwt_body = strtok (jwt_string, delim);
1276 jwt_body = strtok (NULL, delim);
1277 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
1278 (void **) &decoded_jwt);
1279 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
1282 json_object_foreach (json_val, key, value) {
1283 if (0 == strcasecmp (key,claim))
1285 val_str = json_dumps (value, JSON_ENCODE_ANY);
1288 type_str = "String";
1289 type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
1290 if (GNUNET_SYSERR ==(GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,val_str,
1294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1295 "Attribute value from JWT Parser invalid!\n");
1296 GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
1297 "Error: Referenced Claim Name not Found",
1300 attr = GNUNET_RECLAIM_ATTRIBUTE_claim_new (claim, type, data, data_size);
1301 attr->id = attest->id;
1306 attr = GNUNET_RECLAIM_ATTRIBUTE_claim_new (claim, type, data, data_size);
1307 attr->id = attest->id;
1315 * Collect all attributes for an ego
1319 attr_collect (void *cls,
1320 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1321 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
1322 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1323 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
1325 struct RequestHandle *handle = cls;
1330 if ((NULL == attr) && (NULL == reference))
1332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1333 "Attribute Collection with empty Attribute/Reference\n");
1334 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1341 if ((NULL == reference->name) || (NULL == reference->reference_value))
1343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1344 "Attribute Collection with empty Reference Name/Value\n");
1347 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr2;
1348 attr2 = parse_jwt (attest, reference->reference_value);
1351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1352 "Attribute Collection with unparsed Attestation\n");
1355 attr2->name = reference->name;
1356 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference as attribute: %s\n",
1359 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr2->type,
1362 attr_obj = json_object ();
1364 json_object_set_new (attr_obj, "value", json_string (tmp_value));
1365 json_object_set_new (attr_obj, "name", json_string (attr2->name));
1366 json_object_set_new (attr_obj, "flag", json_string ("1"));
1367 type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr2->type);
1368 json_object_set_new (attr_obj, "type", json_string (type));
1369 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr2->id, sizeof(uint64_t));
1370 json_object_set_new (attr_obj, "id", json_string (id_str));
1371 json_array_append (handle->resp_object, attr_obj);
1372 json_decref (attr_obj);
1373 GNUNET_free (tmp_value);
1377 if ((NULL == attr->name) || (NULL == attr->data))
1379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1380 "Attribute Collection with empty Attribute Name/Value\n");
1381 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
1388 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
1392 attr_obj = json_object ();
1393 json_object_set_new (attr_obj, "value", json_string (tmp_value));
1394 json_object_set_new (attr_obj, "name", json_string (attr->name));
1395 GNUNET_asprintf (&flag_str,"%d",attr->flag);
1396 json_object_set_new (attr_obj, "flag", json_string (flag_str));
1397 type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
1398 json_object_set_new (attr_obj, "type", json_string (type));
1399 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(uint64_t));
1400 json_object_set_new (attr_obj, "id", json_string (id_str));
1401 json_array_append (handle->resp_object, attr_obj);
1402 json_decref (attr_obj);
1403 GNUNET_free (tmp_value);
1404 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1409 * List attributes for identity request
1411 * @param con_handle the connection handle
1412 * @param url the url
1413 * @param cls the RequestHandle
1416 list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1420 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1421 struct RequestHandle *handle = cls;
1422 struct EgoEntry *ego_entry;
1425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1426 "Getting attributes for %s.\n",
1428 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1430 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1431 GNUNET_SCHEDULER_add_now (&do_error, handle);
1434 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
1436 for (ego_entry = handle->ego_head; NULL != ego_entry;
1437 ego_entry = ego_entry->next)
1438 if (0 == strcmp (identity, ego_entry->identifier))
1440 handle->resp_object = json_array ();
1443 if (NULL == ego_entry)
1446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1447 GNUNET_SCHEDULER_add_now (&return_response, handle);
1450 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1451 handle->idp = GNUNET_RECLAIM_connect (cfg);
1452 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
1458 &collect_finished_cb,
1464 * List attributes for identity request
1466 * @param con_handle the connection handle
1467 * @param url the url
1468 * @param cls the RequestHandle
1471 delete_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1475 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1476 struct RequestHandle *handle = cls;
1477 struct GNUNET_RECLAIM_ATTRIBUTE_Claim attr;
1478 struct EgoEntry *ego_entry;
1479 char *identity_id_str;
1483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attributes.\n");
1484 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1487 GNUNET_SCHEDULER_add_now (&do_error, handle);
1491 strdup (handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1);
1492 identity = strtok (identity_id_str, "/");
1493 id = strtok (NULL, "/");
1494 if ((NULL == identity) || (NULL == id))
1496 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
1497 GNUNET_free (identity_id_str);
1498 GNUNET_SCHEDULER_add_now (&do_error, handle);
1502 for (ego_entry = handle->ego_head; NULL != ego_entry;
1503 ego_entry = ego_entry->next)
1504 if (0 == strcmp (identity, ego_entry->identifier))
1506 handle->resp_object = json_array ();
1507 if (NULL == ego_entry)
1510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1511 GNUNET_free (identity_id_str);
1512 GNUNET_SCHEDULER_add_now (&return_response, handle);
1515 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1516 handle->idp = GNUNET_RECLAIM_connect (cfg);
1517 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim));
1518 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(uint64_t));
1520 handle->idp_op = GNUNET_RECLAIM_attribute_delete (handle->idp,
1523 &delete_finished_cb,
1525 GNUNET_free (identity_id_str);
1530 revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1534 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
1535 struct RequestHandle *handle = cls;
1536 struct EgoEntry *ego_entry;
1537 struct GNUNET_RECLAIM_Ticket *ticket = NULL;
1538 struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
1539 char term_data[handle->rest_handle->data_size + 1];
1542 struct GNUNET_JSON_Specification tktspec[] =
1543 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1545 if (0 >= handle->rest_handle->data_size)
1547 GNUNET_SCHEDULER_add_now (&do_error, handle);
1551 term_data[handle->rest_handle->data_size] = '\0';
1552 GNUNET_memcpy (term_data,
1553 handle->rest_handle->data,
1554 handle->rest_handle->data_size);
1555 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1556 if ((NULL == data_json) ||
1557 (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL)))
1559 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1560 GNUNET_SCHEDULER_add_now (&do_error, handle);
1561 GNUNET_JSON_parse_free (tktspec);
1562 if (NULL != data_json)
1563 json_decref (data_json);
1566 json_decref (data_json);
1569 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1570 "Unable to parse ticket from %s\n",
1572 GNUNET_SCHEDULER_add_now (&do_error, handle);
1576 for (ego_entry = handle->ego_head; NULL != ego_entry;
1577 ego_entry = ego_entry->next)
1579 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1580 if (0 == memcmp (&ticket->identity,
1582 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
1585 if (NULL == ego_entry)
1587 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1588 GNUNET_JSON_parse_free (tktspec);
1591 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1593 handle->idp = GNUNET_RECLAIM_connect (cfg);
1594 handle->idp_op = GNUNET_RECLAIM_ticket_revoke (handle->idp,
1599 GNUNET_JSON_parse_free (tktspec);
1604 consume_cont (void *cls,
1605 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1606 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
1607 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1608 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
1610 struct RequestHandle *handle = cls;
1614 if (NULL == identity)
1616 GNUNET_SCHEDULER_add_now (&return_response, handle);
1620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
1621 val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
1624 if (NULL == val_str)
1626 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1627 "Failed to parse value for: %s\n",
1631 value = json_string (val_str);
1632 json_object_set_new (handle->resp_object, attr->name, value);
1633 json_decref (value);
1634 GNUNET_free (val_str);
1639 consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1643 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
1644 struct RequestHandle *handle = cls;
1645 struct EgoEntry *ego_entry;
1646 struct GNUNET_RECLAIM_Ticket *ticket;
1647 struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
1648 char term_data[handle->rest_handle->data_size + 1];
1651 struct GNUNET_JSON_Specification tktspec[] =
1652 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1654 if (0 >= handle->rest_handle->data_size)
1656 GNUNET_SCHEDULER_add_now (&do_error, handle);
1660 term_data[handle->rest_handle->data_size] = '\0';
1661 GNUNET_memcpy (term_data,
1662 handle->rest_handle->data,
1663 handle->rest_handle->data_size);
1664 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1665 if (NULL == data_json)
1667 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1668 "Unable to parse JSON Object from %s\n",
1670 GNUNET_SCHEDULER_add_now (&do_error, handle);
1673 if (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL))
1675 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1676 GNUNET_SCHEDULER_add_now (&do_error, handle);
1677 GNUNET_JSON_parse_free (tktspec);
1678 json_decref (data_json);
1681 for (ego_entry = handle->ego_head; NULL != ego_entry;
1682 ego_entry = ego_entry->next)
1684 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1685 if (0 == memcmp (&ticket->audience,
1687 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
1690 if (NULL == ego_entry)
1692 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1693 GNUNET_JSON_parse_free (tktspec);
1696 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1697 handle->resp_object = json_object ();
1698 handle->idp = GNUNET_RECLAIM_connect (cfg);
1699 handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
1704 GNUNET_JSON_parse_free (tktspec);
1709 * Respond to OPTIONS request
1711 * @param con_handle the connection handle
1712 * @param url the url
1713 * @param cls the RequestHandle
1716 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1720 struct MHD_Response *resp;
1721 struct RequestHandle *handle = cls;
1723 // For now, independent of path return all options
1724 resp = GNUNET_REST_create_response (NULL);
1725 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1726 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1727 cleanup_handle (handle);
1733 * Handle rest request
1735 * @param handle the request handle
1738 init_cont (struct RequestHandle *handle)
1740 struct GNUNET_REST_RequestHandlerError err;
1741 static const struct GNUNET_REST_RequestHandler handlers[] =
1742 { { MHD_HTTP_METHOD_GET,
1743 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES,
1744 &list_attribute_cont },
1745 { MHD_HTTP_METHOD_POST,
1746 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES,
1747 &add_attribute_cont },
1748 { MHD_HTTP_METHOD_DELETE,
1749 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES,
1750 &delete_attribute_cont },
1751 { MHD_HTTP_METHOD_GET,
1752 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
1753 &list_attestation_cont },
1754 { MHD_HTTP_METHOD_POST,
1755 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
1756 &add_attestation_cont },
1757 { MHD_HTTP_METHOD_DELETE,
1758 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
1759 &delete_attestation_cont },
1760 { MHD_HTTP_METHOD_GET,
1761 GNUNET_REST_API_NS_IDENTITY_TICKETS,
1762 &list_tickets_cont },
1763 { MHD_HTTP_METHOD_POST,
1764 GNUNET_REST_API_NS_IDENTITY_REVOKE,
1765 &revoke_ticket_cont },
1766 { MHD_HTTP_METHOD_POST,
1767 GNUNET_REST_API_NS_IDENTITY_CONSUME,
1768 &consume_ticket_cont },
1769 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
1770 GNUNET_REST_HANDLER_END };
1773 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1775 handle->response_code = err.error_code;
1776 GNUNET_SCHEDULER_add_now (&do_error, handle);
1782 * If listing is enabled, prints information about the egos.
1784 * This function is initially called for all egos and then again
1785 * whenever a ego's identifier changes or if it is deleted. At the
1786 * end of the initial pass over all egos, the function is once called
1787 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
1788 * be invoked in the future or that there was an error.
1790 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
1791 * this function is only called ONCE, and 'NULL' being passed in
1792 * 'ego' does indicate an error (i.e. name is taken or no default
1793 * value is known). If 'ego' is non-NULL and if '*ctx'
1794 * is set in those callbacks, the value WILL be passed to a subsequent
1795 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
1796 * that one was not NULL).
1798 * When an identity is renamed, this function is called with the
1799 * (known) ego but the NEW identifier.
1801 * When an identity is deleted, this function is called with the
1802 * (known) ego and "NULL" for the 'identifier'. In this case,
1803 * the 'ego' is henceforth invalid (and the 'ctx' should also be
1806 * @param cls closure
1807 * @param ego ego handle
1808 * @param ctx context for application to store data for this ego
1809 * (during the lifetime of this process, initially NULL)
1810 * @param identifier identifier assigned by the user for this ego,
1811 * NULL if the user just deleted the ego and it
1812 * must thus no longer be used
1815 list_ego (void *cls,
1816 struct GNUNET_IDENTITY_Ego *ego,
1818 const char *identifier)
1820 struct RequestHandle *handle = cls;
1821 struct EgoEntry *ego_entry;
1822 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1824 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1826 handle->state = ID_REST_STATE_POST_INIT;
1830 if (ID_REST_STATE_INIT == handle->state)
1832 ego_entry = GNUNET_new (struct EgoEntry);
1833 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1834 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
1835 ego_entry->ego = ego;
1836 ego_entry->identifier = GNUNET_strdup (identifier);
1837 GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
1845 rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1846 GNUNET_REST_ResultProcessor proc,
1849 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1851 handle->response_code = 0;
1852 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1853 handle->proc_cls = proc_cls;
1854 handle->proc = proc;
1855 handle->state = ID_REST_STATE_INIT;
1856 handle->rest_handle = rest_handle;
1858 handle->url = GNUNET_strdup (rest_handle->url);
1859 if (handle->url[strlen (handle->url) - 1] == '/')
1860 handle->url[strlen (handle->url) - 1] = '\0';
1861 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1862 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, handle);
1863 handle->timeout_task =
1864 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
1865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1870 * Entry point for the plugin.
1872 * @param cls Config info
1873 * @return NULL on error, otherwise the plugin context
1876 libgnunet_plugin_rest_reclaim_init (void *cls)
1878 static struct Plugin plugin;
1879 struct GNUNET_REST_Plugin *api;
1882 if (NULL != plugin.cfg)
1883 return NULL; /* can only initialize once! */
1884 memset (&plugin, 0, sizeof(struct Plugin));
1886 api = GNUNET_new (struct GNUNET_REST_Plugin);
1888 api->name = GNUNET_REST_API_NS_RECLAIM;
1889 api->process_request = &rest_identity_process_request;
1890 GNUNET_asprintf (&allow_methods,
1891 "%s, %s, %s, %s, %s",
1892 MHD_HTTP_METHOD_GET,
1893 MHD_HTTP_METHOD_POST,
1894 MHD_HTTP_METHOD_PUT,
1895 MHD_HTTP_METHOD_DELETE,
1896 MHD_HTTP_METHOD_OPTIONS);
1898 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1899 _ ("Identity Provider REST API initialized\n"));
1905 * Exit point from the plugin.
1907 * @param cls the plugin context (as returned by "init")
1908 * @return always NULL
1911 libgnunet_plugin_rest_reclaim_done (void *cls)
1913 struct GNUNET_REST_Plugin *api = cls;
1914 struct Plugin *plugin = api->cls;
1918 GNUNET_free_non_null (allow_methods);
1920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1921 "Identity Provider REST plugin is finished\n");
1926 /* end of plugin_rest_reclaim.c */