aboutsummaryrefslogtreecommitdiff
path: root/src/service/rest/reclaim_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/rest/reclaim_plugin.c')
-rw-r--r--src/service/rest/reclaim_plugin.c1532
1 files changed, 1532 insertions, 0 deletions
diff --git a/src/service/rest/reclaim_plugin.c b/src/service/rest/reclaim_plugin.c
new file mode 100644
index 000000000..adddab5c6
--- /dev/null
+++ b/src/service/rest/reclaim_plugin.c
@@ -0,0 +1,1532 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 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 * @author Philippe Buschmann
23 * @file reclaim/plugin_rest_reclaim.c
24 * @brief GNUnet reclaim REST plugin
25 *
26 */
27#include "platform.h"
28#include "microhttpd.h"
29#include <inttypes.h>
30#include <jansson.h>
31#include "gnunet_gns_service.h"
32#include "gnunet_gnsrecord_lib.h"
33#include "gnunet_identity_service.h"
34#include "gnunet_reclaim_lib.h"
35#include "gnunet_reclaim_service.h"
36#include "gnunet_rest_lib.h"
37#include "gnunet_rest_plugin.h"
38#include "gnunet_signatures.h"
39#include "json_reclaim.h"
40/**
41 * REST root namespace
42 */
43#define GNUNET_REST_API_NS_RECLAIM "/reclaim"
44
45/**
46 * Attribute namespace
47 */
48#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
49
50/**
51 * Credential namespace
52 */
53#define GNUNET_REST_API_NS_RECLAIM_CREDENTIAL "/reclaim/credential"
54
55/**
56 * Ticket namespace
57 */
58#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
59
60/**
61 * Revoke namespace
62 */
63#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/reclaim/revoke"
64
65/**
66 * Revoke namespace
67 */
68#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/reclaim/consume"
69
70/**
71 * State while collecting all egos
72 */
73#define ID_REST_STATE_INIT 0
74
75/**
76 * Done collecting egos
77 */
78#define ID_REST_STATE_POST_INIT 1
79
80/**
81 * The configuration handle
82 */
83const struct GNUNET_CONFIGURATION_Handle *rcfg;
84
85/**
86 * HTTP methods allows for this plugin
87 */
88static char *allow_methods;
89
90/**
91 * Ego list
92 */
93static struct EgoEntry *ego_head;
94
95/**
96 * Ego list
97 */
98static struct EgoEntry *ego_tail;
99
100/**
101 * The processing state
102 */
103static int state;
104
105/**
106 * Handle to Identity service.
107 */
108static struct GNUNET_IDENTITY_Handle *identity_handle;
109
110/**
111 * Identity Provider
112 */
113static struct GNUNET_RECLAIM_Handle *idp;
114
115/**
116 * @brief struct returned by the initialization function of the plugin
117 */
118struct Plugin
119{
120 const struct GNUNET_CONFIGURATION_Handle *cfg;
121};
122
123/**
124 * The ego list
125 */
126struct EgoEntry
127{
128 /**
129 * DLL
130 */
131 struct EgoEntry *next;
132
133 /**
134 * DLL
135 */
136 struct EgoEntry *prev;
137
138 /**
139 * Ego Identifier
140 */
141 char *identifier;
142
143 /**
144 * Public key string
145 */
146 char *keystring;
147
148 /**
149 * The Ego
150 */
151 struct GNUNET_IDENTITY_Ego *ego;
152};
153
154
155struct RequestHandle
156{
157 /**
158 * DLL
159 */
160 struct RequestHandle *next;
161
162 /**
163 * DLL
164 */
165 struct RequestHandle *prev;
166
167 /**
168 * Selected ego
169 */
170 struct EgoEntry *ego_entry;
171
172 /**
173 * Pointer to ego private key
174 */
175 struct GNUNET_CRYPTO_PrivateKey priv_key;
176
177 /**
178 * Rest connection
179 */
180 struct GNUNET_REST_RequestHandle *rest_handle;
181
182 /**
183 * Attribute claim list
184 */
185 struct GNUNET_RECLAIM_AttributeList *attr_list;
186
187 /**
188 * IDENTITY Operation
189 */
190 struct GNUNET_IDENTITY_Operation *op;
191
192 /**
193 * Idp Operation
194 */
195 struct GNUNET_RECLAIM_Operation *idp_op;
196
197 /**
198 * Attribute iterator
199 */
200 struct GNUNET_RECLAIM_AttributeIterator *attr_it;
201
202 /**
203 * Attribute iterator
204 */
205 struct GNUNET_RECLAIM_CredentialIterator *cred_it;
206
207 /**
208 * Ticket iterator
209 */
210 struct GNUNET_RECLAIM_TicketIterator *ticket_it;
211
212 /**
213 * A ticket
214 */
215 struct GNUNET_RECLAIM_Ticket ticket;
216
217 /**
218 * Desired timeout for the lookup (default is no timeout).
219 */
220 struct GNUNET_TIME_Relative timeout;
221
222 /**
223 * ID of a task associated with the resolution process.
224 */
225 struct GNUNET_SCHEDULER_Task *timeout_task;
226
227 /**
228 * The plugin result processor
229 */
230 GNUNET_REST_ResultProcessor proc;
231
232 /**
233 * The closure of the result processor
234 */
235 void *proc_cls;
236
237 /**
238 * The url
239 */
240 char *url;
241
242 /**
243 * Error response message
244 */
245 char *emsg;
246
247 /**
248 * Response code
249 */
250 int response_code;
251
252 /**
253 * Response object
254 */
255 json_t *resp_object;
256};
257
258/**
259 * DLL
260 */
261static struct RequestHandle *requests_head;
262
263/**
264 * DLL
265 */
266static struct RequestHandle *requests_tail;
267
268
269/**
270 * Cleanup lookup handle
271 * @param handle Handle to clean up
272 */
273static void
274cleanup_handle (void *cls)
275{
276 struct RequestHandle *handle = cls;
277
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
279 if (NULL != handle->resp_object)
280 json_decref (handle->resp_object);
281 if (NULL != handle->timeout_task)
282 GNUNET_SCHEDULER_cancel (handle->timeout_task);
283 if (NULL != handle->attr_it)
284 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
285 if (NULL != handle->cred_it)
286 GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
287 if (NULL != handle->ticket_it)
288 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
289 if (NULL != handle->url)
290 GNUNET_free (handle->url);
291 if (NULL != handle->emsg)
292 GNUNET_free (handle->emsg);
293 if (NULL != handle->attr_list)
294 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list);
295 GNUNET_CONTAINER_DLL_remove (requests_head,
296 requests_tail,
297 handle);
298 GNUNET_free (handle);
299}
300
301
302/**
303 * Task run on error, sends error message. Cleans up everything.
304 *
305 * @param cls the `struct RequestHandle`
306 */
307static void
308do_error (void *cls)
309{
310 struct RequestHandle *handle = cls;
311 struct MHD_Response *resp;
312 char *json_error;
313
314 GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", handle->emsg);
315 if (0 == handle->response_code)
316 {
317 handle->response_code = MHD_HTTP_BAD_REQUEST;
318 }
319 resp = GNUNET_REST_create_response (json_error);
320 GNUNET_assert (MHD_NO != MHD_add_response_header (resp, "Content-Type",
321 "application/json"));
322 handle->proc (handle->proc_cls, resp, handle->response_code);
323 cleanup_handle (handle);
324 GNUNET_free (json_error);
325}
326
327
328/**
329 * Task run on timeout, sends error message. Cleans up everything.
330 *
331 * @param cls the `struct RequestHandle`
332 */
333static void
334do_timeout (void *cls)
335{
336 struct RequestHandle *handle = cls;
337
338 handle->timeout_task = NULL;
339 do_error (handle);
340}
341
342
343static void
344collect_error_cb (void *cls)
345{
346 GNUNET_SCHEDULER_add_now (&do_error, cls);
347}
348
349
350static void
351finished_cont (void *cls, int32_t success, const char *emsg)
352{
353 struct RequestHandle *handle = cls;
354 struct MHD_Response *resp;
355
356 handle->idp_op = NULL;
357 if (GNUNET_OK != success)
358 {
359 GNUNET_SCHEDULER_add_now (&do_error, handle);
360 return;
361 }
362 resp = GNUNET_REST_create_response (emsg);
363 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
364 "Content-Type",
365 "application/json"));
366 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
367 "Access-Control-Allow-Methods",
368 allow_methods));
369 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
370 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
371}
372
373
374static void
375delete_finished_cb (void *cls, int32_t success, const char *emsg)
376{
377 struct RequestHandle *handle = cls;
378 struct MHD_Response *resp;
379
380 if (GNUNET_OK != success)
381 {
382 GNUNET_SCHEDULER_add_now (&do_error, handle);
383 return;
384 }
385 resp = GNUNET_REST_create_response (emsg);
386 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
387 "Access-Control-Allow-Methods",
388 allow_methods));
389 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
390 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
391}
392
393
394/**
395 * Return attributes for identity
396 *
397 * @param cls the request handle
398 */
399static void
400return_response (void *cls)
401{
402 char *result_str;
403 struct RequestHandle *handle = cls;
404 struct MHD_Response *resp;
405
406 result_str = json_dumps (handle->resp_object, 0);
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
408 resp = GNUNET_REST_create_response (result_str);
409 GNUNET_assert (MHD_NO !=
410 MHD_add_response_header (resp,
411 "Access-Control-Allow-Methods",
412 allow_methods));
413 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
414 GNUNET_free (result_str);
415 cleanup_handle (handle);
416}
417
418
419static void
420collect_finished_cb (void *cls)
421{
422 struct RequestHandle *handle = cls;
423
424 // Done
425 handle->attr_it = NULL;
426 handle->cred_it = NULL;
427 handle->ticket_it = NULL;
428 GNUNET_SCHEDULER_add_now (&return_response, handle);
429}
430
431
432/**
433 * Collect all attributes for an ego
434 *
435 */
436static void
437ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket,
438 const char *rp_uri)
439{
440 json_t *json_resource;
441 struct RequestHandle *handle = cls;
442
443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
444 json_resource = json_object ();
445 json_array_append (handle->resp_object, json_resource);
446
447 json_object_set_new (json_resource, "gns_name", json_string (ticket->gns_name)
448 );
449 json_object_set_new (json_resource, "rp_uri", json_string (rp_uri));
450 GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
451}
452
453
454static void
455add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
456 const char *url,
457 void *cls)
458{
459 struct RequestHandle *handle = cls;
460 const struct GNUNET_CRYPTO_PrivateKey *identity_priv;
461 const char *identity;
462 struct EgoEntry *ego_entry;
463 struct GNUNET_RECLAIM_Credential *attribute;
464 struct GNUNET_TIME_Relative exp;
465 char term_data[handle->rest_handle->data_size + 1];
466 json_t *data_json;
467 json_error_t err;
468 struct GNUNET_JSON_Specification attrspec[] =
469 { GNUNET_RECLAIM_JSON_spec_credential (&attribute),
470 GNUNET_JSON_spec_end () };
471
472 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
473 "Adding an credential for %s.\n",
474 handle->url);
475 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
476 handle->url))
477 {
478 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
479 GNUNET_SCHEDULER_add_now (&do_error, handle);
480 return;
481 }
482 identity = handle->url + strlen (
483 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
484
485 for (ego_entry = ego_head; NULL != ego_entry;
486 ego_entry = ego_entry->next)
487 if (0 == strcmp (identity, ego_entry->identifier))
488 break;
489
490 if (NULL == ego_entry)
491 {
492 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
493 return;
494 }
495 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
496
497 if (0 >= handle->rest_handle->data_size)
498 {
499 GNUNET_SCHEDULER_add_now (&do_error, handle);
500 return;
501 }
502
503 term_data[handle->rest_handle->data_size] = '\0';
504 GNUNET_memcpy (term_data,
505 handle->rest_handle->data,
506 handle->rest_handle->data_size);
507 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
508 if (GNUNET_OK != GNUNET_JSON_parse (data_json, attrspec, NULL, NULL))
509 {
510 json_decref (data_json);
511 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
512 "Unable to parse JSON from %s\n",
513 term_data);
514 GNUNET_SCHEDULER_add_now (&do_error, handle);
515 return;
516 }
517 json_decref (data_json);
518 if (NULL == attribute)
519 {
520 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
521 "Unable to parse credential from %s\n",
522 term_data);
523 GNUNET_SCHEDULER_add_now (&do_error, handle);
524 return;
525 }
526 /**
527 * New ID for attribute
528 */
529 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
530 GNUNET_RECLAIM_id_generate (&attribute->id);
531 exp = GNUNET_TIME_UNIT_HOURS;
532 handle->idp_op = GNUNET_RECLAIM_credential_store (idp,
533 identity_priv,
534 attribute,
535 &exp,
536 &finished_cont,
537 handle);
538 GNUNET_JSON_parse_free (attrspec);
539}
540
541
542/**
543 * Collect all credentials for an ego
544 *
545 */
546static void
547cred_collect (void *cls,
548 const struct GNUNET_CRYPTO_PublicKey *identity,
549 const struct GNUNET_RECLAIM_Credential *cred)
550{
551 struct RequestHandle *handle = cls;
552 struct GNUNET_RECLAIM_AttributeList *attrs;
553 struct GNUNET_RECLAIM_AttributeListEntry *ale;
554 struct GNUNET_TIME_Absolute exp;
555 json_t *attr_obj;
556 json_t *cred_obj;
557 const char *type;
558 char *tmp_value;
559 char *id_str;
560 char *issuer;
561
562
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential: %s\n",
564 cred->name);
565 attrs = GNUNET_RECLAIM_credential_get_attributes (cred);
566 issuer = GNUNET_RECLAIM_credential_get_issuer (cred);
567 tmp_value = GNUNET_RECLAIM_credential_value_to_string (cred->type,
568 cred->data,
569 cred->data_size);
570 cred_obj = json_object ();
571 json_object_set_new (cred_obj, "value", json_string (tmp_value));
572 json_object_set_new (cred_obj, "name", json_string (cred->name));
573 type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
574 json_object_set_new (cred_obj, "type", json_string (type));
575 if (NULL != issuer)
576 {
577 json_object_set_new (cred_obj, "issuer", json_string (issuer));
578 GNUNET_free (issuer);
579 }
580 if (GNUNET_OK == GNUNET_RECLAIM_credential_get_expiration (cred,
581 &exp))
582 {
583 json_object_set_new (cred_obj, "expiration", json_integer (
584 exp.abs_value_us));
585 }
586 id_str = GNUNET_STRINGS_data_to_string_alloc (&cred->id,
587 sizeof(cred->id));
588 json_object_set_new (cred_obj, "id", json_string (id_str));
589 GNUNET_free (tmp_value);
590 GNUNET_free (id_str);
591 if (NULL != attrs)
592 {
593 json_t *attr_arr = json_array ();
594 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
595 {
596 tmp_value =
597 GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
598 ale->attribute->data,
599 ale->attribute->data_size);
600 attr_obj = json_object ();
601 json_object_set_new (attr_obj, "value", json_string (tmp_value));
602 json_object_set_new (attr_obj, "name", json_string (
603 ale->attribute->name));
604
605 json_object_set_new (attr_obj, "flag", json_string ("1")); // FIXME
606 type = GNUNET_RECLAIM_attribute_number_to_typename (ale->attribute->type);
607 json_object_set_new (attr_obj, "type", json_string (type));
608 json_object_set_new (attr_obj, "id", json_string (""));
609 json_object_set_new (attr_obj, "credential", json_string (""));
610 json_array_append_new (attr_arr, attr_obj);
611 GNUNET_free (tmp_value);
612 }
613 json_object_set_new (cred_obj, "attributes", attr_arr);
614 }
615 json_array_append_new (handle->resp_object, cred_obj);
616 if (NULL != attrs)
617 GNUNET_RECLAIM_attribute_list_destroy (attrs);
618 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
619}
620
621
622/**
623 * Lists credential for identity request
624 *
625 * @param con_handle the connection handle
626 * @param url the url
627 * @param cls the RequestHandle
628 */
629static void
630list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
631 const char *url,
632 void *cls)
633{
634 struct RequestHandle *handle = cls;
635 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
636 struct EgoEntry *ego_entry;
637 char *identity;
638
639 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
640 "Getting credentials for %s.\n",
641 handle->url);
642 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
643 handle->url))
644 {
645 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
646 GNUNET_SCHEDULER_add_now (&do_error, handle);
647 return;
648 }
649 identity = handle->url + strlen (
650 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
651
652 for (ego_entry = ego_head; NULL != ego_entry;
653 ego_entry = ego_entry->next)
654 if (0 == strcmp (identity, ego_entry->identifier))
655 break;
656 handle->resp_object = json_array ();
657
658
659 if (NULL == ego_entry)
660 {
661 // Done
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
663 GNUNET_SCHEDULER_add_now (&return_response, handle);
664 return;
665 }
666 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
667 handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
668 priv_key,
669 &collect_error_cb,
670 handle,
671 &cred_collect,
672 handle,
673 &
674 collect_finished_cb,
675 handle);
676}
677
678
679/**
680 * Deletes credential from an identity
681 *
682 * @param con_handle the connection handle
683 * @param url the url
684 * @param cls the RequestHandle
685 */
686static void
687delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
688 const char *url,
689 void *cls)
690{
691 struct RequestHandle *handle = cls;
692 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
693 struct GNUNET_RECLAIM_Credential attr;
694 struct EgoEntry *ego_entry;
695 char *identity_id_str;
696 char *identity;
697 char *id;
698
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting credential.\n");
700 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
701 handle->url))
702 {
703 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
704 GNUNET_SCHEDULER_add_now (&do_error, handle);
705 return;
706 }
707 identity_id_str =
708 strdup (handle->url + strlen (
709 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1);
710 identity = strtok (identity_id_str, "/");
711 id = strtok (NULL, "/");
712 if ((NULL == identity) || (NULL == id))
713 {
714 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
715 GNUNET_free (identity_id_str);
716 GNUNET_SCHEDULER_add_now (&do_error, handle);
717 return;
718 }
719
720 for (ego_entry = ego_head; NULL != ego_entry;
721 ego_entry = ego_entry->next)
722 if (0 == strcmp (identity, ego_entry->identifier))
723 break;
724 handle->resp_object = json_array ();
725 if (NULL == ego_entry)
726 {
727 // Done
728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
729 GNUNET_free (identity_id_str);
730 GNUNET_SCHEDULER_add_now (&return_response, handle);
731 return;
732 }
733 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
734 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Credential));
735 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
736 attr.name = "";
737 handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
738 priv_key,
739 &attr,
740 &delete_finished_cb,
741 handle);
742 GNUNET_free (identity_id_str);
743}
744
745
746/**
747 * List tickets for identity request
748 *
749 * @param con_handle the connection handle
750 * @param url the url
751 * @param cls the RequestHandle
752 */
753static void
754list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
755 const char *url,
756 void *cls)
757{
758 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
759 struct RequestHandle *handle = cls;
760 struct EgoEntry *ego_entry;
761 char *identity;
762
763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
764 "Getting tickets for %s.\n",
765 handle->url);
766 if (strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= strlen (handle->url))
767 {
768 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
769 GNUNET_SCHEDULER_add_now (&do_error, handle);
770 return;
771 }
772 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
773
774 for (ego_entry = ego_head; NULL != ego_entry;
775 ego_entry = ego_entry->next)
776 if (0 == strcmp (identity, ego_entry->identifier))
777 break;
778 handle->resp_object = json_array ();
779
780 if (NULL == ego_entry)
781 {
782 // Done
783 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
784 GNUNET_SCHEDULER_add_now (&return_response, handle);
785 return;
786 }
787 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
788 handle->ticket_it =
789 GNUNET_RECLAIM_ticket_iteration_start (idp,
790 priv_key,
791 &collect_error_cb,
792 handle,
793 &ticket_collect,
794 handle,
795 &collect_finished_cb,
796 handle);
797}
798
799
800static void
801add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
802 const char *url,
803 void *cls)
804{
805 const struct GNUNET_CRYPTO_PrivateKey *identity_priv;
806 const char *identity;
807 struct RequestHandle *handle = cls;
808 struct EgoEntry *ego_entry;
809 struct GNUNET_RECLAIM_Attribute *attribute;
810 struct GNUNET_TIME_Relative exp;
811 char term_data[handle->rest_handle->data_size + 1];
812 json_t *data_json;
813 json_error_t err;
814 struct GNUNET_JSON_Specification attrspec[] =
815 { GNUNET_RECLAIM_JSON_spec_attribute (&attribute), GNUNET_JSON_spec_end () };
816
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
818 "Adding an attribute for %s.\n",
819 handle->url);
820 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
821 {
822 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
823 GNUNET_SCHEDULER_add_now (&do_error, handle);
824 return;
825 }
826 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
827
828 for (ego_entry = ego_head; NULL != ego_entry;
829 ego_entry = ego_entry->next)
830 if (0 == strcmp (identity, ego_entry->identifier))
831 break;
832
833 if (NULL == ego_entry)
834 {
835 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
836 return;
837 }
838 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
839
840 if (0 >= handle->rest_handle->data_size)
841 {
842 GNUNET_SCHEDULER_add_now (&do_error, handle);
843 return;
844 }
845
846 term_data[handle->rest_handle->data_size] = '\0';
847 GNUNET_memcpy (term_data,
848 handle->rest_handle->data,
849 handle->rest_handle->data_size);
850 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
851 GNUNET_assert (GNUNET_OK ==
852 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
853 json_decref (data_json);
854 if (NULL == attribute)
855 {
856 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
857 "Unable to parse attribute from %s\n",
858 term_data);
859 GNUNET_SCHEDULER_add_now (&do_error, handle);
860 return;
861 }
862 /**
863 * New ID for attribute
864 */
865 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
866 GNUNET_RECLAIM_id_generate (&attribute->id);
867 exp = GNUNET_TIME_UNIT_HOURS;
868 handle->idp_op = GNUNET_RECLAIM_attribute_store (idp,
869 identity_priv,
870 attribute,
871 &exp,
872 &finished_cont,
873 handle);
874 GNUNET_JSON_parse_free (attrspec);
875}
876
877
878/**
879 * Parse a JWT and return the respective claim value as Attribute
880 *
881 * @param cred the jwt credential
882 * @param claim the name of the claim in the JWT
883 *
884 * @return a GNUNET_RECLAIM_Attribute, containing the new value
885 */
886struct GNUNET_RECLAIM_Attribute *
887parse_jwt (const struct GNUNET_RECLAIM_Credential *cred,
888 const char *claim)
889{
890 char *jwt_string;
891 struct GNUNET_RECLAIM_Attribute *attr;
892 char delim[] = ".";
893 const char *type_str = NULL;
894 const char *val_str = NULL;
895 char *data;
896 size_t data_size;
897 uint32_t type;
898 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
899 char *decoded_jwt;
900 json_t *json_val;
901 json_error_t *json_err = NULL;
902
903 jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type,
904 cred->data,
905 cred->data_size);
906 char *jwt_body = strtok (jwt_string, delim);
907 jwt_body = strtok (NULL, delim);
908 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
909 (void **) &decoded_jwt);
910 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
911 const char *key;
912 json_t *value;
913 json_object_foreach (json_val, key, value) {
914 if (0 == strcasecmp (key,claim))
915 {
916 val_str = json_dumps (value, JSON_ENCODE_ANY);
917 }
918 }
919 type_str = "String";
920 type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
921 if (GNUNET_SYSERR == GNUNET_RECLAIM_attribute_string_to_value (type,val_str,
922 (void **) &data
923 ,
924 &data_size))
925 {
926 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
927 "Attribute value from JWT Parser invalid!\n");
928 GNUNET_RECLAIM_attribute_string_to_value (type,
929 "Error: Referenced Claim Name not Found",
930 (void **) &data,
931 &data_size);
932 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
933 type, data, data_size);
934 attr->id = cred->id;
935 attr->flag = 1;
936 }
937 else
938 {
939 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
940 type, data, data_size);
941 attr->id = cred->id;
942 attr->flag = 1;
943 }
944 return attr;
945}
946
947
948/**
949 * Collect all attributes for an ego
950 *
951 */
952static void
953attr_collect (void *cls,
954 const struct GNUNET_CRYPTO_PublicKey *identity,
955 const struct GNUNET_RECLAIM_Attribute *attr)
956{
957 struct RequestHandle *handle = cls;
958 json_t *attr_obj;
959 const char *type;
960 char *id_str;
961
962 char *tmp_value;
963 tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
964 attr->data,
965 attr->data_size);
966 attr_obj = json_object ();
967 json_object_set_new (attr_obj, "value", json_string (tmp_value));
968 json_object_set_new (attr_obj, "name", json_string (attr->name));
969
970 if (GNUNET_RECLAIM_id_is_zero (&attr->credential))
971 json_object_set_new (attr_obj, "flag", json_string ("0"));
972 else
973 json_object_set_new (attr_obj, "flag", json_string ("1"));
974 type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
975 json_object_set_new (attr_obj, "type", json_string (type));
976 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
977 sizeof(attr->id));
978 json_object_set_new (attr_obj, "id", json_string (id_str));
979 GNUNET_free (id_str);
980 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
981 sizeof(attr->credential));
982 json_object_set_new (attr_obj, "credential", json_string (id_str));
983 GNUNET_free (id_str);
984 json_array_append (handle->resp_object, attr_obj);
985 json_decref (attr_obj);
986 GNUNET_free (tmp_value);
987 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
988}
989
990
991/**
992 * List attributes for identity request
993 *
994 * @param con_handle the connection handle
995 * @param url the url
996 * @param cls the RequestHandle
997 */
998static void
999list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1000 const char *url,
1001 void *cls)
1002{
1003 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1004 struct RequestHandle *handle = cls;
1005 struct EgoEntry *ego_entry;
1006 char *identity;
1007
1008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1009 "Getting attributes for %s.\n",
1010 handle->url);
1011 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1012 {
1013 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1014 GNUNET_SCHEDULER_add_now (&do_error, handle);
1015 return;
1016 }
1017 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
1018
1019 for (ego_entry = ego_head; NULL != ego_entry;
1020 ego_entry = ego_entry->next)
1021 if (0 == strcmp (identity, ego_entry->identifier))
1022 break;
1023 handle->resp_object = json_array ();
1024
1025
1026 if (NULL == ego_entry)
1027 {
1028 // Done
1029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1030 GNUNET_SCHEDULER_add_now (&return_response, handle);
1031 return;
1032 }
1033 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1034 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (idp,
1035 priv_key,
1036 &collect_error_cb,
1037 handle,
1038 &attr_collect,
1039 handle,
1040 &collect_finished_cb,
1041 handle);
1042}
1043
1044
1045/**
1046 * List attributes for identity request
1047 *
1048 * @param con_handle the connection handle
1049 * @param url the url
1050 * @param cls the RequestHandle
1051 */
1052static void
1053delete_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1054 const char *url,
1055 void *cls)
1056{
1057 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1058 struct RequestHandle *handle = cls;
1059 struct GNUNET_RECLAIM_Attribute attr;
1060 struct EgoEntry *ego_entry;
1061 char *identity_id_str;
1062 char *identity;
1063 char *id;
1064
1065 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attributes.\n");
1066 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1067 {
1068 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1069 GNUNET_SCHEDULER_add_now (&do_error, handle);
1070 return;
1071 }
1072 identity_id_str =
1073 strdup (handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1);
1074 identity = strtok (identity_id_str, "/");
1075 id = strtok (NULL, "/");
1076 if ((NULL == identity) || (NULL == id))
1077 {
1078 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
1079 GNUNET_free (identity_id_str);
1080 GNUNET_SCHEDULER_add_now (&do_error, handle);
1081 return;
1082 }
1083
1084 for (ego_entry = ego_head; NULL != ego_entry;
1085 ego_entry = ego_entry->next)
1086 if (0 == strcmp (identity, ego_entry->identifier))
1087 break;
1088 handle->resp_object = json_array ();
1089 if (NULL == ego_entry)
1090 {
1091 // Done
1092 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1093 GNUNET_free (identity_id_str);
1094 GNUNET_SCHEDULER_add_now (&return_response, handle);
1095 return;
1096 }
1097 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1098 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Attribute));
1099 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
1100 attr.name = "";
1101 handle->idp_op = GNUNET_RECLAIM_attribute_delete (idp,
1102 priv_key,
1103 &attr,
1104 &delete_finished_cb,
1105 handle);
1106 GNUNET_free (identity_id_str);
1107}
1108
1109
1110static void
1111revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1112 const char *url,
1113 void *cls)
1114{
1115 const struct GNUNET_CRYPTO_PrivateKey *identity_priv;
1116 struct RequestHandle *handle = cls;
1117 struct EgoEntry *ego_entry;
1118 struct GNUNET_RECLAIM_Ticket *ticket = NULL;
1119 struct GNUNET_CRYPTO_PublicKey iss;
1120 struct GNUNET_CRYPTO_PublicKey tmp_pk;
1121 char term_data[handle->rest_handle->data_size + 1];
1122 json_t *data_json;
1123 json_error_t err;
1124 struct GNUNET_JSON_Specification tktspec[] =
1125 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1126
1127 if (0 >= handle->rest_handle->data_size)
1128 {
1129 GNUNET_SCHEDULER_add_now (&do_error, handle);
1130 return;
1131 }
1132
1133 term_data[handle->rest_handle->data_size] = '\0';
1134 GNUNET_memcpy (term_data,
1135 handle->rest_handle->data,
1136 handle->rest_handle->data_size);
1137 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1138 if ((NULL == data_json) ||
1139 (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL)))
1140 {
1141 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1142 GNUNET_SCHEDULER_add_now (&do_error, handle);
1143 GNUNET_JSON_parse_free (tktspec);
1144 if (NULL != data_json)
1145 json_decref (data_json);
1146 return;
1147 }
1148 json_decref (data_json);
1149 if (NULL == ticket)
1150 {
1151 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1152 "Unable to parse ticket from %s\n",
1153 term_data);
1154 GNUNET_SCHEDULER_add_now (&do_error, handle);
1155 return;
1156 }
1157
1158 GNUNET_assert (GNUNET_OK == GNUNET_GNS_parse_ztld (ticket->gns_name, &iss));
1159
1160 for (ego_entry = ego_head; NULL != ego_entry;
1161 ego_entry = ego_entry->next)
1162 {
1163 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1164 if (0 == memcmp (&iss,
1165 &tmp_pk,
1166 sizeof(struct GNUNET_CRYPTO_PublicKey)))
1167 break;
1168 }
1169 if (NULL == ego_entry)
1170 {
1171 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1172 GNUNET_JSON_parse_free (tktspec);
1173 return;
1174 }
1175 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1176
1177 handle->idp_op = GNUNET_RECLAIM_ticket_revoke (idp,
1178 identity_priv,
1179 ticket,
1180 &finished_cont,
1181 handle);
1182 GNUNET_JSON_parse_free (tktspec);
1183}
1184
1185
1186static void
1187consume_cont (void *cls,
1188 const struct GNUNET_CRYPTO_PublicKey *identity,
1189 const struct GNUNET_RECLAIM_Attribute *attr,
1190 const struct GNUNET_RECLAIM_Presentation *presentation)
1191{
1192 struct RequestHandle *handle = cls;
1193 char *val_str;
1194 json_t *value;
1195
1196 if (NULL == identity)
1197 {
1198 GNUNET_SCHEDULER_add_now (&return_response, handle);
1199 return;
1200 }
1201
1202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
1203 val_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
1204 attr->data,
1205 attr->data_size);
1206 if (NULL == val_str)
1207 {
1208 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1209 "Failed to parse value for: %s\n",
1210 attr->name);
1211 return;
1212 }
1213 value = json_string (val_str);
1214 json_object_set_new (handle->resp_object, attr->name, value);
1215 json_decref (value);
1216 GNUNET_free (val_str);
1217}
1218
1219
1220static void
1221consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1222 const char *url,
1223 void *cls)
1224{
1225 struct RequestHandle *handle = cls;
1226 struct GNUNET_RECLAIM_Ticket *ticket;
1227 char term_data[handle->rest_handle->data_size + 1];
1228 json_t *data_json;
1229 json_error_t err;
1230 struct GNUNET_JSON_Specification tktspec[] =
1231 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1232
1233 if (0 >= handle->rest_handle->data_size)
1234 {
1235 GNUNET_SCHEDULER_add_now (&do_error, handle);
1236 return;
1237 }
1238
1239 term_data[handle->rest_handle->data_size] = '\0';
1240 GNUNET_memcpy (term_data,
1241 handle->rest_handle->data,
1242 handle->rest_handle->data_size);
1243 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1244 if (NULL == data_json)
1245 {
1246 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1247 "Unable to parse JSON Object from %s\n",
1248 term_data);
1249 GNUNET_SCHEDULER_add_now (&do_error, handle);
1250 return;
1251 }
1252 if (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL))
1253 {
1254 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1255 GNUNET_SCHEDULER_add_now (&do_error, handle);
1256 GNUNET_JSON_parse_free (tktspec);
1257 json_decref (data_json);
1258 return;
1259 }
1260 handle->resp_object = json_object ();
1261 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
1262 ticket,
1263 &consume_cont,
1264 handle);
1265 GNUNET_JSON_parse_free (tktspec);
1266}
1267
1268
1269/**
1270 * Respond to OPTIONS request
1271 *
1272 * @param con_handle the connection handle
1273 * @param url the url
1274 * @param cls the RequestHandle
1275 */
1276static void
1277options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1278 const char *url,
1279 void *cls)
1280{
1281 struct MHD_Response *resp;
1282 struct RequestHandle *handle = cls;
1283
1284 // For now, independent of path return all options
1285 resp = GNUNET_REST_create_response (NULL);
1286 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1287 "Access-Control-Allow-Methods",
1288 allow_methods));
1289 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1290 cleanup_handle (handle);
1291 return;
1292}
1293
1294
1295/**
1296 * If listing is enabled, prints information about the egos.
1297 *
1298 * This function is initially called for all egos and then again
1299 * whenever a ego's identifier changes or if it is deleted. At the
1300 * end of the initial pass over all egos, the function is once called
1301 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
1302 * be invoked in the future or that there was an error.
1303 *
1304 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', this
1305 * function is only called ONCE, and 'NULL' being passed in 'ego' does
1306 * indicate an error (for example because name is taken or no default value is
1307 * known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the
1308 * value WILL be passed to a subsequent call to the identity callback of
1309 * 'GNUNET_IDENTITY_connect' (if that one was not NULL).
1310 *
1311 * When an identity is renamed, this function is called with the
1312 * (known) ego but the NEW identifier.
1313 *
1314 * When an identity is deleted, this function is called with the
1315 * (known) ego and "NULL" for the 'identifier'. In this case,
1316 * the 'ego' is henceforth invalid (and the 'ctx' should also be
1317 * cleaned up).
1318 *
1319 * @param cls closure
1320 * @param ego ego handle
1321 * @param ctx context for application to store data for this ego
1322 * (during the lifetime of this process, initially NULL)
1323 * @param identifier identifier assigned by the user for this ego,
1324 * NULL if the user just deleted the ego and it
1325 * must thus no longer be used
1326 */
1327static void
1328list_ego (void *cls,
1329 struct GNUNET_IDENTITY_Ego *ego,
1330 void **ctx,
1331 const char *identifier)
1332{
1333 struct EgoEntry *ego_entry;
1334 struct GNUNET_CRYPTO_PublicKey pk;
1335
1336 if (NULL == ego)
1337 {
1338 state = ID_REST_STATE_POST_INIT;
1339 return;
1340 }
1341 if (ID_REST_STATE_INIT == state)
1342 {
1343 ego_entry = GNUNET_new (struct EgoEntry);
1344 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1345 ego_entry->keystring = GNUNET_CRYPTO_public_key_to_string (&pk);
1346 ego_entry->ego = ego;
1347 ego_entry->identifier = GNUNET_strdup (identifier);
1348 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1349 ego_tail,
1350 ego_entry);
1351 }
1352 /* Ego renamed or added */
1353 if (identifier != NULL)
1354 {
1355 for (ego_entry = ego_head; NULL != ego_entry;
1356 ego_entry = ego_entry->next)
1357 {
1358 if (ego_entry->ego == ego)
1359 {
1360 /* Rename */
1361 GNUNET_free (ego_entry->identifier);
1362 ego_entry->identifier = GNUNET_strdup (identifier);
1363 break;
1364 }
1365 }
1366 if (NULL == ego_entry)
1367 {
1368 /* Add */
1369 ego_entry = GNUNET_new (struct EgoEntry);
1370 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1371 ego_entry->keystring = GNUNET_CRYPTO_public_key_to_string (&pk);
1372 ego_entry->ego = ego;
1373 ego_entry->identifier = GNUNET_strdup (identifier);
1374 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1375 ego_tail,
1376 ego_entry);
1377 }
1378 }
1379 else
1380 {
1381 /* Delete */
1382 for (ego_entry = ego_head; NULL != ego_entry;
1383 ego_entry = ego_entry->next)
1384 {
1385 if (ego_entry->ego == ego)
1386 break;
1387 }
1388 if (NULL == ego_entry)
1389 return; /* Not found */
1390
1391 GNUNET_CONTAINER_DLL_remove (ego_head,
1392 ego_tail,
1393 ego_entry);
1394 GNUNET_free (ego_entry->identifier);
1395 GNUNET_free (ego_entry->keystring);
1396 GNUNET_free (ego_entry);
1397 return;
1398 }
1399
1400}
1401
1402
1403enum GNUNET_GenericReturnValue
1404REST_reclaim_process_request (void *plugin,
1405 struct GNUNET_REST_RequestHandle *rest_handle,
1406 GNUNET_REST_ResultProcessor proc,
1407 void *proc_cls)
1408{
1409 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1410 struct GNUNET_REST_RequestHandlerError err;
1411 static const struct GNUNET_REST_RequestHandler handlers[] =
1412 { { MHD_HTTP_METHOD_GET,
1413 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont },
1414 { MHD_HTTP_METHOD_POST,
1415 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont },
1416 { MHD_HTTP_METHOD_DELETE,
1417 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont },
1418 { MHD_HTTP_METHOD_GET,
1419 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
1420 { MHD_HTTP_METHOD_POST,
1421 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
1422 { MHD_HTTP_METHOD_DELETE,
1423 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont },
1424 { MHD_HTTP_METHOD_GET,
1425 GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont },
1426 { MHD_HTTP_METHOD_POST,
1427 GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont },
1428 { MHD_HTTP_METHOD_POST,
1429 GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont },
1430 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
1431 GNUNET_REST_HANDLER_END};
1432
1433 handle->response_code = 0;
1434 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1435 handle->proc_cls = proc_cls;
1436 handle->proc = proc;
1437 handle->rest_handle = rest_handle;
1438
1439 handle->url = GNUNET_strdup (rest_handle->url);
1440 if (handle->url[strlen (handle->url) - 1] == '/')
1441 handle->url[strlen (handle->url) - 1] = '\0';
1442 handle->timeout_task =
1443 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
1444 GNUNET_CONTAINER_DLL_insert (requests_head,
1445 requests_tail,
1446 handle);
1447 if (GNUNET_NO ==
1448 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1449 {
1450 cleanup_handle (handle);
1451 return GNUNET_NO;
1452 }
1453
1454 return GNUNET_YES;
1455}
1456
1457
1458/**
1459 * Entry point for the plugin.
1460 *
1461 * @param cls Config info
1462 * @return NULL on error, otherwise the plugin context
1463 */
1464void *
1465REST_reclaim_init (struct GNUNET_CONFIGURATION_Handle *c)
1466{
1467 static struct Plugin plugin;
1468 struct GNUNET_REST_Plugin *api;
1469
1470 rcfg = c;
1471 if (NULL != plugin.cfg)
1472 return NULL; /* can only initialize once! */
1473 memset (&plugin, 0, sizeof(struct Plugin));
1474 plugin.cfg = rcfg;
1475 api = GNUNET_new (struct GNUNET_REST_Plugin);
1476 api->cls = &plugin;
1477 api->name = GNUNET_REST_API_NS_RECLAIM;
1478 GNUNET_asprintf (&allow_methods,
1479 "%s, %s, %s, %s, %s",
1480 MHD_HTTP_METHOD_GET,
1481 MHD_HTTP_METHOD_POST,
1482 MHD_HTTP_METHOD_PUT,
1483 MHD_HTTP_METHOD_DELETE,
1484 MHD_HTTP_METHOD_OPTIONS);
1485 identity_handle = GNUNET_IDENTITY_connect (rcfg, &list_ego, NULL);
1486 state = ID_REST_STATE_INIT;
1487 idp = GNUNET_RECLAIM_connect (rcfg);
1488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1489 _ ("Identity Provider REST API initialized\n"));
1490 return api;
1491}
1492
1493
1494/**
1495 * Exit point from the plugin.
1496 *
1497 * @param cls the plugin context (as returned by "init")
1498 * @return always NULL
1499 */
1500void *
1501REST_reclaim_done (struct GNUNET_REST_Plugin *api)
1502{
1503 struct Plugin *plugin = api->cls;
1504 struct RequestHandle *request;
1505 struct EgoEntry *ego_entry;
1506 struct EgoEntry *ego_tmp;
1507
1508 plugin->cfg = NULL;
1509 while (NULL != (request = requests_head))
1510 do_error (request);
1511 if (NULL != idp)
1512 GNUNET_RECLAIM_disconnect (idp);
1513 if (NULL != identity_handle)
1514 GNUNET_IDENTITY_disconnect (identity_handle);
1515 for (ego_entry = ego_head; NULL != ego_entry;)
1516 {
1517 ego_tmp = ego_entry;
1518 ego_entry = ego_entry->next;
1519 GNUNET_free (ego_tmp->identifier);
1520 GNUNET_free (ego_tmp->keystring);
1521 GNUNET_free (ego_tmp);
1522 }
1523
1524 GNUNET_free (allow_methods);
1525 GNUNET_free (api);
1526 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1527 "Identity Provider REST plugin is finished\n");
1528 return NULL;
1529}
1530
1531
1532/* end of plugin_rest_reclaim.c */