2 This file is part of GNUnet.
3 Copyright (C) 2012-2016 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 * @file credential/plugin_rest_credential.c
23 * @brief GNUnet CREDENTIAL REST plugin
28 #include "gnunet_rest_plugin.h"
29 #include <gnunet_identity_service.h>
30 #include <gnunet_gnsrecord_lib.h>
31 #include <gnunet_namestore_service.h>
32 #include <gnunet_credential_service.h>
33 #include <gnunet_rest_lib.h>
34 #include <gnunet_jsonapi_lib.h>
35 #include <gnunet_jsonapi_util.h>
38 #define GNUNET_REST_API_NS_CREDENTIAL "/credential"
40 #define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
42 #define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
44 #define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
46 #define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
48 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
50 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
52 #define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
54 #define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
56 #define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
58 #define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
60 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
63 * @brief struct returned by the initialization function of the plugin
67 const struct GNUNET_CONFIGURATION_Handle *cfg;
70 const struct GNUNET_CONFIGURATION_Handle *cfg;
75 * Handle to Credential service.
77 struct GNUNET_CREDENTIAL_Handle *credential;
80 * Handle to lookup request
82 struct GNUNET_CREDENTIAL_Request *verify_request;
85 * Handle to issue request
87 struct GNUNET_CREDENTIAL_Request *issue_request;
92 struct GNUNET_IDENTITY_Handle *identity;
95 * Handle to identity operation
97 struct GNUNET_IDENTITY_Operation *id_op;
100 * Handle to ego lookup
102 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
105 * Handle to rest request
107 struct GNUNET_REST_RequestHandle *rest_handle;
110 * ID of a task associated with the resolution process.
112 struct GNUNET_SCHEDULER_Task *timeout_task;
115 * The root of the received JSON or NULL
120 * The plugin result processor
122 GNUNET_REST_ResultProcessor proc;
125 * The closure of the result processor
130 * The issuer attribute to verify
135 * The subject attribute
140 * The public key of the issuer
142 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
145 * The public key of the subject
147 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
157 struct GNUNET_TIME_Relative timeout;
162 * Cleanup lookup handle.
164 * @param handle Handle to clean up
167 cleanup_handle (struct RequestHandle *handle)
169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
171 if (NULL != handle->json_root)
172 json_decref (handle->json_root);
174 if (NULL != handle->issuer_attr)
175 GNUNET_free (handle->issuer_attr);
176 if (NULL != handle->subject_attr)
177 GNUNET_free (handle->subject_attr);
178 if (NULL != handle->verify_request)
179 GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
180 if (NULL != handle->credential)
181 GNUNET_CREDENTIAL_disconnect (handle->credential);
182 if (NULL != handle->id_op)
183 GNUNET_IDENTITY_cancel (handle->id_op);
184 if (NULL != handle->ego_lookup)
185 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
186 if (NULL != handle->identity)
187 GNUNET_IDENTITY_disconnect (handle->identity);
188 if (NULL != handle->timeout_task)
190 GNUNET_SCHEDULER_cancel (handle->timeout_task);
192 GNUNET_free (handle);
199 struct RequestHandle *handle = cls;
200 struct MHD_Response *resp;
202 resp = GNUNET_REST_create_response (NULL);
203 handle->proc (handle->proc_cls, resp, handle->response_code);
204 cleanup_handle (handle);
208 * Attribute delegation to JSON
210 * @param delegation_chain_entry the DSE
211 * @return JSON, NULL if failed
214 attribute_delegation_to_json (struct
215 GNUNET_CREDENTIAL_Delegation *
216 delegation_chain_entry)
222 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (
223 &delegation_chain_entry->issuer_key);
226 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
227 "Issuer in delegation malformed\n");
230 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (
231 &delegation_chain_entry->subject_key);
234 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
235 "Subject in credential malformed\n");
236 GNUNET_free (issuer);
239 attr_obj = json_object ();
241 json_object_set_new (attr_obj, "issuer", json_string (issuer));
242 json_object_set_new (attr_obj, "issuer_attribute",
243 json_string (delegation_chain_entry->issuer_attribute));
245 json_object_set_new (attr_obj, "subject", json_string (subject));
246 if (0 < delegation_chain_entry->subject_attribute_len)
248 json_object_set_new (attr_obj, "subject_attribute",
250 delegation_chain_entry->subject_attribute));
252 GNUNET_free (issuer);
253 GNUNET_free (subject);
258 * JSONAPI resource to Credential
260 * @param res the JSONAPI resource
261 * @return the resulting credential, NULL if failed
263 static struct GNUNET_CREDENTIAL_Credential*
264 json_to_credential (json_t *res)
266 struct GNUNET_CREDENTIAL_Credential *cred;
268 const char *attribute;
269 const char *signature;
272 tmp = json_object_get (res, "attribute");
273 if (0 == json_is_string (tmp))
277 attribute = json_string_value (tmp);
278 cred = GNUNET_malloc (sizeof(struct GNUNET_CREDENTIAL_Credential)
279 + strlen (attribute));
280 cred->issuer_attribute = attribute;
281 cred->issuer_attribute_len = strlen (attribute);
282 tmp = json_object_get (res, "issuer");
283 if (0 == json_is_string (tmp))
289 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value (tmp),
290 strlen (json_string_value (tmp)),
292 tmp = json_object_get (res, "subject");
293 if (0 == json_is_string (tmp))
298 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value (tmp),
299 strlen (json_string_value (tmp)),
302 tmp = json_object_get (res, "signature");
303 if (0 == json_is_string (tmp))
308 signature = json_string_value (tmp);
309 GNUNET_STRINGS_base64_decode (signature,
312 GNUNET_memcpy (&cred->signature,
314 sizeof(struct GNUNET_CRYPTO_EcdsaSignature));
317 tmp = json_object_get (res, "expiration");
318 if (0 == json_is_integer (tmp))
323 cred->expiration.abs_value_us = json_integer_value (tmp);
331 * @param cred the credential
332 * @return the resulting json, NULL if failed
335 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
340 char attribute[cred->issuer_attribute_len + 1];
343 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
346 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
347 "Issuer in credential malformed\n");
350 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
353 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
354 "Subject in credential malformed\n");
355 GNUNET_free (issuer);
358 GNUNET_STRINGS_base64_encode ((char*) &cred->signature,
359 sizeof(struct GNUNET_CRYPTO_EcdsaSignature),
361 GNUNET_memcpy (attribute,
362 cred->issuer_attribute,
363 cred->issuer_attribute_len);
364 attribute[cred->issuer_attribute_len] = '\0';
365 cred_obj = json_object ();
366 json_object_set_new (cred_obj, "issuer", json_string (issuer));
367 json_object_set_new (cred_obj, "subject", json_string (subject));
368 json_object_set_new (cred_obj, "attribute", json_string (attribute));
369 json_object_set_new (cred_obj, "signature", json_string (signature));
370 json_object_set_new (cred_obj, "expiration", json_integer (
371 cred->expiration.abs_value_us));
372 GNUNET_free (issuer);
373 GNUNET_free (subject);
374 GNUNET_free (signature);
379 handle_collect_response (void *cls,
380 unsigned int d_count,
381 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
382 unsigned int c_count,
383 struct GNUNET_CREDENTIAL_Credential *cred)
385 struct RequestHandle *handle = cls;
386 struct MHD_Response *resp;
387 struct GNUNET_JSONAPI_Document *json_document;
388 struct GNUNET_JSONAPI_Resource *json_resource;
396 handle->verify_request = NULL;
399 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
401 handle->response_code = MHD_HTTP_NOT_FOUND;
402 GNUNET_SCHEDULER_add_now (&do_error, handle);
405 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
408 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
409 "Issuer in delegation malformed\n");
412 GNUNET_asprintf (&id,
415 handle->issuer_attr);
416 GNUNET_free (issuer);
417 json_document = GNUNET_JSONAPI_document_new ();
418 json_resource = GNUNET_JSONAPI_resource_new (
419 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
422 cred_array = json_array ();
423 for (i = 0; i < c_count; i++)
425 cred_obj = credential_to_json (&cred[i]);
426 json_array_append_new (cred_array, cred_obj);
428 GNUNET_JSONAPI_resource_add_attr (json_resource,
429 GNUNET_REST_JSONAPI_CREDENTIAL,
431 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
432 GNUNET_JSONAPI_document_serialize (json_document, &result);
433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
436 json_decref (cred_array);
437 GNUNET_JSONAPI_document_delete (json_document);
438 resp = GNUNET_REST_create_response (result);
439 GNUNET_free (result);
440 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
441 cleanup_handle (handle);
445 subject_ego_lookup (void *cls,
446 const struct GNUNET_IDENTITY_Ego *ego)
448 struct RequestHandle *handle = cls;
449 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
451 handle->ego_lookup = NULL;
455 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
456 "Subject not found\n");
457 GNUNET_SCHEDULER_add_now (&do_error, handle);
460 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
461 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
465 &handle_collect_response,
472 handle_verify_response (void *cls,
473 unsigned int d_count,
474 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
475 unsigned int c_count,
476 struct GNUNET_CREDENTIAL_Credential *cred)
478 struct RequestHandle *handle = cls;
479 struct MHD_Response *resp;
480 struct GNUNET_JSONAPI_Document *json_document;
481 struct GNUNET_JSONAPI_Resource *json_resource;
491 handle->verify_request = NULL;
494 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
496 handle->response_code = MHD_HTTP_NOT_FOUND;
497 GNUNET_SCHEDULER_add_now (&do_error, handle);
500 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
503 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
504 "Issuer in delegation malformed\n");
507 GNUNET_asprintf (&id,
510 handle->issuer_attr);
511 GNUNET_free (issuer);
512 json_document = GNUNET_JSONAPI_document_new ();
513 json_resource = GNUNET_JSONAPI_resource_new (
514 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
517 attr_array = json_array ();
518 for (i = 0; i < d_count; i++)
520 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
521 json_array_append_new (attr_array, attr_obj);
523 cred_array = json_array ();
524 for (i = 0; i < c_count; i++)
526 cred_obj = credential_to_json (&cred[i]);
527 json_array_append_new (cred_array, cred_obj);
529 GNUNET_JSONAPI_resource_add_attr (json_resource,
530 GNUNET_REST_JSONAPI_CREDENTIAL,
532 GNUNET_JSONAPI_resource_add_attr (json_resource,
533 GNUNET_REST_JSONAPI_DELEGATIONS,
535 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
536 GNUNET_JSONAPI_document_serialize (json_document, &result);
537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 json_decref (attr_array);
541 json_decref (cred_array);
542 GNUNET_JSONAPI_document_delete (json_document);
543 resp = GNUNET_REST_create_response (result);
544 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
545 GNUNET_free (result);
546 cleanup_handle (handle);
550 collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
554 struct RequestHandle *handle = cls;
555 struct GNUNET_HashCode key;
559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
561 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
562 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
564 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
566 if (NULL == handle->credential)
568 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
569 "Connecting to CREDENTIAL failed\n");
570 GNUNET_SCHEDULER_add_now (&do_error, handle);
573 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
574 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
577 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
580 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
581 "Missing issuer attribute\n");
582 GNUNET_SCHEDULER_add_now (&do_error, handle);
585 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
587 entity_attr = GNUNET_strdup (tmp);
588 tmp = strtok (entity_attr, ".");
591 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
592 "Malformed issuer or attribute\n");
593 GNUNET_free (entity_attr);
594 GNUNET_SCHEDULER_add_now (&do_error, handle);
598 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
600 &handle->issuer_key))
602 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603 "Malformed issuer key\n");
604 GNUNET_free (entity_attr);
605 GNUNET_SCHEDULER_add_now (&do_error, handle);
608 tmp = strtok (NULL, "."); // Issuer attribute
611 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
612 "Malformed attribute\n");
613 GNUNET_free (entity_attr);
614 GNUNET_SCHEDULER_add_now (&do_error, handle);
617 handle->issuer_attr = GNUNET_strdup (tmp);
618 GNUNET_free (entity_attr);
620 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
621 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
624 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
627 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
628 "Missing subject\n");
629 GNUNET_SCHEDULER_add_now (&do_error, handle);
632 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
636 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
637 "Malformed subject\n");
638 GNUNET_SCHEDULER_add_now (&do_error, handle);
641 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
650 verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
654 struct RequestHandle *handle = cls;
655 struct GNUNET_HashCode key;
656 struct GNUNET_JSONAPI_Document *json_obj;
657 struct GNUNET_JSONAPI_Resource *res;
658 struct GNUNET_CREDENTIAL_Credential *cred;
662 uint32_t credential_count;
663 uint32_t resource_count;
668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
670 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
671 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
675 if (NULL == handle->credential)
677 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
678 "Connecting to CREDENTIAL failed\n");
679 GNUNET_SCHEDULER_add_now (&do_error, handle);
682 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
683 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
686 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
689 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
690 "Missing issuer attribute\n");
691 GNUNET_SCHEDULER_add_now (&do_error, handle);
694 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
696 entity_attr = GNUNET_strdup (tmp);
697 tmp = strtok (entity_attr, ".");
700 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
701 "Malformed issuer or attribute\n");
702 GNUNET_free (entity_attr);
703 GNUNET_SCHEDULER_add_now (&do_error, handle);
707 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
709 &handle->issuer_key))
711 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
712 "Malformed issuer key\n");
713 GNUNET_free (entity_attr);
714 GNUNET_SCHEDULER_add_now (&do_error, handle);
717 tmp = strtok (NULL, "."); // Issuer attribute
720 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
721 "Malformed attribute\n");
722 GNUNET_free (entity_attr);
723 GNUNET_SCHEDULER_add_now (&do_error, handle);
726 handle->issuer_attr = GNUNET_strdup (tmp);
727 GNUNET_free (entity_attr);
729 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
730 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
733 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
736 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
737 "Missing subject key\n");
738 GNUNET_SCHEDULER_add_now (&do_error, handle);
741 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
745 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
746 "Malformed subject\n");
747 GNUNET_SCHEDULER_add_now (&do_error, handle);
751 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
753 &handle->subject_key))
755 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
756 "Malformed subject key\n");
757 GNUNET_SCHEDULER_add_now (&do_error, handle);
761 if (0 >= handle->rest_handle->data_size)
763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
764 "Missing credentials\n");
765 GNUNET_SCHEDULER_add_now (&do_error, handle);
769 struct GNUNET_JSON_Specification docspec[] = {
770 GNUNET_JSON_spec_jsonapi_document (&json_obj),
771 GNUNET_JSON_spec_end ()
773 char term_data[handle->rest_handle->data_size + 1];
774 term_data[handle->rest_handle->data_size] = '\0';
775 credential_count = 0;
776 GNUNET_memcpy (term_data,
777 handle->rest_handle->data,
778 handle->rest_handle->data_size);
779 data_js = json_loads (term_data,
782 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
784 json_decref (data_js);
785 if (NULL == json_obj)
787 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
788 "Unable to parse JSONAPI Object from %s\n",
790 GNUNET_SCHEDULER_add_now (&do_error, handle);
794 resource_count = GNUNET_JSONAPI_document_resource_count (json_obj);
795 GNUNET_assert (1 == resource_count);
796 res = (GNUNET_JSONAPI_document_get_resource (json_obj, 0));
797 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (res,
798 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
800 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
801 "Resource not a credential!\n");
802 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
803 "Unable to parse JSONAPI Object from %s\n",
805 GNUNET_JSONAPI_document_delete (json_obj);
806 GNUNET_SCHEDULER_add_now (&do_error, handle);
809 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
810 GNUNET_REST_JSONAPI_CREDENTIAL);
812 GNUNET_assert (json_is_array (cred_json));
814 credential_count = json_array_size (cred_json);
816 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
817 for (i = 0; i < credential_count; i++)
819 cred = json_to_credential (json_array_get (cred_json, i));
822 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
823 "Unable to parse credential!\n");
826 GNUNET_memcpy (&credentials[i],
828 sizeof(struct GNUNET_CREDENTIAL_Credential));
829 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
832 GNUNET_JSONAPI_document_delete (json_obj);
833 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
836 &handle->subject_key,
839 &handle_verify_response,
841 for (i = 0; i < credential_count; i++)
842 GNUNET_free ((char*) credentials[i].issuer_attribute);
846 send_cred_response (struct RequestHandle *handle,
847 struct GNUNET_CREDENTIAL_Credential *cred)
849 struct MHD_Response *resp;
850 struct GNUNET_JSONAPI_Document *json_document;
851 struct GNUNET_JSONAPI_Resource *json_resource;
859 GNUNET_assert (NULL != cred);
860 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
863 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
864 "Subject malformed\n");
865 GNUNET_free (issuer);
868 GNUNET_asprintf (&id,
872 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
875 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
876 "Subject malformed\n");
878 GNUNET_free (issuer);
881 GNUNET_STRINGS_base64_encode ((char*) &cred->signature,
882 sizeof(struct GNUNET_CRYPTO_EcdsaSignature),
884 json_document = GNUNET_JSONAPI_document_new ();
885 json_resource = GNUNET_JSONAPI_resource_new (
886 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
889 cred_obj = json_object ();
890 json_object_set_new (cred_obj, "issuer", json_string (issuer));
891 json_object_set_new (cred_obj, "subject", json_string (subject));
892 json_object_set_new (cred_obj, "expiration", json_integer (
893 cred->expiration.abs_value_us));
894 json_object_set_new (cred_obj, "signature", json_string (signature));
895 GNUNET_JSONAPI_resource_add_attr (json_resource,
896 GNUNET_REST_JSONAPI_CREDENTIAL,
898 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
899 GNUNET_JSONAPI_document_serialize (json_document, &result);
900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
903 json_decref (cred_obj);
904 GNUNET_JSONAPI_document_delete (json_document);
905 resp = GNUNET_REST_create_response (result);
906 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
907 GNUNET_free (result);
908 GNUNET_free (signature);
909 GNUNET_free (issuer);
910 GNUNET_free (subject);
911 cleanup_handle (handle);
915 get_cred_issuer_cb (void *cls,
916 struct GNUNET_IDENTITY_Ego *ego,
920 struct RequestHandle *handle = cls;
921 struct GNUNET_TIME_Absolute etime_abs;
922 struct GNUNET_TIME_Relative etime_rel;
923 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
924 struct GNUNET_HashCode key;
925 struct GNUNET_CREDENTIAL_Credential *cred;
929 handle->id_op = NULL;
933 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
934 "Issuer not configured!\n");
935 GNUNET_SCHEDULER_add_now (&do_error, handle);
939 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
940 "Connecting to credential service...\n");
941 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
942 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
944 if (NULL == handle->credential)
946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
947 "Connecting to CREDENTIAL failed\n");
948 GNUNET_SCHEDULER_add_now (&do_error, handle);
951 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
952 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
955 GNUNET_CONTAINER_multihashmap_contains (
956 handle->rest_handle->url_param_map,
959 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
960 "Missing expiration\n");
961 GNUNET_SCHEDULER_add_now (&do_error, handle);
964 expiration_str = GNUNET_CONTAINER_multihashmap_get (
965 handle->rest_handle->url_param_map,
967 if (NULL == expiration_str)
969 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
970 "Expiration malformed\n");
971 GNUNET_SCHEDULER_add_now (&do_error, handle);
975 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
978 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
980 else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
983 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
984 "Malformed expiration: %s\n", expiration_str);
985 GNUNET_SCHEDULER_add_now (&do_error, handle);
988 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
989 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
992 GNUNET_CONTAINER_multihashmap_contains (
993 handle->rest_handle->url_param_map,
996 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
997 "Missing issuer attribute\n");
998 GNUNET_SCHEDULER_add_now (&do_error, handle);
1001 handle->issuer_attr = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get
1002 (handle->rest_handle->url_param_map,
1004 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
1005 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
1008 GNUNET_CONTAINER_multihashmap_contains (
1009 handle->rest_handle->url_param_map,
1012 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1013 "Missing subject\n");
1014 GNUNET_SCHEDULER_add_now (&do_error, handle);
1017 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1021 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1022 "Malformed subject\n");
1023 GNUNET_SCHEDULER_add_now (&do_error, handle);
1027 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1029 &handle->subject_key))
1031 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1032 "Malformed subject key\n");
1033 GNUNET_SCHEDULER_add_now (&do_error, handle);
1036 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1037 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1038 &handle->subject_key,
1039 handle->issuer_attr,
1043 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1044 "Failed to create credential\n");
1045 GNUNET_SCHEDULER_add_now (&do_error, handle);
1048 send_cred_response (handle, cred);
1053 issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1057 struct RequestHandle *handle = cls;
1059 handle->identity = GNUNET_IDENTITY_connect (cfg,
1062 handle->id_op = GNUNET_IDENTITY_get (handle->identity,
1063 "credential-issuer",
1064 &get_cred_issuer_cb,
1066 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1072 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1076 struct MHD_Response *resp;
1077 struct RequestHandle *handle = cls;
1079 // For GNS, independent of path return all options
1080 resp = GNUNET_REST_create_response (NULL);
1081 MHD_add_response_header (resp,
1082 "Access-Control-Allow-Methods",
1083 MHD_HTTP_METHOD_GET);
1084 handle->proc (handle->proc_cls,
1087 cleanup_handle (handle);
1092 rest_credential_process_request (struct
1093 GNUNET_REST_RequestHandle *conndata_handle,
1094 GNUNET_REST_ResultProcessor proc,
1097 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1098 struct GNUNET_REST_RequestHandlerError err;
1100 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1101 handle->proc_cls = proc_cls;
1102 handle->proc = proc;
1103 handle->rest_handle = conndata_handle;
1105 static const struct GNUNET_REST_RequestHandler handlers[] = {
1106 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY,
1107 &verify_cred_cont },
1108 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT,
1109 &collect_cred_cont },
1110 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE,
1112 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont },
1113 GNUNET_REST_HANDLER_END
1116 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1121 handle->response_code = err.error_code;
1122 GNUNET_SCHEDULER_add_now (&do_error, handle);
1128 * Entry point for the plugin.
1130 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1131 * @return NULL on error, otherwise the plugin context
1134 libgnunet_plugin_rest_credential_init (void *cls)
1136 static struct Plugin plugin;
1139 struct GNUNET_REST_Plugin *api;
1141 if (NULL != plugin.cfg)
1142 return NULL; /* can only initialize once! */
1143 memset (&plugin, 0, sizeof(struct Plugin));
1145 api = GNUNET_new (struct GNUNET_REST_Plugin);
1147 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1148 api->process_request = &rest_credential_process_request;
1149 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1150 _ ("GNS REST API initialized\n"));
1156 * Exit point from the plugin.
1158 * @param cls the plugin context (as returned by "init")
1159 * @return always NULL
1162 libgnunet_plugin_rest_credential_done (void *cls)
1164 struct GNUNET_REST_Plugin *api = cls;
1165 struct Plugin *plugin = api->cls;
1169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1170 "GNS REST plugin is finished\n");
1174 /* end of plugin_rest_gns.c */