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;
163 * Cleanup lookup handle.
165 * @param handle Handle to clean up
168 cleanup_handle (struct RequestHandle *handle)
170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
172 if (NULL != handle->json_root)
173 json_decref (handle->json_root);
175 if (NULL != handle->issuer_attr)
176 GNUNET_free (handle->issuer_attr);
177 if (NULL != handle->subject_attr)
178 GNUNET_free (handle->subject_attr);
179 if (NULL != handle->verify_request)
180 GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
181 if (NULL != handle->credential)
182 GNUNET_CREDENTIAL_disconnect (handle->credential);
183 if (NULL != handle->id_op)
184 GNUNET_IDENTITY_cancel (handle->id_op);
185 if (NULL != handle->ego_lookup)
186 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
187 if (NULL != handle->identity)
188 GNUNET_IDENTITY_disconnect (handle->identity);
189 if (NULL != handle->timeout_task)
191 GNUNET_SCHEDULER_cancel (handle->timeout_task);
193 GNUNET_free (handle);
200 struct RequestHandle *handle = cls;
201 struct MHD_Response *resp;
203 resp = GNUNET_REST_create_response (NULL);
204 handle->proc (handle->proc_cls, resp, handle->response_code);
205 cleanup_handle (handle);
209 * Attribute delegation to JSON
211 * @param delegation_chain_entry the DSE
212 * @return JSON, NULL if failed
215 attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
221 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 "Issuer in delegation malformed\n");
228 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 "Subject in credential malformed\n");
233 GNUNET_free (issuer);
236 attr_obj = json_object ();
238 json_object_set_new (attr_obj, "issuer", json_string (issuer));
239 json_object_set_new (attr_obj, "issuer_attribute",
240 json_string (delegation_chain_entry->issuer_attribute));
242 json_object_set_new (attr_obj, "subject", json_string (subject));
243 if (0 < delegation_chain_entry->subject_attribute_len)
245 json_object_set_new (attr_obj, "subject_attribute",
246 json_string (delegation_chain_entry->subject_attribute));
248 GNUNET_free (issuer);
249 GNUNET_free (subject);
254 * JSONAPI resource to Credential
256 * @param res the JSONAPI resource
257 * @return the resulting credential, NULL if failed
259 static struct GNUNET_CREDENTIAL_Credential*
260 json_to_credential (json_t *res)
262 struct GNUNET_CREDENTIAL_Credential *cred;
264 const char *attribute;
265 const char *signature;
268 tmp = json_object_get (res, "attribute");
269 if (0 == json_is_string (tmp))
273 attribute = json_string_value (tmp);
274 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
275 + strlen (attribute));
276 cred->issuer_attribute = attribute;
277 cred->issuer_attribute_len = strlen (attribute);
278 tmp = json_object_get (res, "issuer");
279 if (0 == json_is_string (tmp))
285 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
286 strlen (json_string_value(tmp)),
288 tmp = json_object_get (res, "subject");
289 if (0 == json_is_string (tmp))
294 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
295 strlen (json_string_value(tmp)),
298 tmp = json_object_get (res, "signature");
299 if (0 == json_is_string (tmp))
304 signature = json_string_value (tmp);
305 GNUNET_STRINGS_base64_decode (signature,
308 GNUNET_memcpy (&cred->signature,
310 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
313 tmp = json_object_get (res, "expiration");
314 if (0 == json_is_integer (tmp))
319 cred->expiration.abs_value_us = json_integer_value (tmp);
327 * @param cred the credential
328 * @return the resulting json, NULL if failed
331 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
336 char attribute[cred->issuer_attribute_len + 1];
339 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
343 "Issuer in credential malformed\n");
346 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
349 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
350 "Subject in credential malformed\n");
351 GNUNET_free (issuer);
354 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
355 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
357 GNUNET_memcpy (attribute,
358 cred->issuer_attribute,
359 cred->issuer_attribute_len);
360 attribute[cred->issuer_attribute_len] = '\0';
361 cred_obj = json_object ();
362 json_object_set_new (cred_obj, "issuer", json_string (issuer));
363 json_object_set_new (cred_obj, "subject", json_string (subject));
364 json_object_set_new (cred_obj, "attribute", json_string (attribute));
365 json_object_set_new (cred_obj, "signature", json_string (signature));
366 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
367 GNUNET_free (issuer);
368 GNUNET_free (subject);
369 GNUNET_free (signature);
374 handle_collect_response (void *cls,
375 unsigned int d_count,
376 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
377 unsigned int c_count,
378 struct GNUNET_CREDENTIAL_Credential *cred)
380 struct RequestHandle *handle = cls;
381 struct MHD_Response *resp;
382 struct GNUNET_JSONAPI_Document *json_document;
383 struct GNUNET_JSONAPI_Resource *json_resource;
391 handle->verify_request = NULL;
393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
395 handle->response_code = MHD_HTTP_NOT_FOUND;
396 GNUNET_SCHEDULER_add_now (&do_error, handle);
399 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
402 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403 "Issuer in delegation malformed\n");
406 GNUNET_asprintf (&id,
409 handle->issuer_attr);
410 GNUNET_free (issuer);
411 json_document = GNUNET_JSONAPI_document_new ();
412 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
415 cred_array = json_array ();
416 for (i=0;i<c_count;i++)
418 cred_obj = credential_to_json (&cred[i]);
419 json_array_append_new (cred_array, cred_obj);
421 GNUNET_JSONAPI_resource_add_attr (json_resource,
422 GNUNET_REST_JSONAPI_CREDENTIAL,
424 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
425 GNUNET_JSONAPI_document_serialize (json_document, &result);
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
429 json_decref (cred_array);
430 GNUNET_JSONAPI_document_delete (json_document);
431 resp = GNUNET_REST_create_response (result);
433 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
434 cleanup_handle (handle);
438 subject_ego_lookup (void *cls,
439 const struct GNUNET_IDENTITY_Ego *ego)
441 struct RequestHandle *handle = cls;
442 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
443 handle->ego_lookup = NULL;
447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
448 "Subject not found\n");
449 GNUNET_SCHEDULER_add_now (&do_error, handle);
452 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
453 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
457 &handle_collect_response,
464 handle_verify_response (void *cls,
465 unsigned int d_count,
466 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
467 unsigned int c_count,
468 struct GNUNET_CREDENTIAL_Credential *cred)
471 struct RequestHandle *handle = cls;
472 struct MHD_Response *resp;
473 struct GNUNET_JSONAPI_Document *json_document;
474 struct GNUNET_JSONAPI_Resource *json_resource;
484 handle->verify_request = NULL;
486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
488 handle->response_code = MHD_HTTP_NOT_FOUND;
489 GNUNET_SCHEDULER_add_now (&do_error, handle);
492 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
496 "Issuer in delegation malformed\n");
499 GNUNET_asprintf (&id,
502 handle->issuer_attr);
503 GNUNET_free (issuer);
504 json_document = GNUNET_JSONAPI_document_new ();
505 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
508 attr_array = json_array ();
509 for (i = 0; i < d_count; i++)
511 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
512 json_array_append_new (attr_array, attr_obj);
514 cred_array = json_array ();
515 for (i=0;i<c_count;i++)
517 cred_obj = credential_to_json (&cred[i]);
518 json_array_append_new (cred_array, cred_obj);
520 GNUNET_JSONAPI_resource_add_attr (json_resource,
521 GNUNET_REST_JSONAPI_CREDENTIAL,
523 GNUNET_JSONAPI_resource_add_attr (json_resource,
524 GNUNET_REST_JSONAPI_DELEGATIONS,
526 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
527 GNUNET_JSONAPI_document_serialize (json_document, &result);
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
531 json_decref (attr_array);
532 json_decref (cred_array);
533 GNUNET_JSONAPI_document_delete (json_document);
534 resp = GNUNET_REST_create_response (result);
535 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
536 GNUNET_free (result);
537 cleanup_handle (handle);
541 collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
545 struct RequestHandle *handle = cls;
546 struct GNUNET_HashCode key;
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
552 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
553 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
557 if (NULL == handle->credential)
559 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560 "Connecting to CREDENTIAL failed\n");
561 GNUNET_SCHEDULER_add_now (&do_error, handle);
564 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
565 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
568 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 "Missing issuer attribute\n");
573 GNUNET_SCHEDULER_add_now (&do_error, handle);
576 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
578 entity_attr = GNUNET_strdup (tmp);
579 tmp = strtok(entity_attr, ".");
582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
583 "Malformed issuer or attribute\n");
584 GNUNET_free (entity_attr);
585 GNUNET_SCHEDULER_add_now (&do_error, handle);
589 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
591 &handle->issuer_key))
593 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
594 "Malformed issuer key\n");
595 GNUNET_free (entity_attr);
596 GNUNET_SCHEDULER_add_now (&do_error, handle);
599 tmp = strtok (NULL, "."); //Issuer attribute
602 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603 "Malformed attribute\n");
604 GNUNET_free (entity_attr);
605 GNUNET_SCHEDULER_add_now (&do_error, handle);
608 handle->issuer_attr = GNUNET_strdup (tmp);
609 GNUNET_free (entity_attr);
611 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
612 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
615 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
618 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619 "Missing subject\n");
620 GNUNET_SCHEDULER_add_now (&do_error, handle);
623 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
627 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
628 "Malformed subject\n");
629 GNUNET_SCHEDULER_add_now (&do_error, handle);
632 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
641 verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
645 struct RequestHandle *handle = cls;
646 struct GNUNET_HashCode key;
647 struct GNUNET_JSONAPI_Document *json_obj;
648 struct GNUNET_JSONAPI_Resource *res;
649 struct GNUNET_CREDENTIAL_Credential *cred;
653 uint32_t credential_count;
654 uint32_t resource_count;
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
661 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
662 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
666 if (NULL == handle->credential)
668 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
669 "Connecting to CREDENTIAL failed\n");
670 GNUNET_SCHEDULER_add_now (&do_error, handle);
673 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
674 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
677 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
680 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
681 "Missing issuer attribute\n");
682 GNUNET_SCHEDULER_add_now (&do_error, handle);
685 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
687 entity_attr = GNUNET_strdup (tmp);
688 tmp = strtok(entity_attr, ".");
691 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
692 "Malformed issuer or attribute\n");
693 GNUNET_free (entity_attr);
694 GNUNET_SCHEDULER_add_now (&do_error, handle);
698 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
700 &handle->issuer_key))
702 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
703 "Malformed issuer key\n");
704 GNUNET_free (entity_attr);
705 GNUNET_SCHEDULER_add_now (&do_error, handle);
708 tmp = strtok (NULL, "."); //Issuer attribute
711 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
712 "Malformed attribute\n");
713 GNUNET_free (entity_attr);
714 GNUNET_SCHEDULER_add_now (&do_error, handle);
717 handle->issuer_attr = GNUNET_strdup (tmp);
718 GNUNET_free (entity_attr);
720 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
721 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
724 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
727 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
728 "Missing subject key\n");
729 GNUNET_SCHEDULER_add_now (&do_error, handle);
732 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
736 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
737 "Malformed subject\n");
738 GNUNET_SCHEDULER_add_now (&do_error, handle);
742 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
744 &handle->subject_key)) {
745 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
746 "Malformed subject key\n");
747 GNUNET_SCHEDULER_add_now (&do_error, handle);
751 if (0 >= handle->rest_handle->data_size)
753 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
754 "Missing credentials\n");
755 GNUNET_SCHEDULER_add_now (&do_error, handle);
759 struct GNUNET_JSON_Specification docspec[] = {
760 GNUNET_JSON_spec_jsonapi_document (&json_obj),
761 GNUNET_JSON_spec_end()
763 char term_data[handle->rest_handle->data_size+1];
764 term_data[handle->rest_handle->data_size] = '\0';
765 credential_count = 0;
766 GNUNET_memcpy (term_data,
767 handle->rest_handle->data,
768 handle->rest_handle->data_size);
769 data_js = json_loads (term_data,
772 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
774 json_decref (data_js);
775 if (NULL == json_obj)
777 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
778 "Unable to parse JSONAPI Object from %s\n",
780 GNUNET_SCHEDULER_add_now (&do_error, handle);
784 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
785 GNUNET_assert (1 == resource_count);
786 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
787 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
788 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
791 "Resource not a credential!\n");
792 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
793 "Unable to parse JSONAPI Object from %s\n",
795 GNUNET_JSONAPI_document_delete (json_obj);
796 GNUNET_SCHEDULER_add_now (&do_error, handle);
799 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
800 GNUNET_REST_JSONAPI_CREDENTIAL);
802 GNUNET_assert (json_is_array (cred_json));
804 credential_count = json_array_size(cred_json);
806 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
807 for (i=0;i<credential_count;i++)
809 cred = json_to_credential (json_array_get (cred_json, i));
812 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
813 "Unable to parse credential!\n");
816 GNUNET_memcpy (&credentials[i],
818 sizeof (struct GNUNET_CREDENTIAL_Credential));
819 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
822 GNUNET_JSONAPI_document_delete(json_obj);
823 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
826 &handle->subject_key,
829 &handle_verify_response,
831 for (i=0;i<credential_count;i++)
832 GNUNET_free ((char*)credentials[i].issuer_attribute);
837 send_cred_response (struct RequestHandle *handle,
838 struct GNUNET_CREDENTIAL_Credential *cred)
840 struct MHD_Response *resp;
841 struct GNUNET_JSONAPI_Document *json_document;
842 struct GNUNET_JSONAPI_Resource *json_resource;
850 GNUNET_assert (NULL != cred);
851 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
854 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
855 "Subject malformed\n");
856 GNUNET_free (issuer);
859 GNUNET_asprintf (&id,
863 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
866 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
867 "Subject malformed\n");
869 GNUNET_free (issuer);
872 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
873 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
875 json_document = GNUNET_JSONAPI_document_new ();
876 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
879 cred_obj = json_object();
880 json_object_set_new (cred_obj, "issuer", json_string (issuer));
881 json_object_set_new (cred_obj, "subject", json_string (subject));
882 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
883 json_object_set_new (cred_obj, "signature", json_string (signature));
884 GNUNET_JSONAPI_resource_add_attr (json_resource,
885 GNUNET_REST_JSONAPI_CREDENTIAL,
887 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
888 GNUNET_JSONAPI_document_serialize (json_document, &result);
889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
892 json_decref (cred_obj);
893 GNUNET_JSONAPI_document_delete (json_document);
894 resp = GNUNET_REST_create_response (result);
895 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
896 GNUNET_free (result);
897 GNUNET_free (signature);
898 GNUNET_free (issuer);
899 GNUNET_free (subject);
900 cleanup_handle (handle);
904 get_cred_issuer_cb (void *cls,
905 struct GNUNET_IDENTITY_Ego *ego,
909 struct RequestHandle *handle = cls;
910 struct GNUNET_TIME_Absolute etime_abs;
911 struct GNUNET_TIME_Relative etime_rel;
912 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
913 struct GNUNET_HashCode key;
914 struct GNUNET_CREDENTIAL_Credential *cred;
915 char* expiration_str;
918 handle->id_op = NULL;
922 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
923 "Issuer not configured!\n");
924 GNUNET_SCHEDULER_add_now (&do_error, handle);
928 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
929 "Connecting to credential service...\n");
930 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
933 if (NULL == handle->credential)
935 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
936 "Connecting to CREDENTIAL failed\n");
937 GNUNET_SCHEDULER_add_now (&do_error, handle);
940 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
941 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
944 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
947 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
948 "Missing expiration\n");
949 GNUNET_SCHEDULER_add_now (&do_error, handle);
952 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
954 if ( NULL == expiration_str )
956 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
957 "Expiration malformed\n");
958 GNUNET_SCHEDULER_add_now (&do_error, handle);
962 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
965 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
966 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
969 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
970 "Malformed expiration: %s\n", expiration_str);
971 GNUNET_SCHEDULER_add_now (&do_error, handle);
974 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
975 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
978 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
981 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
982 "Missing issuer attribute\n");
983 GNUNET_SCHEDULER_add_now (&do_error, handle);
986 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
987 (handle->rest_handle->url_param_map,
989 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
990 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
993 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
996 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
997 "Missing subject\n");
998 GNUNET_SCHEDULER_add_now (&do_error, handle);
1001 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1005 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1006 "Malformed subject\n");
1007 GNUNET_SCHEDULER_add_now (&do_error, handle);
1011 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1013 &handle->subject_key)) {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1015 "Malformed subject key\n");
1016 GNUNET_SCHEDULER_add_now (&do_error, handle);
1019 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1020 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1021 &handle->subject_key,
1022 handle->issuer_attr,
1026 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1027 "Failed to create credential\n");
1028 GNUNET_SCHEDULER_add_now (&do_error, handle);
1031 send_cred_response (handle, cred);
1036 issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1040 struct RequestHandle *handle = cls;
1042 handle->identity = GNUNET_IDENTITY_connect (cfg,
1045 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1046 "credential-issuer",
1047 &get_cred_issuer_cb,
1049 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1055 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1059 struct MHD_Response *resp;
1060 struct RequestHandle *handle = cls;
1062 //For GNS, independent of path return all options
1063 resp = GNUNET_REST_create_response (NULL);
1064 MHD_add_response_header (resp,
1065 "Access-Control-Allow-Methods",
1066 MHD_HTTP_METHOD_GET);
1067 handle->proc (handle->proc_cls,
1070 cleanup_handle (handle);
1075 rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1076 GNUNET_REST_ResultProcessor proc,
1079 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1080 struct GNUNET_REST_RequestHandlerError err;
1082 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1083 handle->proc_cls = proc_cls;
1084 handle->proc = proc;
1085 handle->rest_handle = conndata_handle;
1087 static const struct GNUNET_REST_RequestHandler handlers[] = {
1088 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1089 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1090 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1091 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1092 GNUNET_REST_HANDLER_END
1095 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1100 handle->response_code = err.error_code;
1101 GNUNET_SCHEDULER_add_now (&do_error, handle);
1107 * Entry point for the plugin.
1109 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1110 * @return NULL on error, otherwise the plugin context
1113 libgnunet_plugin_rest_credential_init (void *cls)
1115 static struct Plugin plugin;
1117 struct GNUNET_REST_Plugin *api;
1119 if (NULL != plugin.cfg)
1120 return NULL; /* can only initialize once! */
1121 memset (&plugin, 0, sizeof (struct Plugin));
1123 api = GNUNET_new (struct GNUNET_REST_Plugin);
1125 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1126 api->process_request = &rest_credential_process_request;
1127 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1128 _("GNS REST API initialized\n"));
1134 * Exit point from the plugin.
1136 * @param cls the plugin context (as returned by "init")
1137 * @return always NULL
1140 libgnunet_plugin_rest_credential_done (void *cls)
1142 struct GNUNET_REST_Plugin *api = cls;
1143 struct Plugin *plugin = api->cls;
1147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1148 "GNS REST plugin is finished\n");
1152 /* end of plugin_rest_gns.c */