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