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 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.
16 * @author Martin Schanzenbach
17 * @file credential/plugin_rest_credential.c
18 * @brief GNUnet CREDENTIAL REST plugin
23 #include "gnunet_rest_plugin.h"
24 #include <gnunet_identity_service.h>
25 #include <gnunet_gnsrecord_lib.h>
26 #include <gnunet_namestore_service.h>
27 #include <gnunet_credential_service.h>
28 #include <gnunet_rest_lib.h>
29 #include <gnunet_jsonapi_lib.h>
30 #include <gnunet_jsonapi_util.h>
33 #define GNUNET_REST_API_NS_CREDENTIAL "/credential"
35 #define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
37 #define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
39 #define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
41 #define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
43 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
45 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
47 #define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
49 #define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
51 #define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
53 #define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
55 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
58 * @brief struct returned by the initialization function of the plugin
62 const struct GNUNET_CONFIGURATION_Handle *cfg;
65 const struct GNUNET_CONFIGURATION_Handle *cfg;
70 * Handle to Credential service.
72 struct GNUNET_CREDENTIAL_Handle *credential;
75 * Handle to lookup request
77 struct GNUNET_CREDENTIAL_Request *verify_request;
80 * Handle to issue request
82 struct GNUNET_CREDENTIAL_Request *issue_request;
87 struct GNUNET_IDENTITY_Handle *identity;
90 * Handle to identity operation
92 struct GNUNET_IDENTITY_Operation *id_op;
95 * Handle to ego lookup
97 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
100 * Handle to rest request
102 struct GNUNET_REST_RequestHandle *rest_handle;
105 * ID of a task associated with the resolution process.
107 struct GNUNET_SCHEDULER_Task * timeout_task;
110 * The root of the received JSON or NULL
115 * The plugin result processor
117 GNUNET_REST_ResultProcessor proc;
120 * The closure of the result processor
125 * The issuer attribute to verify
130 * The subject attribute
135 * The public key of the issuer
137 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
140 * The public key of the subject
142 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
152 struct GNUNET_TIME_Relative timeout;
158 * Cleanup lookup handle.
160 * @param handle Handle to clean up
163 cleanup_handle (struct RequestHandle *handle)
165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
167 if (NULL != handle->json_root)
168 json_decref (handle->json_root);
170 if (NULL != handle->issuer_attr)
171 GNUNET_free (handle->issuer_attr);
172 if (NULL != handle->subject_attr)
173 GNUNET_free (handle->subject_attr);
174 if (NULL != handle->verify_request)
175 GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
176 if (NULL != handle->credential)
177 GNUNET_CREDENTIAL_disconnect (handle->credential);
178 if (NULL != handle->id_op)
179 GNUNET_IDENTITY_cancel (handle->id_op);
180 if (NULL != handle->ego_lookup)
181 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
182 if (NULL != handle->identity)
183 GNUNET_IDENTITY_disconnect (handle->identity);
184 if (NULL != handle->timeout_task)
186 GNUNET_SCHEDULER_cancel (handle->timeout_task);
188 GNUNET_free (handle);
195 struct RequestHandle *handle = cls;
196 struct MHD_Response *resp;
198 resp = GNUNET_REST_create_response (NULL);
199 handle->proc (handle->proc_cls, resp, handle->response_code);
200 cleanup_handle (handle);
204 * Attribute delegation to JSON
206 * @param delegation_chain_entry the DSE
207 * @return JSON, NULL if failed
210 attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
216 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
219 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
220 "Issuer in delegation malformed\n");
223 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
226 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
227 "Subject in credential malformed\n");
228 GNUNET_free (issuer);
231 attr_obj = json_object ();
233 json_object_set_new (attr_obj, "issuer", json_string (issuer));
234 json_object_set_new (attr_obj, "issuer_attribute",
235 json_string (delegation_chain_entry->issuer_attribute));
237 json_object_set_new (attr_obj, "subject", json_string (subject));
238 if (0 < delegation_chain_entry->subject_attribute_len)
240 json_object_set_new (attr_obj, "subject_attribute",
241 json_string (delegation_chain_entry->subject_attribute));
243 GNUNET_free (issuer);
244 GNUNET_free (subject);
249 * JSONAPI resource to Credential
251 * @param res the JSONAPI resource
252 * @return the resulting credential, NULL if failed
254 static struct GNUNET_CREDENTIAL_Credential*
255 json_to_credential (json_t *res)
257 struct GNUNET_CREDENTIAL_Credential *cred;
259 const char *attribute;
260 const char *signature;
263 tmp = json_object_get (res, "attribute");
264 if (0 == json_is_string (tmp))
268 attribute = json_string_value (tmp);
269 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
270 + strlen (attribute));
271 cred->issuer_attribute = attribute;
272 cred->issuer_attribute_len = strlen (attribute);
273 tmp = json_object_get (res, "issuer");
274 if (0 == json_is_string (tmp))
280 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
281 strlen (json_string_value(tmp)),
283 tmp = json_object_get (res, "subject");
284 if (0 == json_is_string (tmp))
289 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
290 strlen (json_string_value(tmp)),
293 tmp = json_object_get (res, "signature");
294 if (0 == json_is_string (tmp))
299 signature = json_string_value (tmp);
300 GNUNET_STRINGS_base64_decode (signature,
303 GNUNET_memcpy (&cred->signature,
305 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
308 tmp = json_object_get (res, "expiration");
309 if (0 == json_is_integer (tmp))
314 cred->expiration.abs_value_us = json_integer_value (tmp);
322 * @param cred the credential
323 * @return the resulting json, NULL if failed
326 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
331 char attribute[cred->issuer_attribute_len + 1];
334 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
337 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
338 "Issuer in credential malformed\n");
341 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
344 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
345 "Subject in credential malformed\n");
346 GNUNET_free (issuer);
349 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
350 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
352 GNUNET_memcpy (attribute,
353 cred->issuer_attribute,
354 cred->issuer_attribute_len);
355 attribute[cred->issuer_attribute_len] = '\0';
356 cred_obj = json_object ();
357 json_object_set_new (cred_obj, "issuer", json_string (issuer));
358 json_object_set_new (cred_obj, "subject", json_string (subject));
359 json_object_set_new (cred_obj, "attribute", json_string (attribute));
360 json_object_set_new (cred_obj, "signature", json_string (signature));
361 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
362 GNUNET_free (issuer);
363 GNUNET_free (subject);
364 GNUNET_free (signature);
369 handle_collect_response (void *cls,
370 unsigned int d_count,
371 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
372 unsigned int c_count,
373 struct GNUNET_CREDENTIAL_Credential *cred)
375 struct RequestHandle *handle = cls;
376 struct MHD_Response *resp;
377 struct GNUNET_JSONAPI_Document *json_document;
378 struct GNUNET_JSONAPI_Resource *json_resource;
386 handle->verify_request = NULL;
388 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
390 handle->response_code = MHD_HTTP_NOT_FOUND;
391 GNUNET_SCHEDULER_add_now (&do_error, handle);
394 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
397 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
398 "Issuer in delegation malformed\n");
401 GNUNET_asprintf (&id,
404 handle->issuer_attr);
405 GNUNET_free (issuer);
406 json_document = GNUNET_JSONAPI_document_new ();
407 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
410 cred_array = json_array ();
411 for (i=0;i<c_count;i++)
413 cred_obj = credential_to_json (&cred[i]);
414 json_array_append_new (cred_array, cred_obj);
416 GNUNET_JSONAPI_resource_add_attr (json_resource,
417 GNUNET_REST_JSONAPI_CREDENTIAL,
419 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
420 GNUNET_JSONAPI_document_serialize (json_document, &result);
421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
424 json_decref (cred_array);
425 GNUNET_JSONAPI_document_delete (json_document);
426 resp = GNUNET_REST_create_response (result);
428 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
429 cleanup_handle (handle);
433 subject_ego_lookup (void *cls,
434 const struct GNUNET_IDENTITY_Ego *ego)
436 struct RequestHandle *handle = cls;
437 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
438 handle->ego_lookup = NULL;
442 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
443 "Subject not found\n");
444 GNUNET_SCHEDULER_add_now (&do_error, handle);
447 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
448 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
452 &handle_collect_response,
459 handle_verify_response (void *cls,
460 unsigned int d_count,
461 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
462 unsigned int c_count,
463 struct GNUNET_CREDENTIAL_Credential *cred)
466 struct RequestHandle *handle = cls;
467 struct MHD_Response *resp;
468 struct GNUNET_JSONAPI_Document *json_document;
469 struct GNUNET_JSONAPI_Resource *json_resource;
479 handle->verify_request = NULL;
481 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
483 handle->response_code = MHD_HTTP_NOT_FOUND;
484 GNUNET_SCHEDULER_add_now (&do_error, handle);
487 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
490 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
491 "Issuer in delegation malformed\n");
494 GNUNET_asprintf (&id,
497 handle->issuer_attr);
498 GNUNET_free (issuer);
499 json_document = GNUNET_JSONAPI_document_new ();
500 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
503 attr_array = json_array ();
504 for (i = 0; i < d_count; i++)
506 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
507 json_array_append_new (attr_array, attr_obj);
509 cred_array = json_array ();
510 for (i=0;i<c_count;i++)
512 cred_obj = credential_to_json (&cred[i]);
513 json_array_append_new (cred_array, cred_obj);
515 GNUNET_JSONAPI_resource_add_attr (json_resource,
516 GNUNET_REST_JSONAPI_CREDENTIAL,
518 GNUNET_JSONAPI_resource_add_attr (json_resource,
519 GNUNET_REST_JSONAPI_DELEGATIONS,
521 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
522 GNUNET_JSONAPI_document_serialize (json_document, &result);
523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
526 json_decref (attr_array);
527 json_decref (cred_array);
528 GNUNET_JSONAPI_document_delete (json_document);
529 resp = GNUNET_REST_create_response (result);
530 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
531 GNUNET_free (result);
532 cleanup_handle (handle);
536 collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
540 struct RequestHandle *handle = cls;
541 struct GNUNET_HashCode key;
545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
547 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
548 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
552 if (NULL == handle->credential)
554 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
555 "Connecting to CREDENTIAL failed\n");
556 GNUNET_SCHEDULER_add_now (&do_error, handle);
559 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
560 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
563 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
566 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
567 "Missing issuer attribute\n");
568 GNUNET_SCHEDULER_add_now (&do_error, handle);
571 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
573 entity_attr = GNUNET_strdup (tmp);
574 tmp = strtok(entity_attr, ".");
577 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
578 "Malformed issuer or attribute\n");
579 GNUNET_free (entity_attr);
580 GNUNET_SCHEDULER_add_now (&do_error, handle);
584 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
586 &handle->issuer_key))
588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
589 "Malformed issuer key\n");
590 GNUNET_free (entity_attr);
591 GNUNET_SCHEDULER_add_now (&do_error, handle);
594 tmp = strtok (NULL, "."); //Issuer attribute
597 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
598 "Malformed attribute\n");
599 GNUNET_free (entity_attr);
600 GNUNET_SCHEDULER_add_now (&do_error, handle);
603 handle->issuer_attr = GNUNET_strdup (tmp);
604 GNUNET_free (entity_attr);
606 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
607 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
610 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
613 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
614 "Missing subject\n");
615 GNUNET_SCHEDULER_add_now (&do_error, handle);
618 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
622 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
623 "Malformed subject\n");
624 GNUNET_SCHEDULER_add_now (&do_error, handle);
627 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
636 verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
640 struct RequestHandle *handle = cls;
641 struct GNUNET_HashCode key;
642 struct GNUNET_JSONAPI_Document *json_obj;
643 struct GNUNET_JSONAPI_Resource *res;
644 struct GNUNET_CREDENTIAL_Credential *cred;
648 uint32_t credential_count;
649 uint32_t resource_count;
654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
656 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
657 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
661 if (NULL == handle->credential)
663 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
664 "Connecting to CREDENTIAL failed\n");
665 GNUNET_SCHEDULER_add_now (&do_error, handle);
668 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
669 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
672 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
675 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
676 "Missing issuer attribute\n");
677 GNUNET_SCHEDULER_add_now (&do_error, handle);
680 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
682 entity_attr = GNUNET_strdup (tmp);
683 tmp = strtok(entity_attr, ".");
686 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
687 "Malformed issuer or attribute\n");
688 GNUNET_free (entity_attr);
689 GNUNET_SCHEDULER_add_now (&do_error, handle);
693 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
695 &handle->issuer_key))
697 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
698 "Malformed issuer key\n");
699 GNUNET_free (entity_attr);
700 GNUNET_SCHEDULER_add_now (&do_error, handle);
703 tmp = strtok (NULL, "."); //Issuer attribute
706 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
707 "Malformed attribute\n");
708 GNUNET_free (entity_attr);
709 GNUNET_SCHEDULER_add_now (&do_error, handle);
712 handle->issuer_attr = GNUNET_strdup (tmp);
713 GNUNET_free (entity_attr);
715 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
716 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
719 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
722 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
723 "Missing subject key\n");
724 GNUNET_SCHEDULER_add_now (&do_error, handle);
727 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
731 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
732 "Malformed subject\n");
733 GNUNET_SCHEDULER_add_now (&do_error, handle);
737 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
739 &handle->subject_key)) {
740 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
741 "Malformed subject key\n");
742 GNUNET_SCHEDULER_add_now (&do_error, handle);
746 if (0 >= handle->rest_handle->data_size)
748 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
749 "Missing credentials\n");
750 GNUNET_SCHEDULER_add_now (&do_error, handle);
754 struct GNUNET_JSON_Specification docspec[] = {
755 GNUNET_JSON_spec_jsonapi_document (&json_obj),
756 GNUNET_JSON_spec_end()
758 char term_data[handle->rest_handle->data_size+1];
759 term_data[handle->rest_handle->data_size] = '\0';
760 credential_count = 0;
761 GNUNET_memcpy (term_data,
762 handle->rest_handle->data,
763 handle->rest_handle->data_size);
764 data_js = json_loads (term_data,
767 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
769 json_decref (data_js);
770 if (NULL == json_obj)
772 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
773 "Unable to parse JSONAPI Object from %s\n",
775 GNUNET_SCHEDULER_add_now (&do_error, handle);
779 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
780 GNUNET_assert (1 == resource_count);
781 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
782 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
783 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
786 "Resource not a credential!\n");
787 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
788 "Unable to parse JSONAPI Object from %s\n",
790 GNUNET_JSONAPI_document_delete (json_obj);
791 GNUNET_SCHEDULER_add_now (&do_error, handle);
794 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
795 GNUNET_REST_JSONAPI_CREDENTIAL);
797 GNUNET_assert (json_is_array (cred_json));
799 credential_count = json_array_size(cred_json);
801 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
802 for (i=0;i<credential_count;i++)
804 cred = json_to_credential (json_array_get (cred_json, i));
807 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
808 "Unable to parse credential!\n");
811 GNUNET_memcpy (&credentials[i],
813 sizeof (struct GNUNET_CREDENTIAL_Credential));
814 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
817 GNUNET_JSONAPI_document_delete(json_obj);
818 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
821 &handle->subject_key,
824 &handle_verify_response,
826 for (i=0;i<credential_count;i++)
827 GNUNET_free ((char*)credentials[i].issuer_attribute);
832 send_cred_response (struct RequestHandle *handle,
833 struct GNUNET_CREDENTIAL_Credential *cred)
835 struct MHD_Response *resp;
836 struct GNUNET_JSONAPI_Document *json_document;
837 struct GNUNET_JSONAPI_Resource *json_resource;
845 GNUNET_assert (NULL != cred);
846 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
849 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
850 "Subject malformed\n");
851 GNUNET_free (issuer);
854 GNUNET_asprintf (&id,
858 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
861 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
862 "Subject malformed\n");
864 GNUNET_free (issuer);
867 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
868 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
870 json_document = GNUNET_JSONAPI_document_new ();
871 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
874 cred_obj = json_object();
875 json_object_set_new (cred_obj, "issuer", json_string (issuer));
876 json_object_set_new (cred_obj, "subject", json_string (subject));
877 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
878 json_object_set_new (cred_obj, "signature", json_string (signature));
879 GNUNET_JSONAPI_resource_add_attr (json_resource,
880 GNUNET_REST_JSONAPI_CREDENTIAL,
882 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
883 GNUNET_JSONAPI_document_serialize (json_document, &result);
884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
887 json_decref (cred_obj);
888 GNUNET_JSONAPI_document_delete (json_document);
889 resp = GNUNET_REST_create_response (result);
890 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
891 GNUNET_free (result);
892 GNUNET_free (signature);
893 GNUNET_free (issuer);
894 GNUNET_free (subject);
895 cleanup_handle (handle);
899 get_cred_issuer_cb (void *cls,
900 struct GNUNET_IDENTITY_Ego *ego,
904 struct RequestHandle *handle = cls;
905 struct GNUNET_TIME_Absolute etime_abs;
906 struct GNUNET_TIME_Relative etime_rel;
907 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
908 struct GNUNET_HashCode key;
909 struct GNUNET_CREDENTIAL_Credential *cred;
910 char* expiration_str;
913 handle->id_op = NULL;
917 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
918 "Issuer not configured!\n");
919 GNUNET_SCHEDULER_add_now (&do_error, handle);
923 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
924 "Connecting to credential service...\n");
925 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
926 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
928 if (NULL == handle->credential)
930 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
931 "Connecting to CREDENTIAL failed\n");
932 GNUNET_SCHEDULER_add_now (&do_error, handle);
935 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
936 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
939 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
942 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
943 "Missing expiration\n");
944 GNUNET_SCHEDULER_add_now (&do_error, handle);
947 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
949 if ( NULL == expiration_str )
951 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
952 "Expiration malformed\n");
953 GNUNET_SCHEDULER_add_now (&do_error, handle);
957 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
960 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
961 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
964 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
965 "Malformed expiration: %s\n", expiration_str);
966 GNUNET_SCHEDULER_add_now (&do_error, handle);
969 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
970 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
973 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
976 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
977 "Missing issuer attribute\n");
978 GNUNET_SCHEDULER_add_now (&do_error, handle);
981 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
982 (handle->rest_handle->url_param_map,
984 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
985 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
988 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
991 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
992 "Missing subject\n");
993 GNUNET_SCHEDULER_add_now (&do_error, handle);
996 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1000 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1001 "Malformed subject\n");
1002 GNUNET_SCHEDULER_add_now (&do_error, handle);
1006 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1008 &handle->subject_key)) {
1009 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1010 "Malformed subject key\n");
1011 GNUNET_SCHEDULER_add_now (&do_error, handle);
1014 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1015 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1016 &handle->subject_key,
1017 handle->issuer_attr,
1021 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1022 "Failed to create credential\n");
1023 GNUNET_SCHEDULER_add_now (&do_error, handle);
1026 send_cred_response (handle, cred);
1031 issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1035 struct RequestHandle *handle = cls;
1037 handle->identity = GNUNET_IDENTITY_connect (cfg,
1040 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1041 "credential-issuer",
1042 &get_cred_issuer_cb,
1044 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1050 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1054 struct MHD_Response *resp;
1055 struct RequestHandle *handle = cls;
1057 //For GNS, independent of path return all options
1058 resp = GNUNET_REST_create_response (NULL);
1059 MHD_add_response_header (resp,
1060 "Access-Control-Allow-Methods",
1061 MHD_HTTP_METHOD_GET);
1062 handle->proc (handle->proc_cls,
1065 cleanup_handle (handle);
1070 rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1071 GNUNET_REST_ResultProcessor proc,
1074 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1075 struct GNUNET_REST_RequestHandlerError err;
1077 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1078 handle->proc_cls = proc_cls;
1079 handle->proc = proc;
1080 handle->rest_handle = conndata_handle;
1082 static const struct GNUNET_REST_RequestHandler handlers[] = {
1083 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1084 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1085 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1086 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1087 GNUNET_REST_HANDLER_END
1090 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1095 handle->response_code = err.error_code;
1096 GNUNET_SCHEDULER_add_now (&do_error, handle);
1102 * Entry point for the plugin.
1104 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1105 * @return NULL on error, otherwise the plugin context
1108 libgnunet_plugin_rest_credential_init (void *cls)
1110 static struct Plugin plugin;
1112 struct GNUNET_REST_Plugin *api;
1114 if (NULL != plugin.cfg)
1115 return NULL; /* can only initialize once! */
1116 memset (&plugin, 0, sizeof (struct Plugin));
1118 api = GNUNET_new (struct GNUNET_REST_Plugin);
1120 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1121 api->process_request = &rest_credential_process_request;
1122 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1123 _("GNS REST API initialized\n"));
1129 * Exit point from the plugin.
1131 * @param cls the plugin context (as returned by "init")
1132 * @return always NULL
1135 libgnunet_plugin_rest_credential_done (void *cls)
1137 struct GNUNET_REST_Plugin *api = cls;
1138 struct Plugin *plugin = api->cls;
1142 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1143 "GNS REST plugin is finished\n");
1147 /* end of plugin_rest_gns.c */