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(ticket->rnd));
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(ticket->rnd));
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 (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&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 (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
696 GNUNET_RECLAIM_id_generate (&attribute->id);
697 handle->idp = GNUNET_RECLAIM_connect (cfg);
698 exp = GNUNET_TIME_UNIT_HOURS;
699 handle->idp_op = GNUNET_RECLAIM_attestation_store (handle->idp,
705 GNUNET_JSON_parse_free (attrspec);
709 * Collect all references for an ego
713 ref_collect (void *cls,
714 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
715 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
716 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
717 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
719 struct RequestHandle *handle = cls;
724 if (NULL == reference)
726 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
730 if ((NULL == reference->name) || (NULL == reference->reference_value))
735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference: %s\n",
737 attr_obj = json_object ();
738 json_object_set_new (attr_obj, "name", json_string (reference->name));
739 json_object_set_new (attr_obj, "ref_value", json_string (
740 reference->reference_value));
741 id_str = GNUNET_STRINGS_data_to_string_alloc (&reference->id,
742 sizeof(reference->id));
743 id_attest_str = GNUNET_STRINGS_data_to_string_alloc (&reference->id_attest,
744 sizeof(reference->id_attest));
745 json_object_set_new (attr_obj, "id", json_string (id_str));
746 json_object_set_new (attr_obj, "ref_id", json_string (id_attest_str));
747 json_array_append (handle->resp_object, attr_obj);
748 json_decref (attr_obj);
752 * Lists references for identity request
754 * @param con_handle the connection handle
756 * @param cls the RequestHandle
759 list_reference_cont (struct GNUNET_REST_RequestHandle *con_handle,
763 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
764 struct RequestHandle *handle = cls;
765 struct EgoEntry *ego_entry;
768 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
769 "Getting references for %s.\n",
771 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
772 "reference/") + 1 >= strlen (
775 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
776 GNUNET_SCHEDULER_add_now (&do_error, handle);
779 identity = handle->url + strlen (
780 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/")
782 for (ego_entry = handle->ego_head; NULL != ego_entry;
783 ego_entry = ego_entry->next)
784 if (0 == strcmp (identity, ego_entry->identifier))
786 handle->resp_object = json_array ();
788 if (NULL == ego_entry)
791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
792 GNUNET_SCHEDULER_add_now (&return_response, handle);
795 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
796 handle->idp = GNUNET_RECLAIM_connect (cfg);
797 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
803 &collect_finished_cb,
808 * Collect all attestations for an ego
812 attest_collect (void *cls,
813 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
814 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
815 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
816 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
818 struct RequestHandle *handle = cls;
825 if (NULL != reference)
827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
828 "Attestation Collection with Reference\n");
833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
834 "Attestation Collection with empty Attestation\n");
835 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
839 if ((NULL == attest->name) || (NULL == attest->data))
841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
842 "Attestation Collection with empty Name/Value\n");
843 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation: %s\n",
850 tmp_value = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
853 attr_obj = json_object ();
854 json_object_set_new (attr_obj, "value", json_string (tmp_value));
855 json_object_set_new (attr_obj, "name", json_string (attest->name));
856 type = GNUNET_RECLAIM_ATTESTATION_number_to_typename (attest->type);
857 json_object_set_new (attr_obj, "type", json_string (type));
858 id_str = GNUNET_STRINGS_data_to_string_alloc (&attest->id, sizeof(attest->id));
859 json_object_set_new (attr_obj, "id", json_string (id_str));
860 json_array_append (handle->resp_object, attr_obj);
861 json_decref (attr_obj);
862 GNUNET_free (tmp_value);
863 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
868 * Lists attestation for identity request
870 * @param con_handle the connection handle
872 * @param cls the RequestHandle
875 list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
879 struct RequestHandle *handle = cls;
880 /* Check for substring "reference" */
881 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
884 if ( strncmp ("reference/", (handle->url + strlen (
885 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
889 list_reference_cont (con_handle,url,cls);
893 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
894 struct EgoEntry *ego_entry;
897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
898 "Getting attestations for %s.\n",
900 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
903 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
904 GNUNET_SCHEDULER_add_now (&do_error, handle);
907 identity = handle->url + strlen (
908 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1;
910 for (ego_entry = handle->ego_head; NULL != ego_entry;
911 ego_entry = ego_entry->next)
912 if (0 == strcmp (identity, ego_entry->identifier))
914 handle->resp_object = json_array ();
917 if (NULL == ego_entry)
920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
921 GNUNET_SCHEDULER_add_now (&return_response, handle);
924 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
925 handle->idp = GNUNET_RECLAIM_connect (cfg);
926 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
932 &collect_finished_cb,
937 * Deletes reference from an identity
939 * @param con_handle the connection handle
941 * @param cls the RequestHandle
944 delete_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
948 struct RequestHandle *handle = cls;
949 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
950 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
951 struct EgoEntry *ego_entry;
953 char *identity_id_str;
955 char term_data[handle->rest_handle->data_size + 1];
959 struct GNUNET_JSON_Specification attrspec[] =
960 { GNUNET_RECLAIM_JSON_spec_claim_attest_ref (&attr),
961 GNUNET_JSON_spec_end () };
962 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
963 "Deleting attestation reference.\n");
964 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
965 "reference/") + 1 >= strlen (
968 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
969 GNUNET_SCHEDULER_add_now (&do_error, handle);
972 identity_id_str = strdup (handle->url + strlen (
973 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
974 + strlen ("reference/")
976 identity = strtok (identity_id_str, "/");
977 id = strtok (NULL, "/");
979 if ((NULL == identity) || (NULL == id))
981 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
982 GNUNET_SCHEDULER_add_now (&do_error, handle);
985 for (ego_entry = handle->ego_head; NULL != ego_entry;
986 ego_entry = ego_entry->next)
987 if (0 == strcmp (identity, ego_entry->identifier))
989 handle->resp_object = json_array ();
990 if (NULL == ego_entry)
992 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
993 GNUNET_SCHEDULER_add_now (&return_response, handle);
996 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
997 if (0 >= handle->rest_handle->data_size)
999 GNUNET_SCHEDULER_add_now (&do_error, handle);
1003 term_data[handle->rest_handle->data_size] = '\0';
1004 GNUNET_memcpy (term_data,
1005 handle->rest_handle->data,
1006 handle->rest_handle->data_size);
1007 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1008 GNUNET_assert (GNUNET_OK ==
1009 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
1010 json_decref (data_json);
1013 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1014 "Unable to parse attestation reference from %s\n",
1016 GNUNET_SCHEDULER_add_now (&do_error, handle);
1019 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr->id, sizeof(attr->id));
1021 handle->idp = GNUNET_RECLAIM_connect (cfg);
1022 handle->idp_op = GNUNET_RECLAIM_attestation_reference_delete (handle->idp,
1028 GNUNET_JSON_parse_free (attrspec);
1033 * Deletes attestation from an identity
1035 * @param con_handle the connection handle
1036 * @param url the url
1037 * @param cls the RequestHandle
1040 delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
1044 struct RequestHandle *handle = cls;
1045 /* Check for substring "reference" */
1046 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
1049 if ( strncmp ("reference", (handle->url + strlen (
1050 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
1054 delete_attestation_ref_cont (con_handle,url,cls);
1058 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1059 struct GNUNET_RECLAIM_ATTESTATION_Claim attr;
1060 struct EgoEntry *ego_entry;
1061 char *identity_id_str;
1065 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attestation.\n");
1066 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
1069 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1070 GNUNET_SCHEDULER_add_now (&do_error, handle);
1074 strdup (handle->url + strlen (
1075 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1);
1076 identity = strtok (identity_id_str, "/");
1077 id = strtok (NULL, "/");
1078 if ((NULL == identity) || (NULL == id))
1080 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
1081 GNUNET_free (identity_id_str);
1082 GNUNET_SCHEDULER_add_now (&do_error, handle);
1086 for (ego_entry = handle->ego_head; NULL != ego_entry;
1087 ego_entry = ego_entry->next)
1088 if (0 == strcmp (identity, ego_entry->identifier))
1090 handle->resp_object = json_array ();
1091 if (NULL == ego_entry)
1094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1095 GNUNET_free (identity_id_str);
1096 GNUNET_SCHEDULER_add_now (&return_response, handle);
1099 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1100 handle->idp = GNUNET_RECLAIM_connect (cfg);
1101 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim));
1102 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
1104 handle->idp_op = GNUNET_RECLAIM_attestation_delete (handle->idp,
1107 &delete_finished_cb,
1109 GNUNET_free (identity_id_str);
1113 * List tickets for identity request
1115 * @param con_handle the connection handle
1116 * @param url the url
1117 * @param cls the RequestHandle
1120 list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
1124 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1125 struct RequestHandle *handle = cls;
1126 struct EgoEntry *ego_entry;
1129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1130 "Getting tickets for %s.\n",
1132 if (strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= strlen (handle->url))
1134 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1135 GNUNET_SCHEDULER_add_now (&do_error, handle);
1138 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
1140 for (ego_entry = handle->ego_head; NULL != ego_entry;
1141 ego_entry = ego_entry->next)
1142 if (0 == strcmp (identity, ego_entry->identifier))
1144 handle->resp_object = json_array ();
1146 if (NULL == ego_entry)
1149 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1150 GNUNET_SCHEDULER_add_now (&return_response, handle);
1153 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1154 handle->idp = GNUNET_RECLAIM_connect (cfg);
1156 GNUNET_RECLAIM_ticket_iteration_start (handle->idp,
1162 &collect_finished_cb,
1168 add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1172 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
1173 const char *identity;
1174 struct RequestHandle *handle = cls;
1175 struct EgoEntry *ego_entry;
1176 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attribute;
1177 struct GNUNET_TIME_Relative exp;
1178 char term_data[handle->rest_handle->data_size + 1];
1181 struct GNUNET_JSON_Specification attrspec[] =
1182 { GNUNET_RECLAIM_JSON_spec_claim (&attribute), GNUNET_JSON_spec_end () };
1184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1185 "Adding an attribute for %s.\n",
1187 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1189 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1190 GNUNET_SCHEDULER_add_now (&do_error, handle);
1193 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
1195 for (ego_entry = handle->ego_head; NULL != ego_entry;
1196 ego_entry = ego_entry->next)
1197 if (0 == strcmp (identity, ego_entry->identifier))
1200 if (NULL == ego_entry)
1202 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
1205 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1207 if (0 >= handle->rest_handle->data_size)
1209 GNUNET_SCHEDULER_add_now (&do_error, handle);
1213 term_data[handle->rest_handle->data_size] = '\0';
1214 GNUNET_memcpy (term_data,
1215 handle->rest_handle->data,
1216 handle->rest_handle->data_size);
1217 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1218 GNUNET_assert (GNUNET_OK ==
1219 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
1220 json_decref (data_json);
1221 if (NULL == attribute)
1223 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1224 "Unable to parse attribute from %s\n",
1226 GNUNET_SCHEDULER_add_now (&do_error, handle);
1230 * New ID for attribute
1232 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
1233 GNUNET_RECLAIM_id_generate (&attribute->id);
1234 handle->idp = GNUNET_RECLAIM_connect (cfg);
1235 exp = GNUNET_TIME_UNIT_HOURS;
1236 handle->idp_op = GNUNET_RECLAIM_attribute_store (handle->idp,
1242 GNUNET_JSON_parse_free (attrspec);
1246 * Parse a JWT and return the respective claim value as Attribute
1248 * @param attest the jwt attestation
1249 * @param claim the name of the claim in the JWT
1251 * @return a GNUNET_RECLAIM_ATTRIBUTE_Claim, containing the new value
1253 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
1254 parse_jwt (const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1258 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
1260 const char *type_str = NULL;
1261 const char *val_str = NULL;
1265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
1268 json_error_t *json_err = NULL;
1270 jwt_string = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
1273 char *jwt_body = strtok (jwt_string, delim);
1274 jwt_body = strtok (NULL, delim);
1275 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
1276 (void **) &decoded_jwt);
1277 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
1280 json_object_foreach (json_val, key, value) {
1281 if (0 == strcasecmp (key,claim))
1283 val_str = json_dumps (value, JSON_ENCODE_ANY);
1286 type_str = "String";
1287 type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
1288 if (GNUNET_SYSERR ==(GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,val_str,
1292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1293 "Attribute value from JWT Parser invalid!\n");
1294 GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
1295 "Error: Referenced Claim Name not Found",
1298 attr = GNUNET_RECLAIM_ATTRIBUTE_claim_new (claim, type, data, data_size);
1299 attr->id = attest->id;
1304 attr = GNUNET_RECLAIM_ATTRIBUTE_claim_new (claim, type, data, data_size);
1305 attr->id = attest->id;
1313 * Collect all attributes for an ego
1317 attr_collect (void *cls,
1318 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1319 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
1320 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1321 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
1323 struct RequestHandle *handle = cls;
1328 if ((NULL == attr) && (NULL == reference))
1330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1331 "Attribute Collection with empty Attribute/Reference\n");
1332 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1339 if ((NULL == reference->name) || (NULL == reference->reference_value))
1341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1342 "Attribute Collection with empty Reference Name/Value\n");
1345 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr2;
1346 attr2 = parse_jwt (attest, reference->reference_value);
1349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1350 "Attribute Collection with unparsed Attestation\n");
1353 attr2->name = reference->name;
1354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference as attribute: %s\n",
1357 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr2->type,
1360 attr_obj = json_object ();
1362 json_object_set_new (attr_obj, "value", json_string (tmp_value));
1363 json_object_set_new (attr_obj, "name", json_string (attr2->name));
1364 json_object_set_new (attr_obj, "flag", json_string ("1"));
1365 type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr2->type);
1366 json_object_set_new (attr_obj, "type", json_string (type));
1367 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr2->id,
1369 json_object_set_new (attr_obj, "id", json_string (id_str));
1370 json_array_append (handle->resp_object, attr_obj);
1371 json_decref (attr_obj);
1372 GNUNET_free (tmp_value);
1376 if ((NULL == attr->name) || (NULL == attr->data))
1378 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1379 "Attribute Collection with empty Attribute Name/Value\n");
1380 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
1387 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
1391 attr_obj = json_object ();
1392 json_object_set_new (attr_obj, "value", json_string (tmp_value));
1393 json_object_set_new (attr_obj, "name", json_string (attr->name));
1394 GNUNET_asprintf (&flag_str,"%d",attr->flag);
1395 json_object_set_new (attr_obj, "flag", json_string (flag_str));
1396 type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
1397 json_object_set_new (attr_obj, "type", json_string (type));
1398 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
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(attr.id));
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 */