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 gns/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_verify_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);
198 * Task run on shutdown. Cleans up everything.
201 * @param tc scheduler context
206 struct RequestHandle *handle = cls;
207 struct MHD_Response *resp;
209 resp = GNUNET_REST_create_response (NULL);
210 handle->proc (handle->proc_cls, resp, handle->response_code);
211 cleanup_handle (handle);
215 * Attribute delegation to JSON
216 * @param attr the attribute
217 * @return JSON, NULL if failed
220 attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
226 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
230 "Issuer in delegation malformed\n");
233 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
236 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
237 "Subject in credential malformed\n");
238 GNUNET_free (issuer);
241 attr_obj = json_object ();
243 json_object_set_new (attr_obj, "issuer", json_string (issuer));
244 json_object_set_new (attr_obj, "issuer_attribute",
245 json_string (delegation_chain_entry->issuer_attribute));
247 json_object_set_new (attr_obj, "subject", json_string (subject));
248 if (0 < delegation_chain_entry->subject_attribute_len)
250 json_object_set_new (attr_obj, "subject_attribute",
251 json_string (delegation_chain_entry->subject_attribute));
253 GNUNET_free (issuer);
254 GNUNET_free (subject);
259 * 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);
330 * @param cred the credential
331 * @return the resulting json, NULL if failed
334 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
339 char attribute[cred->issuer_attribute_len + 1];
342 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
345 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
346 "Issuer in credential malformed\n");
349 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
353 "Subject in credential malformed\n");
354 GNUNET_free (issuer);
357 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
358 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
361 cred->issuer_attribute,
362 cred->issuer_attribute_len);
363 attribute[cred->issuer_attribute_len] = '\0';
364 cred_obj = json_object ();
365 json_object_set_new (cred_obj, "issuer", json_string (issuer));
366 json_object_set_new (cred_obj, "subject", json_string (subject));
367 json_object_set_new (cred_obj, "attribute", json_string (attribute));
368 json_object_set_new (cred_obj, "signature", json_string (signature));
369 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
370 GNUNET_free (issuer);
371 GNUNET_free (subject);
372 GNUNET_free (signature);
377 * Function called with the result of a Credential lookup.
379 * @param cls the 'const char *' name that was resolved
380 * @param cd_count number of records returned
381 * @param cd array of @a cd_count records with the results
384 handle_collect_response (void *cls,
385 unsigned int d_count,
386 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
387 unsigned int c_count,
388 struct GNUNET_CREDENTIAL_Credential *cred)
390 struct RequestHandle *handle = cls;
391 struct MHD_Response *resp;
392 struct GNUNET_JSONAPI_Document *json_document;
393 struct GNUNET_JSONAPI_Resource *json_resource;
401 handle->verify_request = NULL;
403 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
405 handle->response_code = MHD_HTTP_NOT_FOUND;
406 GNUNET_SCHEDULER_add_now (&do_error, handle);
409 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
412 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
413 "Issuer in delegation malformed\n");
416 GNUNET_asprintf (&id,
419 handle->issuer_attr);
420 GNUNET_free (issuer);
421 json_document = GNUNET_JSONAPI_document_new ();
422 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
425 cred_array = json_array ();
426 for (i=0;i<c_count;i++)
428 cred_obj = credential_to_json (&cred[i]);
429 json_array_append_new (cred_array, cred_obj);
431 GNUNET_JSONAPI_resource_add_attr (json_resource,
432 GNUNET_REST_JSONAPI_CREDENTIAL,
434 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
435 GNUNET_JSONAPI_document_serialize (json_document, &result);
436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
439 json_decref (cred_array);
440 GNUNET_JSONAPI_document_delete (json_document);
441 resp = GNUNET_REST_create_response (result);
443 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
444 cleanup_handle (handle);
448 subject_ego_lookup (void *cls,
449 const struct GNUNET_IDENTITY_Ego *ego)
451 struct RequestHandle *handle = cls;
452 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
453 handle->ego_lookup = NULL;
457 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
458 "Subject not found\n");
459 GNUNET_SCHEDULER_add_now (&do_error, handle);
462 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
463 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
467 &handle_collect_response,
474 * Function called with the result of a Credential lookup.
476 * @param cls the 'const char *' name that was resolved
477 * @param cd_count number of records returned
478 * @param cd array of @a cd_count records with the results
481 handle_verify_response (void *cls,
482 unsigned int d_count,
483 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
484 unsigned int c_count,
485 struct GNUNET_CREDENTIAL_Credential *cred)
488 struct RequestHandle *handle = cls;
489 struct MHD_Response *resp;
490 struct GNUNET_JSONAPI_Document *json_document;
491 struct GNUNET_JSONAPI_Resource *json_resource;
501 handle->verify_request = NULL;
503 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
505 handle->response_code = MHD_HTTP_NOT_FOUND;
506 GNUNET_SCHEDULER_add_now (&do_error, handle);
509 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
513 "Issuer in delegation malformed\n");
516 GNUNET_asprintf (&id,
519 handle->issuer_attr);
520 GNUNET_free (issuer);
521 json_document = GNUNET_JSONAPI_document_new ();
522 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
525 attr_array = json_array ();
526 for (i = 0; i < d_count; i++)
528 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
529 json_array_append_new (attr_array, attr_obj);
531 cred_array = json_array ();
532 for (i=0;i<c_count;i++)
534 cred_obj = credential_to_json (&cred[i]);
535 json_array_append_new (cred_array, cred_obj);
537 GNUNET_JSONAPI_resource_add_attr (json_resource,
538 GNUNET_REST_JSONAPI_CREDENTIAL,
540 GNUNET_JSONAPI_resource_add_attr (json_resource,
541 GNUNET_REST_JSONAPI_DELEGATIONS,
543 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
544 GNUNET_JSONAPI_document_serialize (json_document, &result);
545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
548 json_decref (attr_array);
549 json_decref (cred_array);
550 GNUNET_JSONAPI_document_delete (json_document);
551 resp = GNUNET_REST_create_response (result);
552 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
553 GNUNET_free (result);
554 cleanup_handle (handle);
558 collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
562 struct RequestHandle *handle = cls;
563 struct GNUNET_HashCode key;
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
569 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
570 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
574 if (NULL == handle->credential)
576 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
577 "Connecting to CREDENTIAL failed\n");
578 GNUNET_SCHEDULER_add_now (&do_error, handle);
581 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
582 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
585 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
589 "Missing issuer attribute\n");
590 GNUNET_SCHEDULER_add_now (&do_error, handle);
593 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
595 entity_attr = GNUNET_strdup (tmp);
596 tmp = strtok(entity_attr, ".");
599 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
600 "Malformed issuer or attribute\n");
601 GNUNET_free (entity_attr);
602 GNUNET_SCHEDULER_add_now (&do_error, handle);
606 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
608 &handle->issuer_key))
610 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
611 "Malformed issuer key\n");
612 GNUNET_free (entity_attr);
613 GNUNET_SCHEDULER_add_now (&do_error, handle);
616 tmp = strtok (NULL, "."); //Issuer attribute
619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
620 "Malformed attribute\n");
621 GNUNET_free (entity_attr);
622 GNUNET_SCHEDULER_add_now (&do_error, handle);
625 handle->issuer_attr = GNUNET_strdup (tmp);
626 GNUNET_free (entity_attr);
628 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
629 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
632 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
635 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
636 "Missing subject\n");
637 GNUNET_free (entity_attr);
638 GNUNET_SCHEDULER_add_now (&do_error, handle);
641 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
645 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
646 "Malformed subject\n");
647 GNUNET_free (entity_attr);
648 GNUNET_SCHEDULER_add_now (&do_error, handle);
651 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
660 verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
664 struct RequestHandle *handle = cls;
665 struct GNUNET_HashCode key;
666 struct GNUNET_JSONAPI_Document *json_obj;
667 struct GNUNET_JSONAPI_Resource *res;
668 struct GNUNET_CREDENTIAL_Credential *cred;
672 uint32_t credential_count;
673 uint32_t resource_count;
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
680 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
681 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
685 if (NULL == handle->credential)
687 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
688 "Connecting to CREDENTIAL failed\n");
689 GNUNET_SCHEDULER_add_now (&do_error, handle);
692 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
693 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
696 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
699 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
700 "Missing issuer attribute\n");
701 GNUNET_SCHEDULER_add_now (&do_error, handle);
704 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
706 entity_attr = GNUNET_strdup (tmp);
707 tmp = strtok(entity_attr, ".");
710 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
711 "Malformed issuer or attribute\n");
712 GNUNET_free (entity_attr);
713 GNUNET_SCHEDULER_add_now (&do_error, handle);
717 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
719 &handle->issuer_key))
721 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
722 "Malformed issuer key\n");
723 GNUNET_free (entity_attr);
724 GNUNET_SCHEDULER_add_now (&do_error, handle);
727 tmp = strtok (NULL, "."); //Issuer attribute
730 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
731 "Malformed attribute\n");
732 GNUNET_free (entity_attr);
733 GNUNET_SCHEDULER_add_now (&do_error, handle);
736 handle->issuer_attr = GNUNET_strdup (tmp);
737 GNUNET_free (entity_attr);
739 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
740 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
743 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
746 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
747 "Missing subject key\n");
748 GNUNET_free (entity_attr);
749 GNUNET_SCHEDULER_add_now (&do_error, handle);
752 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
756 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
757 "Malformed subject\n");
758 GNUNET_free (entity_attr);
759 GNUNET_SCHEDULER_add_now (&do_error, handle);
763 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
765 &handle->subject_key)) {
766 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
767 "Malformed subject key\n");
768 GNUNET_free (entity_attr);
769 GNUNET_SCHEDULER_add_now (&do_error, handle);
773 if (0 >= handle->rest_handle->data_size)
775 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
776 "Missing credentials\n");
777 GNUNET_SCHEDULER_add_now (&do_error, handle);
781 struct GNUNET_JSON_Specification docspec[] = {
782 GNUNET_JSON_spec_jsonapi_document (&json_obj),
783 GNUNET_JSON_spec_end()
785 char term_data[handle->rest_handle->data_size+1];
786 term_data[handle->rest_handle->data_size] = '\0';
787 credential_count = 0;
788 GNUNET_memcpy (term_data,
789 handle->rest_handle->data,
790 handle->rest_handle->data_size);
791 data_js = json_loads (term_data,
794 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
796 json_decref (data_js);
797 if (NULL == json_obj)
799 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
800 "Unable to parse JSONAPI Object from %s\n",
802 GNUNET_SCHEDULER_add_now (&do_error, handle);
806 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
807 GNUNET_assert (1 == resource_count);
808 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
809 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
810 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
812 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
813 "Resource not a credential!\n");
814 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
815 "Unable to parse JSONAPI Object from %s\n",
817 GNUNET_JSONAPI_document_delete (json_obj);
818 GNUNET_SCHEDULER_add_now (&do_error, handle);
821 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
822 GNUNET_REST_JSONAPI_CREDENTIAL);
824 GNUNET_assert (json_is_array (cred_json));
826 credential_count = json_array_size(cred_json);
828 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
829 for (i=0;i<credential_count;i++)
831 cred = json_to_credential (json_array_get (cred_json, i));
834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
835 "Unable to parse credential!\n");
838 GNUNET_memcpy (&credentials[i],
840 sizeof (struct GNUNET_CREDENTIAL_Credential));
841 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
844 GNUNET_JSONAPI_document_delete(json_obj);
845 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
848 &handle->subject_key,
851 &handle_verify_response,
853 for (i=0;i<credential_count;i++)
854 GNUNET_free ((char*)credentials[i].issuer_attribute);
859 send_cred_response (struct RequestHandle *handle,
860 struct GNUNET_CREDENTIAL_Credential *cred)
862 struct MHD_Response *resp;
863 struct GNUNET_JSONAPI_Document *json_document;
864 struct GNUNET_JSONAPI_Resource *json_resource;
872 GNUNET_assert (NULL != cred);
873 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
877 "Subject malformed\n");
880 GNUNET_asprintf (&id,
884 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
887 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
888 "Subject malformed\n");
891 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
892 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
894 json_document = GNUNET_JSONAPI_document_new ();
895 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
898 cred_obj = json_object();
899 json_object_set_new (cred_obj, "issuer", json_string (issuer));
900 json_object_set_new (cred_obj, "subject", json_string (subject));
901 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
902 json_object_set_new (cred_obj, "signature", json_string (signature));
903 GNUNET_JSONAPI_resource_add_attr (json_resource,
904 GNUNET_REST_JSONAPI_CREDENTIAL,
906 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
907 GNUNET_JSONAPI_document_serialize (json_document, &result);
908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
911 json_decref (cred_obj);
912 GNUNET_JSONAPI_document_delete (json_document);
913 resp = GNUNET_REST_create_response (result);
914 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
915 GNUNET_free (result);
916 GNUNET_free (signature);
917 GNUNET_free (issuer);
918 GNUNET_free (subject);
919 cleanup_handle (handle);
923 get_cred_issuer_cb (void *cls,
924 struct GNUNET_IDENTITY_Ego *ego,
928 struct RequestHandle *handle = cls;
929 struct GNUNET_TIME_Absolute etime_abs;
930 struct GNUNET_TIME_Relative etime_rel;
931 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
932 struct GNUNET_HashCode key;
933 struct GNUNET_CREDENTIAL_Credential *cred;
934 char* expiration_str;
937 handle->id_op = NULL;
941 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
942 "Issuer not configured!\n");
943 GNUNET_SCHEDULER_add_now (&do_error, handle);
947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
948 "Connecting to credential service...\n");
949 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
952 if (NULL == handle->credential)
954 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
955 "Connecting to CREDENTIAL failed\n");
956 GNUNET_SCHEDULER_add_now (&do_error, handle);
959 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
960 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
963 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
966 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
967 "Missing expiration\n");
968 GNUNET_SCHEDULER_add_now (&do_error, handle);
971 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
973 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
976 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
977 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
980 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
981 "Malformed expiration: %s\n", expiration_str);
982 GNUNET_SCHEDULER_add_now (&do_error, handle);
985 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
986 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
989 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
992 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
993 "Missing issuer attribute\n");
994 GNUNET_SCHEDULER_add_now (&do_error, handle);
997 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
998 (handle->rest_handle->url_param_map,
1000 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
1001 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
1004 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
1007 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1008 "Missing subject\n");
1009 GNUNET_SCHEDULER_add_now (&do_error, handle);
1012 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1017 "Malformed subject\n");
1018 GNUNET_SCHEDULER_add_now (&do_error, handle);
1022 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1024 &handle->subject_key)) {
1025 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1026 "Malformed subject key\n");
1027 GNUNET_SCHEDULER_add_now (&do_error, handle);
1030 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1031 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1032 &handle->subject_key,
1033 handle->issuer_attr,
1037 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1038 "Failed to create credential\n");
1039 GNUNET_SCHEDULER_add_now (&do_error, handle);
1042 send_cred_response (handle, cred);
1047 issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1051 struct RequestHandle *handle = cls;
1053 handle->identity = GNUNET_IDENTITY_connect (cfg,
1056 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1057 "credential-issuer",
1058 &get_cred_issuer_cb,
1060 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1066 * Handle rest request
1068 * @param handle the lookup handle
1071 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1075 struct MHD_Response *resp;
1076 struct RequestHandle *handle = cls;
1078 //For GNS, independent of path return all options
1079 resp = GNUNET_REST_create_response (NULL);
1080 MHD_add_response_header (resp,
1081 "Access-Control-Allow-Methods",
1082 MHD_HTTP_METHOD_GET);
1083 handle->proc (handle->proc_cls,
1086 cleanup_handle (handle);
1091 * Function processing the REST call
1093 * @param method HTTP method
1094 * @param url URL of the HTTP request
1095 * @param data body of the HTTP request (optional)
1096 * @param data_size length of the body
1097 * @param proc callback function for the result
1098 * @param proc_cls closure for callback function
1099 * @return GNUNET_OK if request accepted
1102 rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1103 GNUNET_REST_ResultProcessor proc,
1106 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1107 struct GNUNET_REST_RequestHandlerError err;
1109 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1110 handle->proc_cls = proc_cls;
1111 handle->proc = proc;
1112 handle->rest_handle = conndata_handle;
1114 static const struct GNUNET_REST_RequestHandler handlers[] = {
1115 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1116 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1117 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1118 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1119 GNUNET_REST_HANDLER_END
1122 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1127 handle->response_code = err.error_code;
1128 GNUNET_SCHEDULER_add_now (&do_error, handle);
1134 * Entry point for the plugin.
1136 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1137 * @return NULL on error, otherwise the plugin context
1140 libgnunet_plugin_rest_credential_init (void *cls)
1142 static struct Plugin plugin;
1144 struct GNUNET_REST_Plugin *api;
1146 if (NULL != plugin.cfg)
1147 return NULL; /* can only initialize once! */
1148 memset (&plugin, 0, sizeof (struct Plugin));
1150 api = GNUNET_new (struct GNUNET_REST_Plugin);
1152 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1153 api->process_request = &rest_credential_process_request;
1154 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1155 _("GNS REST API initialized\n"));
1161 * Exit point from the plugin.
1163 * @param cls the plugin context (as returned by "init")
1164 * @return always NULL
1167 libgnunet_plugin_rest_credential_done (void *cls)
1169 struct GNUNET_REST_Plugin *api = cls;
1170 struct Plugin *plugin = api->cls;
1174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1175 "GNS REST plugin is finished\n");
1179 /* end of plugin_rest_gns.c */