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