aboutsummaryrefslogtreecommitdiff
path: root/src/rest-plugins
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2019-03-12 09:46:51 +0100
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2019-03-12 09:46:51 +0100
commitdbccb37562c243c5099ec07a602a437f6e985a1e (patch)
treeb9f60403534e0335080c6a34fe5f8935a59aa7ae /src/rest-plugins
parent1057efede9f4d08ff9d215162a7ebdeea4869e20 (diff)
downloadgnunet-dbccb37562c243c5099ec07a602a437f6e985a1e.tar.gz
gnunet-dbccb37562c243c5099ec07a602a437f6e985a1e.zip
move disfunc credential
Diffstat (limited to 'src/rest-plugins')
-rw-r--r--src/rest-plugins/plugin_rest_credential.c1152
1 files changed, 0 insertions, 1152 deletions
diff --git a/src/rest-plugins/plugin_rest_credential.c b/src/rest-plugins/plugin_rest_credential.c
deleted file mode 100644
index 78267b54e..000000000
--- a/src/rest-plugins/plugin_rest_credential.c
+++ /dev/null
@@ -1,1152 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2016 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file credential/plugin_rest_credential.c
23 * @brief GNUnet CREDENTIAL REST plugin
24 *
25 */
26
27#include "platform.h"
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>
36#include <jansson.h>
37
38#define GNUNET_REST_API_NS_CREDENTIAL "/credential"
39
40#define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
41
42#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
43
44#define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
45
46#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
47
48#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
49
50#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
51
52#define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
53
54#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
55
56#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
57
58#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
59
60#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
61
62/**
63 * @brief struct returned by the initialization function of the plugin
64 */
65struct Plugin
66{
67 const struct GNUNET_CONFIGURATION_Handle *cfg;
68};
69
70const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72struct RequestHandle
73{
74 /**
75 * Handle to Credential service.
76 */
77 struct GNUNET_CREDENTIAL_Handle *credential;
78
79 /**
80 * Handle to lookup request
81 */
82 struct GNUNET_CREDENTIAL_Request *verify_request;
83
84 /**
85 * Handle to issue request
86 */
87 struct GNUNET_CREDENTIAL_Request *issue_request;
88
89 /**
90 * Handle to identity
91 */
92 struct GNUNET_IDENTITY_Handle *identity;
93
94 /**
95 * Handle to identity operation
96 */
97 struct GNUNET_IDENTITY_Operation *id_op;
98
99 /**
100 * Handle to ego lookup
101 */
102 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
103
104 /**
105 * Handle to rest request
106 */
107 struct GNUNET_REST_RequestHandle *rest_handle;
108
109 /**
110 * ID of a task associated with the resolution process.
111 */
112 struct GNUNET_SCHEDULER_Task * timeout_task;
113
114 /**
115 * The root of the received JSON or NULL
116 */
117 json_t *json_root;
118
119 /**
120 * The plugin result processor
121 */
122 GNUNET_REST_ResultProcessor proc;
123
124 /**
125 * The closure of the result processor
126 */
127 void *proc_cls;
128
129 /**
130 * The issuer attribute to verify
131 */
132 char *issuer_attr;
133
134 /**
135 * The subject attribute
136 */
137 char *subject_attr;
138
139 /**
140 * The public key of the issuer
141 */
142 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
143
144 /**
145 * The public key of the subject
146 */
147 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
148
149 /**
150 * HTTP response code
151 */
152 int response_code;
153
154 /**
155 * Timeout
156 */
157 struct GNUNET_TIME_Relative timeout;
158
159};
160
161
162/**
163 * Cleanup lookup handle.
164 *
165 * @param handle Handle to clean up
166 */
167static void
168cleanup_handle (struct RequestHandle *handle)
169{
170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
171 "Cleaning up\n");
172 if (NULL != handle->json_root)
173 json_decref (handle->json_root);
174
175 if (NULL != handle->issuer_attr)
176 GNUNET_free (handle->issuer_attr);
177 if (NULL != handle->subject_attr)
178 GNUNET_free (handle->subject_attr);
179 if (NULL != handle->verify_request)
180 GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
181 if (NULL != handle->credential)
182 GNUNET_CREDENTIAL_disconnect (handle->credential);
183 if (NULL != handle->id_op)
184 GNUNET_IDENTITY_cancel (handle->id_op);
185 if (NULL != handle->ego_lookup)
186 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
187 if (NULL != handle->identity)
188 GNUNET_IDENTITY_disconnect (handle->identity);
189 if (NULL != handle->timeout_task)
190 {
191 GNUNET_SCHEDULER_cancel (handle->timeout_task);
192 }
193 GNUNET_free (handle);
194}
195
196
197static void
198do_error (void *cls)
199{
200 struct RequestHandle *handle = cls;
201 struct MHD_Response *resp;
202
203 resp = GNUNET_REST_create_response (NULL);
204 handle->proc (handle->proc_cls, resp, handle->response_code);
205 cleanup_handle (handle);
206}
207
208/**
209 * Attribute delegation to JSON
210 *
211 * @param delegation_chain_entry the DSE
212 * @return JSON, NULL if failed
213 */
214static json_t*
215attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
216{
217 char *subject;
218 char *issuer;
219 json_t *attr_obj;
220
221 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
222 if (NULL == issuer)
223 {
224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 "Issuer in delegation malformed\n");
226 return NULL;
227 }
228 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
229 if (NULL == subject)
230 {
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 "Subject in credential malformed\n");
233 GNUNET_free (issuer);
234 return NULL;
235 }
236 attr_obj = json_object ();
237
238 json_object_set_new (attr_obj, "issuer", json_string (issuer));
239 json_object_set_new (attr_obj, "issuer_attribute",
240 json_string (delegation_chain_entry->issuer_attribute));
241
242 json_object_set_new (attr_obj, "subject", json_string (subject));
243 if (0 < delegation_chain_entry->subject_attribute_len)
244 {
245 json_object_set_new (attr_obj, "subject_attribute",
246 json_string (delegation_chain_entry->subject_attribute));
247 }
248 GNUNET_free (issuer);
249 GNUNET_free (subject);
250 return attr_obj;
251}
252
253/**
254 * JSONAPI resource to Credential
255 *
256 * @param res the JSONAPI resource
257 * @return the resulting credential, NULL if failed
258 */
259static struct GNUNET_CREDENTIAL_Credential*
260json_to_credential (json_t *res)
261{
262 struct GNUNET_CREDENTIAL_Credential *cred;
263 json_t *tmp;
264 const char *attribute;
265 const char *signature;
266 char *sig;
267
268 tmp = json_object_get (res, "attribute");
269 if (0 == json_is_string (tmp))
270 {
271 return NULL;
272 }
273 attribute = json_string_value (tmp);
274 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
275 + strlen (attribute));
276 cred->issuer_attribute = attribute;
277 cred->issuer_attribute_len = strlen (attribute);
278 tmp = json_object_get (res, "issuer");
279 if (0 == json_is_string (tmp))
280 {
281 GNUNET_free (cred);
282 return NULL;
283 }
284
285 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
286 strlen (json_string_value(tmp)),
287 &cred->issuer_key);
288 tmp = json_object_get (res, "subject");
289 if (0 == json_is_string (tmp))
290 {
291 GNUNET_free (cred);
292 return NULL;
293 }
294 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
295 strlen (json_string_value(tmp)),
296 &cred->subject_key);
297
298 tmp = json_object_get (res, "signature");
299 if (0 == json_is_string (tmp))
300 {
301 GNUNET_free (cred);
302 return NULL;
303 }
304 signature = json_string_value (tmp);
305 GNUNET_STRINGS_base64_decode (signature,
306 strlen (signature),
307 (char**)&sig);
308 GNUNET_memcpy (&cred->signature,
309 sig,
310 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
311 GNUNET_free (sig);
312
313 tmp = json_object_get (res, "expiration");
314 if (0 == json_is_integer (tmp))
315 {
316 GNUNET_free (cred);
317 return NULL;
318 }
319 cred->expiration.abs_value_us = json_integer_value (tmp);
320 return cred;
321}
322
323
324/**
325 * Credential to JSON
326 *
327 * @param cred the credential
328 * @return the resulting json, NULL if failed
329 */
330static json_t*
331credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
332{
333 char *issuer;
334 char *subject;
335 char *signature;
336 char attribute[cred->issuer_attribute_len + 1];
337 json_t *cred_obj;
338
339 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
340 if (NULL == issuer)
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
343 "Issuer in credential malformed\n");
344 return NULL;
345 }
346 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
347 if (NULL == subject)
348 {
349 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
350 "Subject in credential malformed\n");
351 GNUNET_free (issuer);
352 return NULL;
353 }
354 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
355 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
356 &signature);
357 GNUNET_memcpy (attribute,
358 cred->issuer_attribute,
359 cred->issuer_attribute_len);
360 attribute[cred->issuer_attribute_len] = '\0';
361 cred_obj = json_object ();
362 json_object_set_new (cred_obj, "issuer", json_string (issuer));
363 json_object_set_new (cred_obj, "subject", json_string (subject));
364 json_object_set_new (cred_obj, "attribute", json_string (attribute));
365 json_object_set_new (cred_obj, "signature", json_string (signature));
366 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
367 GNUNET_free (issuer);
368 GNUNET_free (subject);
369 GNUNET_free (signature);
370 return cred_obj;
371}
372
373static void
374handle_collect_response (void *cls,
375 unsigned int d_count,
376 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
377 unsigned int c_count,
378 struct GNUNET_CREDENTIAL_Credential *cred)
379{
380 struct RequestHandle *handle = cls;
381 struct MHD_Response *resp;
382 struct GNUNET_JSONAPI_Document *json_document;
383 struct GNUNET_JSONAPI_Resource *json_resource;
384 json_t *cred_obj;
385 json_t *cred_array;
386 char *result;
387 char *issuer;
388 char *id;
389 uint32_t i;
390
391 handle->verify_request = NULL;
392 if (NULL == cred) {
393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
394 "Verify failed.\n");
395 handle->response_code = MHD_HTTP_NOT_FOUND;
396 GNUNET_SCHEDULER_add_now (&do_error, handle);
397 return;
398 }
399 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
400 if (NULL == issuer)
401 {
402 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403 "Issuer in delegation malformed\n");
404 return;
405 }
406 GNUNET_asprintf (&id,
407 "%s.%s",
408 issuer,
409 handle->issuer_attr);
410 GNUNET_free (issuer);
411 json_document = GNUNET_JSONAPI_document_new ();
412 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
413 id);
414 GNUNET_free (id);
415 cred_array = json_array ();
416 for (i=0;i<c_count;i++)
417 {
418 cred_obj = credential_to_json (&cred[i]);
419 json_array_append_new (cred_array, cred_obj);
420 }
421 GNUNET_JSONAPI_resource_add_attr (json_resource,
422 GNUNET_REST_JSONAPI_CREDENTIAL,
423 cred_array);
424 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
425 GNUNET_JSONAPI_document_serialize (json_document, &result);
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
427 "Result %s\n",
428 result);
429 json_decref (cred_array);
430 GNUNET_JSONAPI_document_delete (json_document);
431 resp = GNUNET_REST_create_response (result);
432 GNUNET_free(result);
433 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
434 cleanup_handle (handle);
435}
436
437static void
438subject_ego_lookup (void *cls,
439 const struct GNUNET_IDENTITY_Ego *ego)
440{
441 struct RequestHandle *handle = cls;
442 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
443 handle->ego_lookup = NULL;
444
445 if (NULL == ego)
446 {
447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
448 "Subject not found\n");
449 GNUNET_SCHEDULER_add_now (&do_error, handle);
450 return;
451 }
452 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
453 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
454 &handle->issuer_key,
455 handle->issuer_attr,
456 sub_key,
457 &handle_collect_response,
458 handle);
459}
460
461
462
463static void
464handle_verify_response (void *cls,
465 unsigned int d_count,
466 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
467 unsigned int c_count,
468 struct GNUNET_CREDENTIAL_Credential *cred)
469{
470
471 struct RequestHandle *handle = cls;
472 struct MHD_Response *resp;
473 struct GNUNET_JSONAPI_Document *json_document;
474 struct GNUNET_JSONAPI_Resource *json_resource;
475 json_t *cred_obj;
476 json_t *attr_obj;
477 json_t *cred_array;
478 json_t *attr_array;
479 char *result;
480 char *issuer;
481 char *id;
482 uint32_t i;
483
484 handle->verify_request = NULL;
485 if (NULL == cred) {
486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
487 "Verify failed.\n");
488 handle->response_code = MHD_HTTP_NOT_FOUND;
489 GNUNET_SCHEDULER_add_now (&do_error, handle);
490 return;
491 }
492 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
493 if (NULL == issuer)
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
496 "Issuer in delegation malformed\n");
497 return;
498 }
499 GNUNET_asprintf (&id,
500 "%s.%s",
501 issuer,
502 handle->issuer_attr);
503 GNUNET_free (issuer);
504 json_document = GNUNET_JSONAPI_document_new ();
505 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
506 id);
507 GNUNET_free (id);
508 attr_array = json_array ();
509 for (i = 0; i < d_count; i++)
510 {
511 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
512 json_array_append_new (attr_array, attr_obj);
513 }
514 cred_array = json_array ();
515 for (i=0;i<c_count;i++)
516 {
517 cred_obj = credential_to_json (&cred[i]);
518 json_array_append_new (cred_array, cred_obj);
519 }
520 GNUNET_JSONAPI_resource_add_attr (json_resource,
521 GNUNET_REST_JSONAPI_CREDENTIAL,
522 cred_array);
523 GNUNET_JSONAPI_resource_add_attr (json_resource,
524 GNUNET_REST_JSONAPI_DELEGATIONS,
525 attr_array);
526 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
527 GNUNET_JSONAPI_document_serialize (json_document, &result);
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Result %s\n",
530 result);
531 json_decref (attr_array);
532 json_decref (cred_array);
533 GNUNET_JSONAPI_document_delete (json_document);
534 resp = GNUNET_REST_create_response (result);
535 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
536 GNUNET_free (result);
537 cleanup_handle (handle);
538}
539
540static void
541collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
542 const char* url,
543 void *cls)
544{
545 struct RequestHandle *handle = cls;
546 struct GNUNET_HashCode key;
547 char *tmp;
548 char *entity_attr;
549
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
551 "Connecting...\n");
552 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
553 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
554 &do_error, handle);
555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
556 "Connected\n");
557 if (NULL == handle->credential)
558 {
559 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560 "Connecting to CREDENTIAL failed\n");
561 GNUNET_SCHEDULER_add_now (&do_error, handle);
562 return;
563 }
564 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
565 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
566 &key);
567 if ( GNUNET_NO ==
568 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
569 &key) )
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 "Missing issuer attribute\n");
573 GNUNET_SCHEDULER_add_now (&do_error, handle);
574 return;
575 }
576 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
577 &key);
578 entity_attr = GNUNET_strdup (tmp);
579 tmp = strtok(entity_attr, ".");
580 if (NULL == tmp)
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
583 "Malformed issuer or attribute\n");
584 GNUNET_free (entity_attr);
585 GNUNET_SCHEDULER_add_now (&do_error, handle);
586 return;
587 }
588 if (GNUNET_OK !=
589 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
590 strlen (tmp),
591 &handle->issuer_key))
592 {
593 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
594 "Malformed issuer key\n");
595 GNUNET_free (entity_attr);
596 GNUNET_SCHEDULER_add_now (&do_error, handle);
597 return;
598 }
599 tmp = strtok (NULL, "."); //Issuer attribute
600 if (NULL == tmp)
601 {
602 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603 "Malformed attribute\n");
604 GNUNET_free (entity_attr);
605 GNUNET_SCHEDULER_add_now (&do_error, handle);
606 return;
607 }
608 handle->issuer_attr = GNUNET_strdup (tmp);
609 GNUNET_free (entity_attr);
610
611 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
612 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
613 &key);
614 if ( GNUNET_NO ==
615 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
616 &key) )
617 {
618 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619 "Missing subject\n");
620 GNUNET_SCHEDULER_add_now (&do_error, handle);
621 return;
622 }
623 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
624 &key);
625 if (NULL == tmp)
626 {
627 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
628 "Malformed subject\n");
629 GNUNET_SCHEDULER_add_now (&do_error, handle);
630 return;
631 }
632 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
633 tmp,
634 &subject_ego_lookup,
635 handle);
636}
637
638
639
640static void
641verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
642 const char* url,
643 void *cls)
644{
645 struct RequestHandle *handle = cls;
646 struct GNUNET_HashCode key;
647 struct GNUNET_JSONAPI_Document *json_obj;
648 struct GNUNET_JSONAPI_Resource *res;
649 struct GNUNET_CREDENTIAL_Credential *cred;
650 char *tmp;
651 char *entity_attr;
652 int i;
653 uint32_t credential_count;
654 uint32_t resource_count;
655 json_t *cred_json;
656 json_t *data_js;
657 json_error_t err;
658
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660 "Connecting...\n");
661 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
662 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
663 &do_error, handle);
664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
665 "Connected\n");
666 if (NULL == handle->credential)
667 {
668 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
669 "Connecting to CREDENTIAL failed\n");
670 GNUNET_SCHEDULER_add_now (&do_error, handle);
671 return;
672 }
673 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
674 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
675 &key);
676 if ( GNUNET_NO ==
677 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
678 &key) )
679 {
680 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
681 "Missing issuer attribute\n");
682 GNUNET_SCHEDULER_add_now (&do_error, handle);
683 return;
684 }
685 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
686 &key);
687 entity_attr = GNUNET_strdup (tmp);
688 tmp = strtok(entity_attr, ".");
689 if (NULL == tmp)
690 {
691 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
692 "Malformed issuer or attribute\n");
693 GNUNET_free (entity_attr);
694 GNUNET_SCHEDULER_add_now (&do_error, handle);
695 return;
696 }
697 if (GNUNET_OK !=
698 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
699 strlen (tmp),
700 &handle->issuer_key))
701 {
702 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
703 "Malformed issuer key\n");
704 GNUNET_free (entity_attr);
705 GNUNET_SCHEDULER_add_now (&do_error, handle);
706 return;
707 }
708 tmp = strtok (NULL, "."); //Issuer attribute
709 if (NULL == tmp)
710 {
711 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
712 "Malformed attribute\n");
713 GNUNET_free (entity_attr);
714 GNUNET_SCHEDULER_add_now (&do_error, handle);
715 return;
716 }
717 handle->issuer_attr = GNUNET_strdup (tmp);
718 GNUNET_free (entity_attr);
719
720 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
721 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
722 &key);
723 if ( GNUNET_NO ==
724 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
725 &key) )
726 {
727 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
728 "Missing subject key\n");
729 GNUNET_SCHEDULER_add_now (&do_error, handle);
730 return;
731 }
732 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
733 &key);
734 if (NULL == tmp)
735 {
736 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
737 "Malformed subject\n");
738 GNUNET_SCHEDULER_add_now (&do_error, handle);
739 return;
740 }
741 if (GNUNET_OK !=
742 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
743 strlen (tmp),
744 &handle->subject_key)) {
745 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
746 "Malformed subject key\n");
747 GNUNET_SCHEDULER_add_now (&do_error, handle);
748 return;
749 }
750
751 if (0 >= handle->rest_handle->data_size)
752 {
753 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
754 "Missing credentials\n");
755 GNUNET_SCHEDULER_add_now (&do_error, handle);
756 return;
757 }
758
759 struct GNUNET_JSON_Specification docspec[] = {
760 GNUNET_JSON_spec_jsonapi_document (&json_obj),
761 GNUNET_JSON_spec_end()
762 };
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,
770 JSON_DECODE_ANY,
771 &err);
772 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
773 NULL, NULL));
774 json_decref (data_js);
775 if (NULL == json_obj)
776 {
777 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
778 "Unable to parse JSONAPI Object from %s\n",
779 term_data);
780 GNUNET_SCHEDULER_add_now (&do_error, handle);
781 return;
782 }
783
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))
789 {
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",
794 term_data);
795 GNUNET_JSONAPI_document_delete (json_obj);
796 GNUNET_SCHEDULER_add_now (&do_error, handle);
797 return;
798 }
799 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
800 GNUNET_REST_JSONAPI_CREDENTIAL);
801
802 GNUNET_assert (json_is_array (cred_json));
803
804 credential_count = json_array_size(cred_json);
805
806 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
807 for (i=0;i<credential_count;i++)
808 {
809 cred = json_to_credential (json_array_get (cred_json, i));
810 if (NULL == cred)
811 {
812 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
813 "Unable to parse credential!\n");
814 continue;
815 }
816 GNUNET_memcpy (&credentials[i],
817 cred,
818 sizeof (struct GNUNET_CREDENTIAL_Credential));
819 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
820 GNUNET_free (cred);
821 }
822 GNUNET_JSONAPI_document_delete(json_obj);
823 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
824 &handle->issuer_key,
825 handle->issuer_attr,
826 &handle->subject_key,
827 credential_count,
828 credentials,
829 &handle_verify_response,
830 handle);
831 for (i=0;i<credential_count;i++)
832 GNUNET_free ((char*)credentials[i].issuer_attribute);
833
834}
835
836void
837send_cred_response (struct RequestHandle *handle,
838 struct GNUNET_CREDENTIAL_Credential *cred)
839{
840 struct MHD_Response *resp;
841 struct GNUNET_JSONAPI_Document *json_document;
842 struct GNUNET_JSONAPI_Resource *json_resource;
843 json_t *cred_obj;
844 char *result;
845 char *issuer;
846 char *subject;
847 char *signature;
848 char *id;
849
850 GNUNET_assert (NULL != cred);
851 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
852 if (NULL == issuer)
853 {
854 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
855 "Subject malformed\n");
856 GNUNET_free (issuer);
857 return;
858 }
859 GNUNET_asprintf (&id,
860 "%s.%s",
861 issuer,
862 (char*)&cred[1]);
863 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
864 if (NULL == subject)
865 {
866 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
867 "Subject malformed\n");
868 GNUNET_free (id);
869 GNUNET_free (issuer);
870 return;
871 }
872 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
873 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
874 &signature);
875 json_document = GNUNET_JSONAPI_document_new ();
876 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
877 id);
878 GNUNET_free (id);
879 cred_obj = json_object();
880 json_object_set_new (cred_obj, "issuer", json_string (issuer));
881 json_object_set_new (cred_obj, "subject", json_string (subject));
882 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
883 json_object_set_new (cred_obj, "signature", json_string (signature));
884 GNUNET_JSONAPI_resource_add_attr (json_resource,
885 GNUNET_REST_JSONAPI_CREDENTIAL,
886 cred_obj);
887 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
888 GNUNET_JSONAPI_document_serialize (json_document, &result);
889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
890 "Result %s\n",
891 result);
892 json_decref (cred_obj);
893 GNUNET_JSONAPI_document_delete (json_document);
894 resp = GNUNET_REST_create_response (result);
895 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
896 GNUNET_free (result);
897 GNUNET_free (signature);
898 GNUNET_free (issuer);
899 GNUNET_free (subject);
900 cleanup_handle (handle);
901}
902
903void
904get_cred_issuer_cb (void *cls,
905 struct GNUNET_IDENTITY_Ego *ego,
906 void **ctx,
907 const char *name)
908{
909 struct RequestHandle *handle = cls;
910 struct GNUNET_TIME_Absolute etime_abs;
911 struct GNUNET_TIME_Relative etime_rel;
912 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
913 struct GNUNET_HashCode key;
914 struct GNUNET_CREDENTIAL_Credential *cred;
915 char* expiration_str;
916 char* tmp;
917
918 handle->id_op = NULL;
919
920 if (NULL == name)
921 {
922 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
923 "Issuer not configured!\n");
924 GNUNET_SCHEDULER_add_now (&do_error, handle);
925 return;
926 }
927
928 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
929 "Connecting to credential service...\n");
930 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
932 "Connected\n");
933 if (NULL == handle->credential)
934 {
935 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
936 "Connecting to CREDENTIAL failed\n");
937 GNUNET_SCHEDULER_add_now (&do_error, handle);
938 return;
939 }
940 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
941 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
942 &key);
943 if ( GNUNET_NO ==
944 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
945 &key) )
946 {
947 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
948 "Missing expiration\n");
949 GNUNET_SCHEDULER_add_now (&do_error, handle);
950 return;
951 }
952 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
953 &key);
954 if ( NULL == expiration_str )
955 {
956 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
957 "Expiration malformed\n");
958 GNUNET_SCHEDULER_add_now (&do_error, handle);
959 return;
960 }
961
962 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
963 &etime_rel))
964 {
965 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
966 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
967 &etime_abs))
968 {
969 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
970 "Malformed expiration: %s\n", expiration_str);
971 GNUNET_SCHEDULER_add_now (&do_error, handle);
972 return;
973 }
974 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
975 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
976 &key);
977 if ( GNUNET_NO ==
978 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
979 &key) )
980 {
981 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
982 "Missing issuer attribute\n");
983 GNUNET_SCHEDULER_add_now (&do_error, handle);
984 return;
985 }
986 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
987 (handle->rest_handle->url_param_map,
988 &key));
989 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
990 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
991 &key);
992 if ( GNUNET_NO ==
993 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
994 &key) )
995 {
996 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
997 "Missing subject\n");
998 GNUNET_SCHEDULER_add_now (&do_error, handle);
999 return;
1000 }
1001 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1002 &key);
1003 if (NULL == tmp)
1004 {
1005 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1006 "Malformed subject\n");
1007 GNUNET_SCHEDULER_add_now (&do_error, handle);
1008 return;
1009 }
1010 if (GNUNET_OK !=
1011 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1012 strlen (tmp),
1013 &handle->subject_key)) {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1015 "Malformed subject key\n");
1016 GNUNET_SCHEDULER_add_now (&do_error, handle);
1017 return;
1018 }
1019 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1020 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1021 &handle->subject_key,
1022 handle->issuer_attr,
1023 &etime_abs);
1024 if (NULL == cred)
1025 {
1026 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1027 "Failed to create credential\n");
1028 GNUNET_SCHEDULER_add_now (&do_error, handle);
1029 return;
1030 }
1031 send_cred_response (handle, cred);
1032}
1033
1034
1035static void
1036issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1037 const char* url,
1038 void *cls)
1039{
1040 struct RequestHandle *handle = cls;
1041
1042 handle->identity = GNUNET_IDENTITY_connect (cfg,
1043 NULL,
1044 NULL);
1045 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1046 "credential-issuer",
1047 &get_cred_issuer_cb,
1048 handle);
1049 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1050 &do_error,
1051 handle);
1052}
1053
1054static void
1055options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1056 const char* url,
1057 void *cls)
1058{
1059 struct MHD_Response *resp;
1060 struct RequestHandle *handle = cls;
1061
1062 //For GNS, independent of path return all options
1063 resp = GNUNET_REST_create_response (NULL);
1064 MHD_add_response_header (resp,
1065 "Access-Control-Allow-Methods",
1066 MHD_HTTP_METHOD_GET);
1067 handle->proc (handle->proc_cls,
1068 resp,
1069 MHD_HTTP_OK);
1070 cleanup_handle (handle);
1071}
1072
1073
1074static void
1075rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1076 GNUNET_REST_ResultProcessor proc,
1077 void *proc_cls)
1078{
1079 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1080 struct GNUNET_REST_RequestHandlerError err;
1081
1082 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1083 handle->proc_cls = proc_cls;
1084 handle->proc = proc;
1085 handle->rest_handle = conndata_handle;
1086
1087 static const struct GNUNET_REST_RequestHandler handlers[] = {
1088 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1089 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1090 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1091 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1092 GNUNET_REST_HANDLER_END
1093 };
1094
1095 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1096 handlers,
1097 &err,
1098 handle))
1099 {
1100 handle->response_code = err.error_code;
1101 GNUNET_SCHEDULER_add_now (&do_error, handle);
1102 }
1103}
1104
1105
1106/**
1107 * Entry point for the plugin.
1108 *
1109 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1110 * @return NULL on error, otherwise the plugin context
1111 */
1112void *
1113libgnunet_plugin_rest_credential_init (void *cls)
1114{
1115 static struct Plugin plugin;
1116 cfg = cls;
1117 struct GNUNET_REST_Plugin *api;
1118
1119 if (NULL != plugin.cfg)
1120 return NULL; /* can only initialize once! */
1121 memset (&plugin, 0, sizeof (struct Plugin));
1122 plugin.cfg = cfg;
1123 api = GNUNET_new (struct GNUNET_REST_Plugin);
1124 api->cls = &plugin;
1125 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1126 api->process_request = &rest_credential_process_request;
1127 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1128 _("GNS REST API initialized\n"));
1129 return api;
1130}
1131
1132
1133/**
1134 * Exit point from the plugin.
1135 *
1136 * @param cls the plugin context (as returned by "init")
1137 * @return always NULL
1138 */
1139void *
1140libgnunet_plugin_rest_credential_done (void *cls)
1141{
1142 struct GNUNET_REST_Plugin *api = cls;
1143 struct Plugin *plugin = api->cls;
1144
1145 plugin->cfg = NULL;
1146 GNUNET_free (api);
1147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1148 "GNS REST plugin is finished\n");
1149 return NULL;
1150}
1151
1152/* end of plugin_rest_gns.c */