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
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 * @author Martin Schanzenbach
22 * @file 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),
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_free (entity_attr);
621 GNUNET_SCHEDULER_add_now (&do_error, handle);
624 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
628 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
629 "Malformed subject\n");
630 GNUNET_free (entity_attr);
631 GNUNET_SCHEDULER_add_now (&do_error, handle);
634 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
643 verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
647 struct RequestHandle *handle = cls;
648 struct GNUNET_HashCode key;
649 struct GNUNET_JSONAPI_Document *json_obj;
650 struct GNUNET_JSONAPI_Resource *res;
651 struct GNUNET_CREDENTIAL_Credential *cred;
655 uint32_t credential_count;
656 uint32_t resource_count;
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
663 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
664 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
668 if (NULL == handle->credential)
670 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
671 "Connecting to CREDENTIAL failed\n");
672 GNUNET_SCHEDULER_add_now (&do_error, handle);
675 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
676 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
679 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
682 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
683 "Missing issuer attribute\n");
684 GNUNET_SCHEDULER_add_now (&do_error, handle);
687 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
689 entity_attr = GNUNET_strdup (tmp);
690 tmp = strtok(entity_attr, ".");
693 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
694 "Malformed issuer or attribute\n");
695 GNUNET_free (entity_attr);
696 GNUNET_SCHEDULER_add_now (&do_error, handle);
700 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
702 &handle->issuer_key))
704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
705 "Malformed issuer key\n");
706 GNUNET_free (entity_attr);
707 GNUNET_SCHEDULER_add_now (&do_error, handle);
710 tmp = strtok (NULL, "."); //Issuer attribute
713 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
714 "Malformed attribute\n");
715 GNUNET_free (entity_attr);
716 GNUNET_SCHEDULER_add_now (&do_error, handle);
719 handle->issuer_attr = GNUNET_strdup (tmp);
720 GNUNET_free (entity_attr);
722 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
723 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
726 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
729 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
730 "Missing subject key\n");
731 GNUNET_free (entity_attr);
732 GNUNET_SCHEDULER_add_now (&do_error, handle);
735 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
739 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
740 "Malformed subject\n");
741 GNUNET_free (entity_attr);
742 GNUNET_SCHEDULER_add_now (&do_error, handle);
746 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
748 &handle->subject_key)) {
749 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
750 "Malformed subject key\n");
751 GNUNET_free (entity_attr);
752 GNUNET_SCHEDULER_add_now (&do_error, handle);
756 if (0 >= handle->rest_handle->data_size)
758 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
759 "Missing credentials\n");
760 GNUNET_SCHEDULER_add_now (&do_error, handle);
764 struct GNUNET_JSON_Specification docspec[] = {
765 GNUNET_JSON_spec_jsonapi_document (&json_obj),
766 GNUNET_JSON_spec_end()
768 char term_data[handle->rest_handle->data_size+1];
769 term_data[handle->rest_handle->data_size] = '\0';
770 credential_count = 0;
771 GNUNET_memcpy (term_data,
772 handle->rest_handle->data,
773 handle->rest_handle->data_size);
774 data_js = json_loads (term_data,
777 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
779 json_decref (data_js);
780 if (NULL == json_obj)
782 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
783 "Unable to parse JSONAPI Object from %s\n",
785 GNUNET_SCHEDULER_add_now (&do_error, handle);
789 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
790 GNUNET_assert (1 == resource_count);
791 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
792 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
793 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
795 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
796 "Resource not a credential!\n");
797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
798 "Unable to parse JSONAPI Object from %s\n",
800 GNUNET_JSONAPI_document_delete (json_obj);
801 GNUNET_SCHEDULER_add_now (&do_error, handle);
804 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
805 GNUNET_REST_JSONAPI_CREDENTIAL);
807 GNUNET_assert (json_is_array (cred_json));
809 credential_count = json_array_size(cred_json);
811 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
812 for (i=0;i<credential_count;i++)
814 cred = json_to_credential (json_array_get (cred_json, i));
817 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
818 "Unable to parse credential!\n");
821 GNUNET_memcpy (&credentials[i],
823 sizeof (struct GNUNET_CREDENTIAL_Credential));
824 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
827 GNUNET_JSONAPI_document_delete(json_obj);
828 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
831 &handle->subject_key,
834 &handle_verify_response,
836 for (i=0;i<credential_count;i++)
837 GNUNET_free ((char*)credentials[i].issuer_attribute);
842 send_cred_response (struct RequestHandle *handle,
843 struct GNUNET_CREDENTIAL_Credential *cred)
845 struct MHD_Response *resp;
846 struct GNUNET_JSONAPI_Document *json_document;
847 struct GNUNET_JSONAPI_Resource *json_resource;
855 GNUNET_assert (NULL != cred);
856 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
859 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
860 "Subject malformed\n");
863 GNUNET_asprintf (&id,
867 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
870 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
871 "Subject malformed\n");
874 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
875 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
877 json_document = GNUNET_JSONAPI_document_new ();
878 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
881 cred_obj = json_object();
882 json_object_set_new (cred_obj, "issuer", json_string (issuer));
883 json_object_set_new (cred_obj, "subject", json_string (subject));
884 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
885 json_object_set_new (cred_obj, "signature", json_string (signature));
886 GNUNET_JSONAPI_resource_add_attr (json_resource,
887 GNUNET_REST_JSONAPI_CREDENTIAL,
889 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
890 GNUNET_JSONAPI_document_serialize (json_document, &result);
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
894 json_decref (cred_obj);
895 GNUNET_JSONAPI_document_delete (json_document);
896 resp = GNUNET_REST_create_response (result);
897 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
898 GNUNET_free (result);
899 GNUNET_free (signature);
900 GNUNET_free (issuer);
901 GNUNET_free (subject);
902 cleanup_handle (handle);
906 get_cred_issuer_cb (void *cls,
907 struct GNUNET_IDENTITY_Ego *ego,
911 struct RequestHandle *handle = cls;
912 struct GNUNET_TIME_Absolute etime_abs;
913 struct GNUNET_TIME_Relative etime_rel;
914 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
915 struct GNUNET_HashCode key;
916 struct GNUNET_CREDENTIAL_Credential *cred;
917 char* expiration_str;
920 handle->id_op = NULL;
924 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
925 "Issuer not configured!\n");
926 GNUNET_SCHEDULER_add_now (&do_error, handle);
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 "Connecting to credential service...\n");
932 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
935 if (NULL == handle->credential)
937 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
938 "Connecting to CREDENTIAL failed\n");
939 GNUNET_SCHEDULER_add_now (&do_error, handle);
942 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
943 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
946 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
949 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
950 "Missing expiration\n");
951 GNUNET_SCHEDULER_add_now (&do_error, handle);
954 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
956 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
959 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
960 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
964 "Malformed expiration: %s\n", expiration_str);
965 GNUNET_SCHEDULER_add_now (&do_error, handle);
968 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
969 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
972 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
975 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
976 "Missing issuer attribute\n");
977 GNUNET_SCHEDULER_add_now (&do_error, handle);
980 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
981 (handle->rest_handle->url_param_map,
983 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
984 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
987 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
991 "Missing subject\n");
992 GNUNET_SCHEDULER_add_now (&do_error, handle);
995 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
999 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1000 "Malformed subject\n");
1001 GNUNET_SCHEDULER_add_now (&do_error, handle);
1005 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1007 &handle->subject_key)) {
1008 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1009 "Malformed subject key\n");
1010 GNUNET_SCHEDULER_add_now (&do_error, handle);
1013 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1014 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1015 &handle->subject_key,
1016 handle->issuer_attr,
1020 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1021 "Failed to create credential\n");
1022 GNUNET_SCHEDULER_add_now (&do_error, handle);
1025 send_cred_response (handle, cred);
1030 issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1034 struct RequestHandle *handle = cls;
1036 handle->identity = GNUNET_IDENTITY_connect (cfg,
1039 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1040 "credential-issuer",
1041 &get_cred_issuer_cb,
1043 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1049 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1053 struct MHD_Response *resp;
1054 struct RequestHandle *handle = cls;
1056 //For GNS, independent of path return all options
1057 resp = GNUNET_REST_create_response (NULL);
1058 MHD_add_response_header (resp,
1059 "Access-Control-Allow-Methods",
1060 MHD_HTTP_METHOD_GET);
1061 handle->proc (handle->proc_cls,
1064 cleanup_handle (handle);
1069 rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1070 GNUNET_REST_ResultProcessor proc,
1073 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1074 struct GNUNET_REST_RequestHandlerError err;
1076 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1077 handle->proc_cls = proc_cls;
1078 handle->proc = proc;
1079 handle->rest_handle = conndata_handle;
1081 static const struct GNUNET_REST_RequestHandler handlers[] = {
1082 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1083 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1084 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1085 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1086 GNUNET_REST_HANDLER_END
1089 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1094 handle->response_code = err.error_code;
1095 GNUNET_SCHEDULER_add_now (&do_error, handle);
1101 * Entry point for the plugin.
1103 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1104 * @return NULL on error, otherwise the plugin context
1107 libgnunet_plugin_rest_credential_init (void *cls)
1109 static struct Plugin plugin;
1111 struct GNUNET_REST_Plugin *api;
1113 if (NULL != plugin.cfg)
1114 return NULL; /* can only initialize once! */
1115 memset (&plugin, 0, sizeof (struct Plugin));
1117 api = GNUNET_new (struct GNUNET_REST_Plugin);
1119 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1120 api->process_request = &rest_credential_process_request;
1121 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1122 _("GNS REST API initialized\n"));
1128 * Exit point from the plugin.
1130 * @param cls the plugin context (as returned by "init")
1131 * @return always NULL
1134 libgnunet_plugin_rest_credential_done (void *cls)
1136 struct GNUNET_REST_Plugin *api = cls;
1137 struct Plugin *plugin = api->cls;
1141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1142 "GNS REST plugin is finished\n");
1146 /* end of plugin_rest_gns.c */