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/>.
19 * @author Martin Schanzenbach
20 * @file credential/plugin_rest_credential.c
21 * @brief GNUnet CREDENTIAL REST plugin
26 #include "gnunet_rest_plugin.h"
27 #include <gnunet_identity_service.h>
28 #include <gnunet_gnsrecord_lib.h>
29 #include <gnunet_namestore_service.h>
30 #include <gnunet_credential_service.h>
31 #include <gnunet_rest_lib.h>
32 #include <gnunet_jsonapi_lib.h>
33 #include <gnunet_jsonapi_util.h>
36 #define GNUNET_REST_API_NS_CREDENTIAL "/credential"
38 #define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
40 #define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
42 #define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
44 #define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
46 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
48 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
50 #define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
52 #define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
54 #define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
56 #define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
58 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
61 * @brief struct returned by the initialization function of the plugin
65 const struct GNUNET_CONFIGURATION_Handle *cfg;
68 const struct GNUNET_CONFIGURATION_Handle *cfg;
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;
161 * Cleanup lookup handle.
163 * @param handle Handle to clean up
166 cleanup_handle (struct RequestHandle *handle)
168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
170 if (NULL != handle->json_root)
171 json_decref (handle->json_root);
173 if (NULL != handle->issuer_attr)
174 GNUNET_free (handle->issuer_attr);
175 if (NULL != handle->subject_attr)
176 GNUNET_free (handle->subject_attr);
177 if (NULL != handle->verify_request)
178 GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
179 if (NULL != handle->credential)
180 GNUNET_CREDENTIAL_disconnect (handle->credential);
181 if (NULL != handle->id_op)
182 GNUNET_IDENTITY_cancel (handle->id_op);
183 if (NULL != handle->ego_lookup)
184 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
185 if (NULL != handle->identity)
186 GNUNET_IDENTITY_disconnect (handle->identity);
187 if (NULL != handle->timeout_task)
189 GNUNET_SCHEDULER_cancel (handle->timeout_task);
191 GNUNET_free (handle);
198 struct RequestHandle *handle = cls;
199 struct MHD_Response *resp;
201 resp = GNUNET_REST_create_response (NULL);
202 handle->proc (handle->proc_cls, resp, handle->response_code);
203 cleanup_handle (handle);
207 * Attribute delegation to JSON
209 * @param delegation_chain_entry the DSE
210 * @return JSON, NULL if failed
213 attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
219 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
222 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
223 "Issuer in delegation malformed\n");
226 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
230 "Subject in credential malformed\n");
231 GNUNET_free (issuer);
234 attr_obj = json_object ();
236 json_object_set_new (attr_obj, "issuer", json_string (issuer));
237 json_object_set_new (attr_obj, "issuer_attribute",
238 json_string (delegation_chain_entry->issuer_attribute));
240 json_object_set_new (attr_obj, "subject", json_string (subject));
241 if (0 < delegation_chain_entry->subject_attribute_len)
243 json_object_set_new (attr_obj, "subject_attribute",
244 json_string (delegation_chain_entry->subject_attribute));
246 GNUNET_free (issuer);
247 GNUNET_free (subject);
252 * JSONAPI resource to Credential
254 * @param res the JSONAPI resource
255 * @return the resulting credential, NULL if failed
257 static struct GNUNET_CREDENTIAL_Credential*
258 json_to_credential (json_t *res)
260 struct GNUNET_CREDENTIAL_Credential *cred;
262 const char *attribute;
263 const char *signature;
266 tmp = json_object_get (res, "attribute");
267 if (0 == json_is_string (tmp))
271 attribute = json_string_value (tmp);
272 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
273 + strlen (attribute));
274 cred->issuer_attribute = attribute;
275 cred->issuer_attribute_len = strlen (attribute);
276 tmp = json_object_get (res, "issuer");
277 if (0 == json_is_string (tmp))
283 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
284 strlen (json_string_value(tmp)),
286 tmp = json_object_get (res, "subject");
287 if (0 == json_is_string (tmp))
292 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
293 strlen (json_string_value(tmp)),
296 tmp = json_object_get (res, "signature");
297 if (0 == json_is_string (tmp))
302 signature = json_string_value (tmp);
303 GNUNET_STRINGS_base64_decode (signature,
306 GNUNET_memcpy (&cred->signature,
308 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
311 tmp = json_object_get (res, "expiration");
312 if (0 == json_is_integer (tmp))
317 cred->expiration.abs_value_us = json_integer_value (tmp);
325 * @param cred the credential
326 * @return the resulting json, NULL if failed
329 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
334 char attribute[cred->issuer_attribute_len + 1];
337 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
340 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
341 "Issuer in credential malformed\n");
344 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
348 "Subject in credential malformed\n");
349 GNUNET_free (issuer);
352 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
353 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
355 GNUNET_memcpy (attribute,
356 cred->issuer_attribute,
357 cred->issuer_attribute_len);
358 attribute[cred->issuer_attribute_len] = '\0';
359 cred_obj = json_object ();
360 json_object_set_new (cred_obj, "issuer", json_string (issuer));
361 json_object_set_new (cred_obj, "subject", json_string (subject));
362 json_object_set_new (cred_obj, "attribute", json_string (attribute));
363 json_object_set_new (cred_obj, "signature", json_string (signature));
364 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
365 GNUNET_free (issuer);
366 GNUNET_free (subject);
367 GNUNET_free (signature);
372 handle_collect_response (void *cls,
373 unsigned int d_count,
374 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
375 unsigned int c_count,
376 struct GNUNET_CREDENTIAL_Credential *cred)
378 struct RequestHandle *handle = cls;
379 struct MHD_Response *resp;
380 struct GNUNET_JSONAPI_Document *json_document;
381 struct GNUNET_JSONAPI_Resource *json_resource;
389 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");
404 GNUNET_asprintf (&id,
407 handle->issuer_attr);
408 GNUNET_free (issuer);
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;
441 handle->ego_lookup = NULL;
445 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
446 "Subject not found\n");
447 GNUNET_SCHEDULER_add_now (&do_error, handle);
450 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
451 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
455 &handle_collect_response,
462 handle_verify_response (void *cls,
463 unsigned int d_count,
464 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
465 unsigned int c_count,
466 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;
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
486 handle->response_code = MHD_HTTP_NOT_FOUND;
487 GNUNET_SCHEDULER_add_now (&do_error, handle);
490 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
493 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
494 "Issuer in delegation malformed\n");
497 GNUNET_asprintf (&id,
500 handle->issuer_attr);
501 GNUNET_free (issuer);
502 json_document = GNUNET_JSONAPI_document_new ();
503 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
506 attr_array = json_array ();
507 for (i = 0; i < d_count; i++)
509 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
510 json_array_append_new (attr_array, attr_obj);
512 cred_array = json_array ();
513 for (i=0;i<c_count;i++)
515 cred_obj = credential_to_json (&cred[i]);
516 json_array_append_new (cred_array, cred_obj);
518 GNUNET_JSONAPI_resource_add_attr (json_resource,
519 GNUNET_REST_JSONAPI_CREDENTIAL,
521 GNUNET_JSONAPI_resource_add_attr (json_resource,
522 GNUNET_REST_JSONAPI_DELEGATIONS,
524 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
525 GNUNET_JSONAPI_document_serialize (json_document, &result);
526 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 json_decref (attr_array);
530 json_decref (cred_array);
531 GNUNET_JSONAPI_document_delete (json_document);
532 resp = GNUNET_REST_create_response (result);
533 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
534 GNUNET_free (result);
535 cleanup_handle (handle);
539 collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
543 struct RequestHandle *handle = cls;
544 struct GNUNET_HashCode key;
548 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
550 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
551 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
553 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
555 if (NULL == handle->credential)
557 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
558 "Connecting to CREDENTIAL failed\n");
559 GNUNET_SCHEDULER_add_now (&do_error, handle);
562 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
563 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
566 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
569 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
570 "Missing issuer attribute\n");
571 GNUNET_SCHEDULER_add_now (&do_error, handle);
574 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
576 entity_attr = GNUNET_strdup (tmp);
577 tmp = strtok(entity_attr, ".");
580 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
581 "Malformed issuer or attribute\n");
582 GNUNET_free (entity_attr);
583 GNUNET_SCHEDULER_add_now (&do_error, handle);
587 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
589 &handle->issuer_key))
591 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
592 "Malformed issuer key\n");
593 GNUNET_free (entity_attr);
594 GNUNET_SCHEDULER_add_now (&do_error, handle);
597 tmp = strtok (NULL, "."); //Issuer attribute
600 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
601 "Malformed attribute\n");
602 GNUNET_free (entity_attr);
603 GNUNET_SCHEDULER_add_now (&do_error, handle);
606 handle->issuer_attr = GNUNET_strdup (tmp);
607 GNUNET_free (entity_attr);
609 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
610 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
613 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
616 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
617 "Missing subject\n");
618 GNUNET_SCHEDULER_add_now (&do_error, handle);
621 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
625 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
626 "Malformed subject\n");
627 GNUNET_SCHEDULER_add_now (&do_error, handle);
630 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
639 verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
643 struct RequestHandle *handle = cls;
644 struct GNUNET_HashCode key;
645 struct GNUNET_JSONAPI_Document *json_obj;
646 struct GNUNET_JSONAPI_Resource *res;
647 struct GNUNET_CREDENTIAL_Credential *cred;
651 uint32_t credential_count;
652 uint32_t resource_count;
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
659 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
660 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
664 if (NULL == handle->credential)
666 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
667 "Connecting to CREDENTIAL failed\n");
668 GNUNET_SCHEDULER_add_now (&do_error, handle);
671 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
672 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
675 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
678 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
679 "Missing issuer attribute\n");
680 GNUNET_SCHEDULER_add_now (&do_error, handle);
683 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
685 entity_attr = GNUNET_strdup (tmp);
686 tmp = strtok(entity_attr, ".");
689 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
690 "Malformed issuer or attribute\n");
691 GNUNET_free (entity_attr);
692 GNUNET_SCHEDULER_add_now (&do_error, handle);
696 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
698 &handle->issuer_key))
700 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
701 "Malformed issuer key\n");
702 GNUNET_free (entity_attr);
703 GNUNET_SCHEDULER_add_now (&do_error, handle);
706 tmp = strtok (NULL, "."); //Issuer attribute
709 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
710 "Malformed attribute\n");
711 GNUNET_free (entity_attr);
712 GNUNET_SCHEDULER_add_now (&do_error, handle);
715 handle->issuer_attr = GNUNET_strdup (tmp);
716 GNUNET_free (entity_attr);
718 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
719 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
722 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
725 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
726 "Missing subject key\n");
727 GNUNET_SCHEDULER_add_now (&do_error, handle);
730 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
734 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
735 "Malformed subject\n");
736 GNUNET_SCHEDULER_add_now (&do_error, handle);
740 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
742 &handle->subject_key)) {
743 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
744 "Malformed subject key\n");
745 GNUNET_SCHEDULER_add_now (&do_error, handle);
749 if (0 >= handle->rest_handle->data_size)
751 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
752 "Missing credentials\n");
753 GNUNET_SCHEDULER_add_now (&do_error, handle);
757 struct GNUNET_JSON_Specification docspec[] = {
758 GNUNET_JSON_spec_jsonapi_document (&json_obj),
759 GNUNET_JSON_spec_end()
761 char term_data[handle->rest_handle->data_size+1];
762 term_data[handle->rest_handle->data_size] = '\0';
763 credential_count = 0;
764 GNUNET_memcpy (term_data,
765 handle->rest_handle->data,
766 handle->rest_handle->data_size);
767 data_js = json_loads (term_data,
770 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
772 json_decref (data_js);
773 if (NULL == json_obj)
775 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
776 "Unable to parse JSONAPI Object from %s\n",
778 GNUNET_SCHEDULER_add_now (&do_error, handle);
782 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
783 GNUNET_assert (1 == resource_count);
784 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
785 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
786 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
788 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
789 "Resource not a credential!\n");
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
791 "Unable to parse JSONAPI Object from %s\n",
793 GNUNET_JSONAPI_document_delete (json_obj);
794 GNUNET_SCHEDULER_add_now (&do_error, handle);
797 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
798 GNUNET_REST_JSONAPI_CREDENTIAL);
800 GNUNET_assert (json_is_array (cred_json));
802 credential_count = json_array_size(cred_json);
804 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
805 for (i=0;i<credential_count;i++)
807 cred = json_to_credential (json_array_get (cred_json, i));
810 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
811 "Unable to parse credential!\n");
814 GNUNET_memcpy (&credentials[i],
816 sizeof (struct GNUNET_CREDENTIAL_Credential));
817 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
820 GNUNET_JSONAPI_document_delete(json_obj);
821 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
824 &handle->subject_key,
827 &handle_verify_response,
829 for (i=0;i<credential_count;i++)
830 GNUNET_free ((char*)credentials[i].issuer_attribute);
835 send_cred_response (struct RequestHandle *handle,
836 struct GNUNET_CREDENTIAL_Credential *cred)
838 struct MHD_Response *resp;
839 struct GNUNET_JSONAPI_Document *json_document;
840 struct GNUNET_JSONAPI_Resource *json_resource;
848 GNUNET_assert (NULL != cred);
849 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
852 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
853 "Subject malformed\n");
854 GNUNET_free (issuer);
857 GNUNET_asprintf (&id,
861 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
864 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
865 "Subject malformed\n");
867 GNUNET_free (issuer);
870 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
871 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
873 json_document = GNUNET_JSONAPI_document_new ();
874 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
877 cred_obj = json_object();
878 json_object_set_new (cred_obj, "issuer", json_string (issuer));
879 json_object_set_new (cred_obj, "subject", json_string (subject));
880 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
881 json_object_set_new (cred_obj, "signature", json_string (signature));
882 GNUNET_JSONAPI_resource_add_attr (json_resource,
883 GNUNET_REST_JSONAPI_CREDENTIAL,
885 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
886 GNUNET_JSONAPI_document_serialize (json_document, &result);
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
890 json_decref (cred_obj);
891 GNUNET_JSONAPI_document_delete (json_document);
892 resp = GNUNET_REST_create_response (result);
893 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
894 GNUNET_free (result);
895 GNUNET_free (signature);
896 GNUNET_free (issuer);
897 GNUNET_free (subject);
898 cleanup_handle (handle);
902 get_cred_issuer_cb (void *cls,
903 struct GNUNET_IDENTITY_Ego *ego,
907 struct RequestHandle *handle = cls;
908 struct GNUNET_TIME_Absolute etime_abs;
909 struct GNUNET_TIME_Relative etime_rel;
910 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
911 struct GNUNET_HashCode key;
912 struct GNUNET_CREDENTIAL_Credential *cred;
913 char* expiration_str;
916 handle->id_op = NULL;
920 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
921 "Issuer not configured!\n");
922 GNUNET_SCHEDULER_add_now (&do_error, handle);
926 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
927 "Connecting to credential service...\n");
928 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
929 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 if (NULL == handle->credential)
933 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
934 "Connecting to CREDENTIAL failed\n");
935 GNUNET_SCHEDULER_add_now (&do_error, handle);
938 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
939 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
942 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
945 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
946 "Missing expiration\n");
947 GNUNET_SCHEDULER_add_now (&do_error, handle);
950 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
952 if ( NULL == expiration_str )
954 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
955 "Expiration malformed\n");
956 GNUNET_SCHEDULER_add_now (&do_error, handle);
960 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
963 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
964 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
967 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
968 "Malformed expiration: %s\n", expiration_str);
969 GNUNET_SCHEDULER_add_now (&do_error, handle);
972 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
973 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
976 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
979 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
980 "Missing issuer attribute\n");
981 GNUNET_SCHEDULER_add_now (&do_error, handle);
984 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
985 (handle->rest_handle->url_param_map,
987 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
988 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
991 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
994 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
995 "Missing subject\n");
996 GNUNET_SCHEDULER_add_now (&do_error, handle);
999 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1003 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1004 "Malformed subject\n");
1005 GNUNET_SCHEDULER_add_now (&do_error, handle);
1009 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1011 &handle->subject_key)) {
1012 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1013 "Malformed subject key\n");
1014 GNUNET_SCHEDULER_add_now (&do_error, handle);
1017 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1018 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1019 &handle->subject_key,
1020 handle->issuer_attr,
1024 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1025 "Failed to create credential\n");
1026 GNUNET_SCHEDULER_add_now (&do_error, handle);
1029 send_cred_response (handle, cred);
1034 issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1038 struct RequestHandle *handle = cls;
1040 handle->identity = GNUNET_IDENTITY_connect (cfg,
1043 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1044 "credential-issuer",
1045 &get_cred_issuer_cb,
1047 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1053 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1057 struct MHD_Response *resp;
1058 struct RequestHandle *handle = cls;
1060 //For GNS, independent of path return all options
1061 resp = GNUNET_REST_create_response (NULL);
1062 MHD_add_response_header (resp,
1063 "Access-Control-Allow-Methods",
1064 MHD_HTTP_METHOD_GET);
1065 handle->proc (handle->proc_cls,
1068 cleanup_handle (handle);
1073 rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1074 GNUNET_REST_ResultProcessor proc,
1077 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1078 struct GNUNET_REST_RequestHandlerError err;
1080 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1081 handle->proc_cls = proc_cls;
1082 handle->proc = proc;
1083 handle->rest_handle = conndata_handle;
1085 static const struct GNUNET_REST_RequestHandler handlers[] = {
1086 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1087 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1088 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1089 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1090 GNUNET_REST_HANDLER_END
1093 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1098 handle->response_code = err.error_code;
1099 GNUNET_SCHEDULER_add_now (&do_error, handle);
1105 * Entry point for the plugin.
1107 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1108 * @return NULL on error, otherwise the plugin context
1111 libgnunet_plugin_rest_credential_init (void *cls)
1113 static struct Plugin plugin;
1115 struct GNUNET_REST_Plugin *api;
1117 if (NULL != plugin.cfg)
1118 return NULL; /* can only initialize once! */
1119 memset (&plugin, 0, sizeof (struct Plugin));
1121 api = GNUNET_new (struct GNUNET_REST_Plugin);
1123 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1124 api->process_request = &rest_credential_process_request;
1125 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1126 _("GNS REST API initialized\n"));
1132 * Exit point from the plugin.
1134 * @param cls the plugin context (as returned by "init")
1135 * @return always NULL
1138 libgnunet_plugin_rest_credential_done (void *cls)
1140 struct GNUNET_REST_Plugin *api = cls;
1141 struct Plugin *plugin = api->cls;
1145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1146 "GNS REST plugin is finished\n");
1150 /* end of plugin_rest_gns.c */