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
66 const struct GNUNET_CONFIGURATION_Handle *cfg;
69 const struct GNUNET_CONFIGURATION_Handle *cfg;
71 struct RequestHandle {
73 * Handle to Credential service.
75 struct GNUNET_CREDENTIAL_Handle *credential;
78 * Handle to lookup request
80 struct GNUNET_CREDENTIAL_Request *verify_request;
83 * Handle to issue request
85 struct GNUNET_CREDENTIAL_Request *issue_request;
90 struct GNUNET_IDENTITY_Handle *identity;
93 * Handle to identity operation
95 struct GNUNET_IDENTITY_Operation *id_op;
98 * Handle to ego lookup
100 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
103 * Handle to rest request
105 struct GNUNET_REST_RequestHandle *rest_handle;
108 * ID of a task associated with the resolution process.
110 struct GNUNET_SCHEDULER_Task * timeout_task;
113 * The root of the received JSON or NULL
118 * The plugin result processor
120 GNUNET_REST_ResultProcessor proc;
123 * The closure of the result processor
128 * The issuer attribute to verify
133 * The subject attribute
138 * The public key of the issuer
140 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
143 * The public key of the subject
145 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
155 struct GNUNET_TIME_Relative timeout;
160 * Cleanup lookup handle.
162 * @param handle Handle to clean up
165 cleanup_handle(struct RequestHandle *handle)
167 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
169 if (NULL != handle->json_root)
170 json_decref(handle->json_root);
172 if (NULL != handle->issuer_attr)
173 GNUNET_free(handle->issuer_attr);
174 if (NULL != handle->subject_attr)
175 GNUNET_free(handle->subject_attr);
176 if (NULL != handle->verify_request)
177 GNUNET_CREDENTIAL_request_cancel(handle->verify_request);
178 if (NULL != handle->credential)
179 GNUNET_CREDENTIAL_disconnect(handle->credential);
180 if (NULL != handle->id_op)
181 GNUNET_IDENTITY_cancel(handle->id_op);
182 if (NULL != handle->ego_lookup)
183 GNUNET_IDENTITY_ego_lookup_cancel(handle->ego_lookup);
184 if (NULL != handle->identity)
185 GNUNET_IDENTITY_disconnect(handle->identity);
186 if (NULL != handle->timeout_task)
188 GNUNET_SCHEDULER_cancel(handle->timeout_task);
197 struct RequestHandle *handle = cls;
198 struct MHD_Response *resp;
200 resp = GNUNET_REST_create_response(NULL);
201 handle->proc(handle->proc_cls, resp, handle->response_code);
202 cleanup_handle(handle);
206 * Attribute delegation to JSON
208 * @param delegation_chain_entry the DSE
209 * @return JSON, NULL if failed
212 attribute_delegation_to_json(struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
218 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string(&delegation_chain_entry->issuer_key);
221 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
222 "Issuer in delegation malformed\n");
225 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string(&delegation_chain_entry->subject_key);
228 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
229 "Subject in credential malformed\n");
233 attr_obj = json_object();
235 json_object_set_new(attr_obj, "issuer", json_string(issuer));
236 json_object_set_new(attr_obj, "issuer_attribute",
237 json_string(delegation_chain_entry->issuer_attribute));
239 json_object_set_new(attr_obj, "subject", json_string(subject));
240 if (0 < delegation_chain_entry->subject_attribute_len)
242 json_object_set_new(attr_obj, "subject_attribute",
243 json_string(delegation_chain_entry->subject_attribute));
246 GNUNET_free(subject);
251 * JSONAPI resource to Credential
253 * @param res the JSONAPI resource
254 * @return the resulting credential, NULL if failed
256 static struct GNUNET_CREDENTIAL_Credential*
257 json_to_credential(json_t *res)
259 struct GNUNET_CREDENTIAL_Credential *cred;
261 const char *attribute;
262 const char *signature;
265 tmp = json_object_get(res, "attribute");
266 if (0 == json_is_string(tmp))
270 attribute = json_string_value(tmp);
271 cred = GNUNET_malloc(sizeof(struct GNUNET_CREDENTIAL_Credential)
272 + strlen(attribute));
273 cred->issuer_attribute = attribute;
274 cred->issuer_attribute_len = strlen(attribute);
275 tmp = json_object_get(res, "issuer");
276 if (0 == json_is_string(tmp))
282 GNUNET_CRYPTO_ecdsa_public_key_from_string(json_string_value(tmp),
283 strlen(json_string_value(tmp)),
285 tmp = json_object_get(res, "subject");
286 if (0 == json_is_string(tmp))
291 GNUNET_CRYPTO_ecdsa_public_key_from_string(json_string_value(tmp),
292 strlen(json_string_value(tmp)),
295 tmp = json_object_get(res, "signature");
296 if (0 == json_is_string(tmp))
301 signature = json_string_value(tmp);
302 GNUNET_STRINGS_base64_decode(signature,
305 GNUNET_memcpy(&cred->signature,
307 sizeof(struct GNUNET_CRYPTO_EcdsaSignature));
310 tmp = json_object_get(res, "expiration");
311 if (0 == json_is_integer(tmp))
316 cred->expiration.abs_value_us = json_integer_value(tmp);
324 * @param cred the credential
325 * @return the resulting json, NULL if failed
328 credential_to_json(struct GNUNET_CREDENTIAL_Credential *cred)
333 char attribute[cred->issuer_attribute_len + 1];
336 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string(&cred->issuer_key);
339 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
340 "Issuer in credential malformed\n");
343 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string(&cred->subject_key);
346 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
347 "Subject in credential malformed\n");
351 GNUNET_STRINGS_base64_encode((char*)&cred->signature,
352 sizeof(struct GNUNET_CRYPTO_EcdsaSignature),
354 GNUNET_memcpy(attribute,
355 cred->issuer_attribute,
356 cred->issuer_attribute_len);
357 attribute[cred->issuer_attribute_len] = '\0';
358 cred_obj = json_object();
359 json_object_set_new(cred_obj, "issuer", json_string(issuer));
360 json_object_set_new(cred_obj, "subject", json_string(subject));
361 json_object_set_new(cred_obj, "attribute", json_string(attribute));
362 json_object_set_new(cred_obj, "signature", json_string(signature));
363 json_object_set_new(cred_obj, "expiration", json_integer(cred->expiration.abs_value_us));
365 GNUNET_free(subject);
366 GNUNET_free(signature);
371 handle_collect_response(void *cls,
372 unsigned int d_count,
373 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
374 unsigned int c_count,
375 struct GNUNET_CREDENTIAL_Credential *cred)
377 struct RequestHandle *handle = cls;
378 struct MHD_Response *resp;
379 struct GNUNET_JSONAPI_Document *json_document;
380 struct GNUNET_JSONAPI_Resource *json_resource;
388 handle->verify_request = NULL;
391 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
393 handle->response_code = MHD_HTTP_NOT_FOUND;
394 GNUNET_SCHEDULER_add_now(&do_error, handle);
397 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string(&handle->issuer_key);
400 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
401 "Issuer in delegation malformed\n");
407 handle->issuer_attr);
409 json_document = GNUNET_JSONAPI_document_new();
410 json_resource = GNUNET_JSONAPI_resource_new(GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
413 cred_array = json_array();
414 for (i = 0; i < c_count; i++)
416 cred_obj = credential_to_json(&cred[i]);
417 json_array_append_new(cred_array, cred_obj);
419 GNUNET_JSONAPI_resource_add_attr(json_resource,
420 GNUNET_REST_JSONAPI_CREDENTIAL,
422 GNUNET_JSONAPI_document_resource_add(json_document, json_resource);
423 GNUNET_JSONAPI_document_serialize(json_document, &result);
424 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
427 json_decref(cred_array);
428 GNUNET_JSONAPI_document_delete(json_document);
429 resp = GNUNET_REST_create_response(result);
431 handle->proc(handle->proc_cls, resp, MHD_HTTP_OK);
432 cleanup_handle(handle);
436 subject_ego_lookup(void *cls,
437 const struct GNUNET_IDENTITY_Ego *ego)
439 struct RequestHandle *handle = cls;
440 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
442 handle->ego_lookup = NULL;
446 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
447 "Subject not found\n");
448 GNUNET_SCHEDULER_add_now(&do_error, handle);
451 sub_key = GNUNET_IDENTITY_ego_get_private_key(ego);
452 handle->verify_request = GNUNET_CREDENTIAL_collect(handle->credential,
456 &handle_collect_response,
463 handle_verify_response(void *cls,
464 unsigned int d_count,
465 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
466 unsigned int c_count,
467 struct GNUNET_CREDENTIAL_Credential *cred)
469 struct RequestHandle *handle = cls;
470 struct MHD_Response *resp;
471 struct GNUNET_JSONAPI_Document *json_document;
472 struct GNUNET_JSONAPI_Resource *json_resource;
482 handle->verify_request = NULL;
485 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
487 handle->response_code = MHD_HTTP_NOT_FOUND;
488 GNUNET_SCHEDULER_add_now(&do_error, handle);
491 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string(&handle->issuer_key);
494 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
495 "Issuer in delegation malformed\n");
501 handle->issuer_attr);
503 json_document = GNUNET_JSONAPI_document_new();
504 json_resource = GNUNET_JSONAPI_resource_new(GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
507 attr_array = json_array();
508 for (i = 0; i < d_count; i++)
510 attr_obj = attribute_delegation_to_json(&delegation_chain[i]);
511 json_array_append_new(attr_array, attr_obj);
513 cred_array = json_array();
514 for (i = 0; i < c_count; i++)
516 cred_obj = credential_to_json(&cred[i]);
517 json_array_append_new(cred_array, cred_obj);
519 GNUNET_JSONAPI_resource_add_attr(json_resource,
520 GNUNET_REST_JSONAPI_CREDENTIAL,
522 GNUNET_JSONAPI_resource_add_attr(json_resource,
523 GNUNET_REST_JSONAPI_DELEGATIONS,
525 GNUNET_JSONAPI_document_resource_add(json_document, json_resource);
526 GNUNET_JSONAPI_document_serialize(json_document, &result);
527 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
530 json_decref(attr_array);
531 json_decref(cred_array);
532 GNUNET_JSONAPI_document_delete(json_document);
533 resp = GNUNET_REST_create_response(result);
534 handle->proc(handle->proc_cls, resp, MHD_HTTP_OK);
536 cleanup_handle(handle);
540 collect_cred_cont(struct GNUNET_REST_RequestHandle *conndata_handle,
544 struct RequestHandle *handle = cls;
545 struct GNUNET_HashCode key;
549 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
551 handle->credential = GNUNET_CREDENTIAL_connect(cfg);
552 handle->timeout_task = GNUNET_SCHEDULER_add_delayed(handle->timeout,
554 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
556 if (NULL == handle->credential)
558 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
559 "Connecting to CREDENTIAL failed\n");
560 GNUNET_SCHEDULER_add_now(&do_error, handle);
563 GNUNET_CRYPTO_hash(GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
564 strlen(GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
567 GNUNET_CONTAINER_multihashmap_contains(conndata_handle->url_param_map,
570 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
571 "Missing issuer attribute\n");
572 GNUNET_SCHEDULER_add_now(&do_error, handle);
575 tmp = GNUNET_CONTAINER_multihashmap_get(conndata_handle->url_param_map,
577 entity_attr = GNUNET_strdup(tmp);
578 tmp = strtok(entity_attr, ".");
581 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
582 "Malformed issuer or attribute\n");
583 GNUNET_free(entity_attr);
584 GNUNET_SCHEDULER_add_now(&do_error, handle);
588 GNUNET_CRYPTO_ecdsa_public_key_from_string(tmp,
590 &handle->issuer_key))
592 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
593 "Malformed issuer key\n");
594 GNUNET_free(entity_attr);
595 GNUNET_SCHEDULER_add_now(&do_error, handle);
598 tmp = strtok(NULL, "."); //Issuer attribute
601 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
602 "Malformed attribute\n");
603 GNUNET_free(entity_attr);
604 GNUNET_SCHEDULER_add_now(&do_error, handle);
607 handle->issuer_attr = GNUNET_strdup(tmp);
608 GNUNET_free(entity_attr);
610 GNUNET_CRYPTO_hash(GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
611 strlen(GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
614 GNUNET_CONTAINER_multihashmap_contains(conndata_handle->url_param_map,
617 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
618 "Missing subject\n");
619 GNUNET_SCHEDULER_add_now(&do_error, handle);
622 tmp = GNUNET_CONTAINER_multihashmap_get(conndata_handle->url_param_map,
626 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
627 "Malformed subject\n");
628 GNUNET_SCHEDULER_add_now(&do_error, handle);
631 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup(cfg,
640 verify_cred_cont(struct GNUNET_REST_RequestHandle *conndata_handle,
644 struct RequestHandle *handle = cls;
645 struct GNUNET_HashCode key;
646 struct GNUNET_JSONAPI_Document *json_obj;
647 struct GNUNET_JSONAPI_Resource *res;
648 struct GNUNET_CREDENTIAL_Credential *cred;
652 uint32_t credential_count;
653 uint32_t resource_count;
658 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
660 handle->credential = GNUNET_CREDENTIAL_connect(cfg);
661 handle->timeout_task = GNUNET_SCHEDULER_add_delayed(handle->timeout,
663 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
665 if (NULL == handle->credential)
667 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
668 "Connecting to CREDENTIAL failed\n");
669 GNUNET_SCHEDULER_add_now(&do_error, handle);
672 GNUNET_CRYPTO_hash(GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
673 strlen(GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
676 GNUNET_CONTAINER_multihashmap_contains(conndata_handle->url_param_map,
679 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
680 "Missing issuer attribute\n");
681 GNUNET_SCHEDULER_add_now(&do_error, handle);
684 tmp = GNUNET_CONTAINER_multihashmap_get(conndata_handle->url_param_map,
686 entity_attr = GNUNET_strdup(tmp);
687 tmp = strtok(entity_attr, ".");
690 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
691 "Malformed issuer or attribute\n");
692 GNUNET_free(entity_attr);
693 GNUNET_SCHEDULER_add_now(&do_error, handle);
697 GNUNET_CRYPTO_ecdsa_public_key_from_string(tmp,
699 &handle->issuer_key))
701 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
702 "Malformed issuer key\n");
703 GNUNET_free(entity_attr);
704 GNUNET_SCHEDULER_add_now(&do_error, handle);
707 tmp = strtok(NULL, "."); //Issuer attribute
710 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
711 "Malformed attribute\n");
712 GNUNET_free(entity_attr);
713 GNUNET_SCHEDULER_add_now(&do_error, handle);
716 handle->issuer_attr = GNUNET_strdup(tmp);
717 GNUNET_free(entity_attr);
719 GNUNET_CRYPTO_hash(GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
720 strlen(GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
723 GNUNET_CONTAINER_multihashmap_contains(conndata_handle->url_param_map,
726 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
727 "Missing subject key\n");
728 GNUNET_SCHEDULER_add_now(&do_error, handle);
731 tmp = GNUNET_CONTAINER_multihashmap_get(conndata_handle->url_param_map,
735 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
736 "Malformed subject\n");
737 GNUNET_SCHEDULER_add_now(&do_error, handle);
741 GNUNET_CRYPTO_ecdsa_public_key_from_string(tmp,
743 &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);
836 send_cred_response(struct RequestHandle *handle,
837 struct GNUNET_CREDENTIAL_Credential *cred)
839 struct MHD_Response *resp;
840 struct GNUNET_JSONAPI_Document *json_document;
841 struct GNUNET_JSONAPI_Resource *json_resource;
849 GNUNET_assert(NULL != cred);
850 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string(&cred->issuer_key);
853 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
854 "Subject malformed\n");
862 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string(&cred->subject_key);
865 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
866 "Subject malformed\n");
871 GNUNET_STRINGS_base64_encode((char*)&cred->signature,
872 sizeof(struct GNUNET_CRYPTO_EcdsaSignature),
874 json_document = GNUNET_JSONAPI_document_new();
875 json_resource = GNUNET_JSONAPI_resource_new(GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
878 cred_obj = json_object();
879 json_object_set_new(cred_obj, "issuer", json_string(issuer));
880 json_object_set_new(cred_obj, "subject", json_string(subject));
881 json_object_set_new(cred_obj, "expiration", json_integer(cred->expiration.abs_value_us));
882 json_object_set_new(cred_obj, "signature", json_string(signature));
883 GNUNET_JSONAPI_resource_add_attr(json_resource,
884 GNUNET_REST_JSONAPI_CREDENTIAL,
886 GNUNET_JSONAPI_document_resource_add(json_document, json_resource);
887 GNUNET_JSONAPI_document_serialize(json_document, &result);
888 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
891 json_decref(cred_obj);
892 GNUNET_JSONAPI_document_delete(json_document);
893 resp = GNUNET_REST_create_response(result);
894 handle->proc(handle->proc_cls, resp, MHD_HTTP_OK);
896 GNUNET_free(signature);
898 GNUNET_free(subject);
899 cleanup_handle(handle);
903 get_cred_issuer_cb(void *cls,
904 struct GNUNET_IDENTITY_Ego *ego,
908 struct RequestHandle *handle = cls;
909 struct GNUNET_TIME_Absolute etime_abs;
910 struct GNUNET_TIME_Relative etime_rel;
911 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
912 struct GNUNET_HashCode key;
913 struct GNUNET_CREDENTIAL_Credential *cred;
914 char* expiration_str;
917 handle->id_op = NULL;
921 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
922 "Issuer not configured!\n");
923 GNUNET_SCHEDULER_add_now(&do_error, handle);
927 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
928 "Connecting to credential service...\n");
929 handle->credential = GNUNET_CREDENTIAL_connect(cfg);
930 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
932 if (NULL == handle->credential)
934 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
935 "Connecting to CREDENTIAL failed\n");
936 GNUNET_SCHEDULER_add_now(&do_error, handle);
939 GNUNET_CRYPTO_hash(GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
940 strlen(GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
943 GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map,
946 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
947 "Missing expiration\n");
948 GNUNET_SCHEDULER_add_now(&do_error, handle);
951 expiration_str = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
953 if (NULL == expiration_str)
955 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
956 "Expiration malformed\n");
957 GNUNET_SCHEDULER_add_now(&do_error, handle);
961 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative(expiration_str,
964 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))
1015 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1016 "Malformed subject key\n");
1017 GNUNET_SCHEDULER_add_now(&do_error, handle);
1020 issuer_key = GNUNET_IDENTITY_ego_get_private_key(ego);
1021 cred = GNUNET_CREDENTIAL_credential_issue(issuer_key,
1022 &handle->subject_key,
1023 handle->issuer_attr,
1027 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1028 "Failed to create credential\n");
1029 GNUNET_SCHEDULER_add_now(&do_error, handle);
1032 send_cred_response(handle, cred);
1037 issue_cred_cont(struct GNUNET_REST_RequestHandle *conndata_handle,
1041 struct RequestHandle *handle = cls;
1043 handle->identity = GNUNET_IDENTITY_connect(cfg,
1046 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1047 "credential-issuer",
1048 &get_cred_issuer_cb,
1050 handle->timeout_task = GNUNET_SCHEDULER_add_delayed(handle->timeout,
1056 options_cont(struct GNUNET_REST_RequestHandle *con_handle,
1060 struct MHD_Response *resp;
1061 struct RequestHandle *handle = cls;
1063 //For GNS, independent of path return all options
1064 resp = GNUNET_REST_create_response(NULL);
1065 MHD_add_response_header(resp,
1066 "Access-Control-Allow-Methods",
1067 MHD_HTTP_METHOD_GET);
1068 handle->proc(handle->proc_cls,
1071 cleanup_handle(handle);
1076 rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1077 GNUNET_REST_ResultProcessor proc,
1080 struct RequestHandle *handle = GNUNET_new(struct RequestHandle);
1081 struct GNUNET_REST_RequestHandlerError err;
1083 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1084 handle->proc_cls = proc_cls;
1085 handle->proc = proc;
1086 handle->rest_handle = conndata_handle;
1088 static const struct GNUNET_REST_RequestHandler handlers[] = {
1089 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont },
1090 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont },
1091 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont },
1092 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont },
1093 GNUNET_REST_HANDLER_END
1096 if (GNUNET_NO == GNUNET_JSONAPI_handle_request(conndata_handle,
1101 handle->response_code = err.error_code;
1102 GNUNET_SCHEDULER_add_now(&do_error, handle);
1108 * Entry point for the plugin.
1110 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1111 * @return NULL on error, otherwise the plugin context
1114 libgnunet_plugin_rest_credential_init(void *cls)
1116 static struct Plugin plugin;
1119 struct GNUNET_REST_Plugin *api;
1121 if (NULL != plugin.cfg)
1122 return NULL; /* can only initialize once! */
1123 memset(&plugin, 0, sizeof(struct Plugin));
1125 api = GNUNET_new(struct GNUNET_REST_Plugin);
1127 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1128 api->process_request = &rest_credential_process_request;
1129 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1130 _("GNS REST API initialized\n"));
1136 * Exit point from the plugin.
1138 * @param cls the plugin context (as returned by "init")
1139 * @return always NULL
1142 libgnunet_plugin_rest_credential_done(void *cls)
1144 struct GNUNET_REST_Plugin *api = cls;
1145 struct Plugin *plugin = api->cls;
1149 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1150 "GNS REST plugin is finished\n");
1154 /* end of plugin_rest_gns.c */