aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/plugin_rest_reclaim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/plugin_rest_reclaim.c')
-rw-r--r--src/reclaim/plugin_rest_reclaim.c1564
1 files changed, 0 insertions, 1564 deletions
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
deleted file mode 100644
index a2f8d96b2..000000000
--- a/src/reclaim/plugin_rest_reclaim.c
+++ /dev/null
@@ -1,1564 +0,0 @@
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 *cfg;
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_IDENTITY_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 MHD_add_response_header (resp, "Content-Type", "application/json");
321 handle->proc (handle->proc_cls, resp, handle->response_code);
322 cleanup_handle (handle);
323 GNUNET_free (json_error);
324}
325
326
327/**
328 * Task run on timeout, sends error message. Cleans up everything.
329 *
330 * @param cls the `struct RequestHandle`
331 */
332static void
333do_timeout (void *cls)
334{
335 struct RequestHandle *handle = cls;
336
337 handle->timeout_task = NULL;
338 do_error (handle);
339}
340
341
342static void
343collect_error_cb (void *cls)
344{
345 GNUNET_SCHEDULER_add_now (&do_error, cls);
346}
347
348
349static void
350finished_cont (void *cls, int32_t success, const char *emsg)
351{
352 struct RequestHandle *handle = cls;
353 struct MHD_Response *resp;
354
355 handle->idp_op = NULL;
356 if (GNUNET_OK != success)
357 {
358 GNUNET_SCHEDULER_add_now (&do_error, handle);
359 return;
360 }
361 resp = GNUNET_REST_create_response (emsg);
362 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
363 "Content-Type",
364 "application/json"));
365 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
366 "Access-Control-Allow-Methods",
367 allow_methods));
368 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
369 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
370}
371
372
373static void
374delete_finished_cb (void *cls, int32_t success, const char *emsg)
375{
376 struct RequestHandle *handle = cls;
377 struct MHD_Response *resp;
378
379 if (GNUNET_OK != success)
380 {
381 GNUNET_SCHEDULER_add_now (&do_error, handle);
382 return;
383 }
384 resp = GNUNET_REST_create_response (emsg);
385 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
386 "Access-Control-Allow-Methods",
387 allow_methods));
388 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
389 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
390}
391
392
393/**
394 * Return attributes for identity
395 *
396 * @param cls the request handle
397 */
398static void
399return_response (void *cls)
400{
401 char *result_str;
402 struct RequestHandle *handle = cls;
403 struct MHD_Response *resp;
404
405 result_str = json_dumps (handle->resp_object, 0);
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
407 resp = GNUNET_REST_create_response (result_str);
408 GNUNET_assert (MHD_NO !=
409 MHD_add_response_header (resp,
410 "Access-Control-Allow-Methods",
411 allow_methods));
412 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
413 GNUNET_free (result_str);
414 cleanup_handle (handle);
415}
416
417
418static void
419collect_finished_cb (void *cls)
420{
421 struct RequestHandle *handle = cls;
422
423 // Done
424 handle->attr_it = NULL;
425 handle->cred_it = NULL;
426 handle->ticket_it = NULL;
427 GNUNET_SCHEDULER_add_now (&return_response, handle);
428}
429
430
431/**
432 * Collect all attributes for an ego
433 *
434 */
435static void
436ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
437{
438 json_t *json_resource;
439 struct RequestHandle *handle = cls;
440 json_t *value;
441 char *tmp;
442
443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
444 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
445 json_resource = json_object ();
446 GNUNET_free (tmp);
447 json_array_append (handle->resp_object, json_resource);
448
449 tmp =
450 GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
451 sizeof(struct
452 GNUNET_IDENTITY_PublicKey));
453 value = json_string (tmp);
454 json_object_set_new (json_resource, "issuer", value);
455 GNUNET_free (tmp);
456 tmp =
457 GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
458 sizeof(struct
459 GNUNET_IDENTITY_PublicKey));
460 value = json_string (tmp);
461 json_object_set_new (json_resource, "audience", value);
462 GNUNET_free (tmp);
463 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
464 value = json_string (tmp);
465 json_object_set_new (json_resource, "rnd", value);
466 GNUNET_free (tmp);
467 GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
468}
469
470
471static void
472add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
473 const char *url,
474 void *cls)
475{
476 struct RequestHandle *handle = cls;
477 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
478 const char *identity;
479 struct EgoEntry *ego_entry;
480 struct GNUNET_RECLAIM_Credential *attribute;
481 struct GNUNET_TIME_Relative exp;
482 char term_data[handle->rest_handle->data_size + 1];
483 json_t *data_json;
484 json_error_t err;
485 struct GNUNET_JSON_Specification attrspec[] =
486 { GNUNET_RECLAIM_JSON_spec_credential (&attribute),
487 GNUNET_JSON_spec_end () };
488
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Adding an credential for %s.\n",
491 handle->url);
492 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
493 handle->url))
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
496 GNUNET_SCHEDULER_add_now (&do_error, handle);
497 return;
498 }
499 identity = handle->url + strlen (
500 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
501
502 for (ego_entry = ego_head; NULL != ego_entry;
503 ego_entry = ego_entry->next)
504 if (0 == strcmp (identity, ego_entry->identifier))
505 break;
506
507 if (NULL == ego_entry)
508 {
509 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
510 return;
511 }
512 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
513
514 if (0 >= handle->rest_handle->data_size)
515 {
516 GNUNET_SCHEDULER_add_now (&do_error, handle);
517 return;
518 }
519
520 term_data[handle->rest_handle->data_size] = '\0';
521 GNUNET_memcpy (term_data,
522 handle->rest_handle->data,
523 handle->rest_handle->data_size);
524 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
525 if (GNUNET_OK != GNUNET_JSON_parse (data_json, attrspec, NULL, NULL))
526 {
527 json_decref (data_json);
528 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
529 "Unable to parse JSON from %s\n",
530 term_data);
531 GNUNET_SCHEDULER_add_now (&do_error, handle);
532 return;
533 }
534 json_decref (data_json);
535 if (NULL == attribute)
536 {
537 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
538 "Unable to parse credential from %s\n",
539 term_data);
540 GNUNET_SCHEDULER_add_now (&do_error, handle);
541 return;
542 }
543 /**
544 * New ID for attribute
545 */
546 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
547 GNUNET_RECLAIM_id_generate (&attribute->id);
548 exp = GNUNET_TIME_UNIT_HOURS;
549 handle->idp_op = GNUNET_RECLAIM_credential_store (idp,
550 identity_priv,
551 attribute,
552 &exp,
553 &finished_cont,
554 handle);
555 GNUNET_JSON_parse_free (attrspec);
556}
557
558
559/**
560 * Collect all credentials for an ego
561 *
562 */
563static void
564cred_collect (void *cls,
565 const struct GNUNET_IDENTITY_PublicKey *identity,
566 const struct GNUNET_RECLAIM_Credential *cred)
567{
568 struct RequestHandle *handle = cls;
569 struct GNUNET_RECLAIM_AttributeList *attrs;
570 struct GNUNET_RECLAIM_AttributeListEntry *ale;
571 struct GNUNET_TIME_Absolute exp;
572 json_t *attr_obj;
573 json_t *cred_obj;
574 const char *type;
575 char *tmp_value;
576 char *id_str;
577 char *issuer;
578
579
580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential: %s\n",
581 cred->name);
582 attrs = GNUNET_RECLAIM_credential_get_attributes (cred);
583 issuer = GNUNET_RECLAIM_credential_get_issuer (cred);
584 tmp_value = GNUNET_RECLAIM_credential_value_to_string (cred->type,
585 cred->data,
586 cred->data_size);
587 cred_obj = json_object ();
588 json_object_set_new (cred_obj, "value", json_string (tmp_value));
589 json_object_set_new (cred_obj, "name", json_string (cred->name));
590 type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
591 json_object_set_new (cred_obj, "type", json_string (type));
592 if (NULL != issuer)
593 {
594 json_object_set_new (cred_obj, "issuer", json_string (issuer));
595 GNUNET_free (issuer);
596 }
597 if (GNUNET_OK == GNUNET_RECLAIM_credential_get_expiration (cred,
598 &exp))
599 {
600 json_object_set_new (cred_obj, "expiration", json_integer (
601 exp.abs_value_us));
602 }
603 id_str = GNUNET_STRINGS_data_to_string_alloc (&cred->id,
604 sizeof(cred->id));
605 json_object_set_new (cred_obj, "id", json_string (id_str));
606 GNUNET_free (tmp_value);
607 GNUNET_free (id_str);
608 if (NULL != attrs)
609 {
610 json_t *attr_arr = json_array ();
611 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
612 {
613 tmp_value =
614 GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
615 ale->attribute->data,
616 ale->attribute->data_size);
617 attr_obj = json_object ();
618 json_object_set_new (attr_obj, "value", json_string (tmp_value));
619 json_object_set_new (attr_obj, "name", json_string (
620 ale->attribute->name));
621
622 json_object_set_new (attr_obj, "flag", json_string ("1")); // FIXME
623 type = GNUNET_RECLAIM_attribute_number_to_typename (ale->attribute->type);
624 json_object_set_new (attr_obj, "type", json_string (type));
625 json_object_set_new (attr_obj, "id", json_string (""));
626 json_object_set_new (attr_obj, "credential", json_string (""));
627 json_array_append_new (attr_arr, attr_obj);
628 GNUNET_free (tmp_value);
629 }
630 json_object_set_new (cred_obj, "attributes", attr_arr);
631 }
632 json_array_append_new (handle->resp_object, cred_obj);
633 if (NULL != attrs)
634 GNUNET_RECLAIM_attribute_list_destroy (attrs);
635 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
636}
637
638
639/**
640 * Lists credential for identity request
641 *
642 * @param con_handle the connection handle
643 * @param url the url
644 * @param cls the RequestHandle
645 */
646static void
647list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
648 const char *url,
649 void *cls)
650{
651 struct RequestHandle *handle = cls;
652 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
653 struct EgoEntry *ego_entry;
654 char *identity;
655
656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
657 "Getting credentials for %s.\n",
658 handle->url);
659 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
660 handle->url))
661 {
662 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
663 GNUNET_SCHEDULER_add_now (&do_error, handle);
664 return;
665 }
666 identity = handle->url + strlen (
667 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
668
669 for (ego_entry = ego_head; NULL != ego_entry;
670 ego_entry = ego_entry->next)
671 if (0 == strcmp (identity, ego_entry->identifier))
672 break;
673 handle->resp_object = json_array ();
674
675
676 if (NULL == ego_entry)
677 {
678 // Done
679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
680 GNUNET_SCHEDULER_add_now (&return_response, handle);
681 return;
682 }
683 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
684 handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
685 priv_key,
686 &collect_error_cb,
687 handle,
688 &cred_collect,
689 handle,
690 &
691 collect_finished_cb,
692 handle);
693}
694
695
696/**
697 * Deletes credential from an identity
698 *
699 * @param con_handle the connection handle
700 * @param url the url
701 * @param cls the RequestHandle
702 */
703static void
704delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
705 const char *url,
706 void *cls)
707{
708 struct RequestHandle *handle = cls;
709 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
710 struct GNUNET_RECLAIM_Credential attr;
711 struct EgoEntry *ego_entry;
712 char *identity_id_str;
713 char *identity;
714 char *id;
715
716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting credential.\n");
717 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
718 handle->url))
719 {
720 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
721 GNUNET_SCHEDULER_add_now (&do_error, handle);
722 return;
723 }
724 identity_id_str =
725 strdup (handle->url + strlen (
726 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1);
727 identity = strtok (identity_id_str, "/");
728 id = strtok (NULL, "/");
729 if ((NULL == identity) || (NULL == id))
730 {
731 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
732 GNUNET_free (identity_id_str);
733 GNUNET_SCHEDULER_add_now (&do_error, handle);
734 return;
735 }
736
737 for (ego_entry = ego_head; NULL != ego_entry;
738 ego_entry = ego_entry->next)
739 if (0 == strcmp (identity, ego_entry->identifier))
740 break;
741 handle->resp_object = json_array ();
742 if (NULL == ego_entry)
743 {
744 // Done
745 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
746 GNUNET_free (identity_id_str);
747 GNUNET_SCHEDULER_add_now (&return_response, handle);
748 return;
749 }
750 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
751 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Credential));
752 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
753 attr.name = "";
754 handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
755 priv_key,
756 &attr,
757 &delete_finished_cb,
758 handle);
759 GNUNET_free (identity_id_str);
760}
761
762
763/**
764 * List tickets for identity request
765 *
766 * @param con_handle the connection handle
767 * @param url the url
768 * @param cls the RequestHandle
769 */
770static void
771list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
772 const char *url,
773 void *cls)
774{
775 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
776 struct RequestHandle *handle = cls;
777 struct EgoEntry *ego_entry;
778 char *identity;
779
780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
781 "Getting tickets for %s.\n",
782 handle->url);
783 if (strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= strlen (handle->url))
784 {
785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
786 GNUNET_SCHEDULER_add_now (&do_error, handle);
787 return;
788 }
789 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
790
791 for (ego_entry = ego_head; NULL != ego_entry;
792 ego_entry = ego_entry->next)
793 if (0 == strcmp (identity, ego_entry->identifier))
794 break;
795 handle->resp_object = json_array ();
796
797 if (NULL == ego_entry)
798 {
799 // Done
800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
801 GNUNET_SCHEDULER_add_now (&return_response, handle);
802 return;
803 }
804 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
805 handle->ticket_it =
806 GNUNET_RECLAIM_ticket_iteration_start (idp,
807 priv_key,
808 &collect_error_cb,
809 handle,
810 &ticket_collect,
811 handle,
812 &collect_finished_cb,
813 handle);
814}
815
816
817static void
818add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
819 const char *url,
820 void *cls)
821{
822 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
823 const char *identity;
824 struct RequestHandle *handle = cls;
825 struct EgoEntry *ego_entry;
826 struct GNUNET_RECLAIM_Attribute *attribute;
827 struct GNUNET_TIME_Relative exp;
828 char term_data[handle->rest_handle->data_size + 1];
829 json_t *data_json;
830 json_error_t err;
831 struct GNUNET_JSON_Specification attrspec[] =
832 { GNUNET_RECLAIM_JSON_spec_attribute (&attribute), GNUNET_JSON_spec_end () };
833
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
835 "Adding an attribute for %s.\n",
836 handle->url);
837 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
838 {
839 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
840 GNUNET_SCHEDULER_add_now (&do_error, handle);
841 return;
842 }
843 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
844
845 for (ego_entry = ego_head; NULL != ego_entry;
846 ego_entry = ego_entry->next)
847 if (0 == strcmp (identity, ego_entry->identifier))
848 break;
849
850 if (NULL == ego_entry)
851 {
852 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
853 return;
854 }
855 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
856
857 if (0 >= handle->rest_handle->data_size)
858 {
859 GNUNET_SCHEDULER_add_now (&do_error, handle);
860 return;
861 }
862
863 term_data[handle->rest_handle->data_size] = '\0';
864 GNUNET_memcpy (term_data,
865 handle->rest_handle->data,
866 handle->rest_handle->data_size);
867 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
868 GNUNET_assert (GNUNET_OK ==
869 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
870 json_decref (data_json);
871 if (NULL == attribute)
872 {
873 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
874 "Unable to parse attribute from %s\n",
875 term_data);
876 GNUNET_SCHEDULER_add_now (&do_error, handle);
877 return;
878 }
879 /**
880 * New ID for attribute
881 */
882 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
883 GNUNET_RECLAIM_id_generate (&attribute->id);
884 exp = GNUNET_TIME_UNIT_HOURS;
885 handle->idp_op = GNUNET_RECLAIM_attribute_store (idp,
886 identity_priv,
887 attribute,
888 &exp,
889 &finished_cont,
890 handle);
891 GNUNET_JSON_parse_free (attrspec);
892}
893
894
895/**
896 * Parse a JWT and return the respective claim value as Attribute
897 *
898 * @param cred the jwt credential
899 * @param claim the name of the claim in the JWT
900 *
901 * @return a GNUNET_RECLAIM_Attribute, containing the new value
902 */
903struct GNUNET_RECLAIM_Attribute *
904parse_jwt (const struct GNUNET_RECLAIM_Credential *cred,
905 const char *claim)
906{
907 char *jwt_string;
908 struct GNUNET_RECLAIM_Attribute *attr;
909 char delim[] = ".";
910 const char *type_str = NULL;
911 const char *val_str = NULL;
912 char *data;
913 size_t data_size;
914 uint32_t type;
915 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
916 char *decoded_jwt;
917 json_t *json_val;
918 json_error_t *json_err = NULL;
919
920 jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type,
921 cred->data,
922 cred->data_size);
923 char *jwt_body = strtok (jwt_string, delim);
924 jwt_body = strtok (NULL, delim);
925 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
926 (void **) &decoded_jwt);
927 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
928 const char *key;
929 json_t *value;
930 json_object_foreach (json_val, key, value) {
931 if (0 == strcasecmp (key,claim))
932 {
933 val_str = json_dumps (value, JSON_ENCODE_ANY);
934 }
935 }
936 type_str = "String";
937 type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
938 if (GNUNET_SYSERR == GNUNET_RECLAIM_attribute_string_to_value (type,val_str,
939 (void **) &data,
940 &data_size))
941 {
942 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
943 "Attribute value from JWT Parser invalid!\n");
944 GNUNET_RECLAIM_attribute_string_to_value (type,
945 "Error: Referenced Claim Name not Found",
946 (void **) &data,
947 &data_size);
948 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
949 type, data, data_size);
950 attr->id = cred->id;
951 attr->flag = 1;
952 }
953 else
954 {
955 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
956 type, data, data_size);
957 attr->id = cred->id;
958 attr->flag = 1;
959 }
960 return attr;
961}
962
963
964/**
965 * Collect all attributes for an ego
966 *
967 */
968static void
969attr_collect (void *cls,
970 const struct GNUNET_IDENTITY_PublicKey *identity,
971 const struct GNUNET_RECLAIM_Attribute *attr)
972{
973 struct RequestHandle *handle = cls;
974 json_t *attr_obj;
975 const char *type;
976 char *id_str;
977
978 char *tmp_value;
979 tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
980 attr->data,
981 attr->data_size);
982 attr_obj = json_object ();
983 json_object_set_new (attr_obj, "value", json_string (tmp_value));
984 json_object_set_new (attr_obj, "name", json_string (attr->name));
985
986 if (GNUNET_RECLAIM_id_is_zero (&attr->credential))
987 json_object_set_new (attr_obj, "flag", json_string ("0"));
988 else
989 json_object_set_new (attr_obj, "flag", json_string ("1"));
990 type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
991 json_object_set_new (attr_obj, "type", json_string (type));
992 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
993 sizeof(attr->id));
994 json_object_set_new (attr_obj, "id", json_string (id_str));
995 GNUNET_free (id_str);
996 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
997 sizeof(attr->credential));
998 json_object_set_new (attr_obj, "credential", json_string (id_str));
999 GNUNET_free (id_str);
1000 json_array_append (handle->resp_object, attr_obj);
1001 json_decref (attr_obj);
1002 GNUNET_free (tmp_value);
1003 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1004}
1005
1006
1007/**
1008 * List attributes for identity request
1009 *
1010 * @param con_handle the connection handle
1011 * @param url the url
1012 * @param cls the RequestHandle
1013 */
1014static void
1015list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1016 const char *url,
1017 void *cls)
1018{
1019 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1020 struct RequestHandle *handle = cls;
1021 struct EgoEntry *ego_entry;
1022 char *identity;
1023
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1025 "Getting attributes for %s.\n",
1026 handle->url);
1027 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1028 {
1029 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1030 GNUNET_SCHEDULER_add_now (&do_error, handle);
1031 return;
1032 }
1033 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
1034
1035 for (ego_entry = ego_head; NULL != ego_entry;
1036 ego_entry = ego_entry->next)
1037 if (0 == strcmp (identity, ego_entry->identifier))
1038 break;
1039 handle->resp_object = json_array ();
1040
1041
1042 if (NULL == ego_entry)
1043 {
1044 // Done
1045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1046 GNUNET_SCHEDULER_add_now (&return_response, handle);
1047 return;
1048 }
1049 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1050 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (idp,
1051 priv_key,
1052 &collect_error_cb,
1053 handle,
1054 &attr_collect,
1055 handle,
1056 &collect_finished_cb,
1057 handle);
1058}
1059
1060
1061/**
1062 * List attributes for identity request
1063 *
1064 * @param con_handle the connection handle
1065 * @param url the url
1066 * @param cls the RequestHandle
1067 */
1068static void
1069delete_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1070 const char *url,
1071 void *cls)
1072{
1073 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1074 struct RequestHandle *handle = cls;
1075 struct GNUNET_RECLAIM_Attribute attr;
1076 struct EgoEntry *ego_entry;
1077 char *identity_id_str;
1078 char *identity;
1079 char *id;
1080
1081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attributes.\n");
1082 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1083 {
1084 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1085 GNUNET_SCHEDULER_add_now (&do_error, handle);
1086 return;
1087 }
1088 identity_id_str =
1089 strdup (handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1);
1090 identity = strtok (identity_id_str, "/");
1091 id = strtok (NULL, "/");
1092 if ((NULL == identity) || (NULL == id))
1093 {
1094 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
1095 GNUNET_free (identity_id_str);
1096 GNUNET_SCHEDULER_add_now (&do_error, handle);
1097 return;
1098 }
1099
1100 for (ego_entry = ego_head; NULL != ego_entry;
1101 ego_entry = ego_entry->next)
1102 if (0 == strcmp (identity, ego_entry->identifier))
1103 break;
1104 handle->resp_object = json_array ();
1105 if (NULL == ego_entry)
1106 {
1107 // Done
1108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1109 GNUNET_free (identity_id_str);
1110 GNUNET_SCHEDULER_add_now (&return_response, handle);
1111 return;
1112 }
1113 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1114 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Attribute));
1115 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
1116 attr.name = "";
1117 handle->idp_op = GNUNET_RECLAIM_attribute_delete (idp,
1118 priv_key,
1119 &attr,
1120 &delete_finished_cb,
1121 handle);
1122 GNUNET_free (identity_id_str);
1123}
1124
1125
1126static void
1127revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1128 const char *url,
1129 void *cls)
1130{
1131 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
1132 struct RequestHandle *handle = cls;
1133 struct EgoEntry *ego_entry;
1134 struct GNUNET_RECLAIM_Ticket *ticket = NULL;
1135 struct GNUNET_IDENTITY_PublicKey tmp_pk;
1136 char term_data[handle->rest_handle->data_size + 1];
1137 json_t *data_json;
1138 json_error_t err;
1139 struct GNUNET_JSON_Specification tktspec[] =
1140 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1141
1142 if (0 >= handle->rest_handle->data_size)
1143 {
1144 GNUNET_SCHEDULER_add_now (&do_error, handle);
1145 return;
1146 }
1147
1148 term_data[handle->rest_handle->data_size] = '\0';
1149 GNUNET_memcpy (term_data,
1150 handle->rest_handle->data,
1151 handle->rest_handle->data_size);
1152 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1153 if ((NULL == data_json) ||
1154 (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL)))
1155 {
1156 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1157 GNUNET_SCHEDULER_add_now (&do_error, handle);
1158 GNUNET_JSON_parse_free (tktspec);
1159 if (NULL != data_json)
1160 json_decref (data_json);
1161 return;
1162 }
1163 json_decref (data_json);
1164 if (NULL == ticket)
1165 {
1166 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1167 "Unable to parse ticket from %s\n",
1168 term_data);
1169 GNUNET_SCHEDULER_add_now (&do_error, handle);
1170 return;
1171 }
1172
1173 for (ego_entry = ego_head; NULL != ego_entry;
1174 ego_entry = ego_entry->next)
1175 {
1176 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1177 if (0 == memcmp (&ticket->identity,
1178 &tmp_pk,
1179 sizeof(struct GNUNET_IDENTITY_PublicKey)))
1180 break;
1181 }
1182 if (NULL == ego_entry)
1183 {
1184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1185 GNUNET_JSON_parse_free (tktspec);
1186 return;
1187 }
1188 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1189
1190 handle->idp_op = GNUNET_RECLAIM_ticket_revoke (idp,
1191 identity_priv,
1192 ticket,
1193 &finished_cont,
1194 handle);
1195 GNUNET_JSON_parse_free (tktspec);
1196}
1197
1198
1199static void
1200consume_cont (void *cls,
1201 const struct GNUNET_IDENTITY_PublicKey *identity,
1202 const struct GNUNET_RECLAIM_Attribute *attr,
1203 const struct GNUNET_RECLAIM_Presentation *presentation)
1204{
1205 struct RequestHandle *handle = cls;
1206 char *val_str;
1207 json_t *value;
1208
1209 if (NULL == identity)
1210 {
1211 GNUNET_SCHEDULER_add_now (&return_response, handle);
1212 return;
1213 }
1214
1215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
1216 val_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
1217 attr->data,
1218 attr->data_size);
1219 if (NULL == val_str)
1220 {
1221 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1222 "Failed to parse value for: %s\n",
1223 attr->name);
1224 return;
1225 }
1226 value = json_string (val_str);
1227 json_object_set_new (handle->resp_object, attr->name, value);
1228 json_decref (value);
1229 GNUNET_free (val_str);
1230}
1231
1232
1233static void
1234consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1235 const char *url,
1236 void *cls)
1237{
1238 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
1239 struct RequestHandle *handle = cls;
1240 struct EgoEntry *ego_entry;
1241 struct GNUNET_RECLAIM_Ticket *ticket;
1242 struct GNUNET_IDENTITY_PublicKey tmp_pk;
1243 char term_data[handle->rest_handle->data_size + 1];
1244 json_t *data_json;
1245 json_error_t err;
1246 struct GNUNET_JSON_Specification tktspec[] =
1247 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1248
1249 if (0 >= handle->rest_handle->data_size)
1250 {
1251 GNUNET_SCHEDULER_add_now (&do_error, handle);
1252 return;
1253 }
1254
1255 term_data[handle->rest_handle->data_size] = '\0';
1256 GNUNET_memcpy (term_data,
1257 handle->rest_handle->data,
1258 handle->rest_handle->data_size);
1259 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1260 if (NULL == data_json)
1261 {
1262 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1263 "Unable to parse JSON Object from %s\n",
1264 term_data);
1265 GNUNET_SCHEDULER_add_now (&do_error, handle);
1266 return;
1267 }
1268 if (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL))
1269 {
1270 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1271 GNUNET_SCHEDULER_add_now (&do_error, handle);
1272 GNUNET_JSON_parse_free (tktspec);
1273 json_decref (data_json);
1274 return;
1275 }
1276 for (ego_entry = ego_head; NULL != ego_entry;
1277 ego_entry = ego_entry->next)
1278 {
1279 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1280 if (0 == memcmp (&ticket->audience,
1281 &tmp_pk,
1282 sizeof(struct GNUNET_IDENTITY_PublicKey)))
1283 break;
1284 }
1285 if (NULL == ego_entry)
1286 {
1287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1288 GNUNET_JSON_parse_free (tktspec);
1289 return;
1290 }
1291 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1292 handle->resp_object = json_object ();
1293 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
1294 identity_priv,
1295 ticket,
1296 &consume_cont,
1297 handle);
1298 GNUNET_JSON_parse_free (tktspec);
1299}
1300
1301
1302/**
1303 * Respond to OPTIONS request
1304 *
1305 * @param con_handle the connection handle
1306 * @param url the url
1307 * @param cls the RequestHandle
1308 */
1309static void
1310options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1311 const char *url,
1312 void *cls)
1313{
1314 struct MHD_Response *resp;
1315 struct RequestHandle *handle = cls;
1316
1317 // For now, independent of path return all options
1318 resp = GNUNET_REST_create_response (NULL);
1319 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1320 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1321 cleanup_handle (handle);
1322 return;
1323}
1324
1325
1326/**
1327 * If listing is enabled, prints information about the egos.
1328 *
1329 * This function is initially called for all egos and then again
1330 * whenever a ego's identifier changes or if it is deleted. At the
1331 * end of the initial pass over all egos, the function is once called
1332 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
1333 * be invoked in the future or that there was an error.
1334 *
1335 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', this
1336 * function is only called ONCE, and 'NULL' being passed in 'ego' does
1337 * indicate an error (for example because name is taken or no default value is
1338 * known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the
1339 * value WILL be passed to a subsequent call to the identity callback of
1340 * 'GNUNET_IDENTITY_connect' (if that one was not NULL).
1341 *
1342 * When an identity is renamed, this function is called with the
1343 * (known) ego but the NEW identifier.
1344 *
1345 * When an identity is deleted, this function is called with the
1346 * (known) ego and "NULL" for the 'identifier'. In this case,
1347 * the 'ego' is henceforth invalid (and the 'ctx' should also be
1348 * cleaned up).
1349 *
1350 * @param cls closure
1351 * @param ego ego handle
1352 * @param ctx context for application to store data for this ego
1353 * (during the lifetime of this process, initially NULL)
1354 * @param identifier identifier assigned by the user for this ego,
1355 * NULL if the user just deleted the ego and it
1356 * must thus no longer be used
1357 */
1358static void
1359list_ego (void *cls,
1360 struct GNUNET_IDENTITY_Ego *ego,
1361 void **ctx,
1362 const char *identifier)
1363{
1364 struct EgoEntry *ego_entry;
1365 struct GNUNET_IDENTITY_PublicKey pk;
1366
1367 if (NULL == ego)
1368 {
1369 state = ID_REST_STATE_POST_INIT;
1370 return;
1371 }
1372 if (ID_REST_STATE_INIT == state)
1373 {
1374 ego_entry = GNUNET_new (struct EgoEntry);
1375 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1376 ego_entry->keystring = GNUNET_IDENTITY_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 /* Ego renamed or added */
1384 if (identifier != NULL)
1385 {
1386 for (ego_entry = ego_head; NULL != ego_entry;
1387 ego_entry = ego_entry->next)
1388 {
1389 if (ego_entry->ego == ego)
1390 {
1391 /* Rename */
1392 GNUNET_free (ego_entry->identifier);
1393 ego_entry->identifier = GNUNET_strdup (identifier);
1394 break;
1395 }
1396 }
1397 if (NULL == ego_entry)
1398 {
1399 /* Add */
1400 ego_entry = GNUNET_new (struct EgoEntry);
1401 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1402 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
1403 ego_entry->ego = ego;
1404 ego_entry->identifier = GNUNET_strdup (identifier);
1405 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1406 ego_tail,
1407 ego_entry);
1408 }
1409 }
1410 else
1411 {
1412 /* Delete */
1413 for (ego_entry = ego_head; NULL != ego_entry;
1414 ego_entry = ego_entry->next)
1415 {
1416 if (ego_entry->ego == ego)
1417 break;
1418 }
1419 if (NULL == ego_entry)
1420 return; /* Not found */
1421
1422 GNUNET_CONTAINER_DLL_remove (ego_head,
1423 ego_tail,
1424 ego_entry);
1425 GNUNET_free (ego_entry->identifier);
1426 GNUNET_free (ego_entry->keystring);
1427 GNUNET_free (ego_entry);
1428 return;
1429 }
1430
1431}
1432
1433
1434static enum GNUNET_GenericReturnValue
1435rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1436 GNUNET_REST_ResultProcessor proc,
1437 void *proc_cls)
1438{
1439 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1440 struct GNUNET_REST_RequestHandlerError err;
1441 static const struct GNUNET_REST_RequestHandler handlers[] =
1442 { { MHD_HTTP_METHOD_GET,
1443 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont },
1444 { MHD_HTTP_METHOD_POST,
1445 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont },
1446 { MHD_HTTP_METHOD_DELETE,
1447 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont },
1448 { MHD_HTTP_METHOD_GET,
1449 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
1450 { MHD_HTTP_METHOD_POST,
1451 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
1452 { MHD_HTTP_METHOD_DELETE,
1453 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont },
1454 { MHD_HTTP_METHOD_GET,
1455 GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont },
1456 { MHD_HTTP_METHOD_POST,
1457 GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont },
1458 { MHD_HTTP_METHOD_POST,
1459 GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont },
1460 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
1461 GNUNET_REST_HANDLER_END};
1462
1463 handle->response_code = 0;
1464 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1465 handle->proc_cls = proc_cls;
1466 handle->proc = proc;
1467 handle->rest_handle = rest_handle;
1468
1469 handle->url = GNUNET_strdup (rest_handle->url);
1470 if (handle->url[strlen (handle->url) - 1] == '/')
1471 handle->url[strlen (handle->url) - 1] = '\0';
1472 handle->timeout_task =
1473 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
1474 GNUNET_CONTAINER_DLL_insert (requests_head,
1475 requests_tail,
1476 handle);
1477 if (GNUNET_NO ==
1478 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1479 {
1480 cleanup_handle (handle);
1481 return GNUNET_NO;
1482 }
1483
1484 return GNUNET_YES;
1485}
1486
1487
1488/**
1489 * Entry point for the plugin.
1490 *
1491 * @param cls Config info
1492 * @return NULL on error, otherwise the plugin context
1493 */
1494void *
1495libgnunet_plugin_rest_reclaim_init (void *cls)
1496{
1497 static struct Plugin plugin;
1498 struct GNUNET_REST_Plugin *api;
1499
1500 cfg = cls;
1501 if (NULL != plugin.cfg)
1502 return NULL; /* can only initialize once! */
1503 memset (&plugin, 0, sizeof(struct Plugin));
1504 plugin.cfg = cfg;
1505 api = GNUNET_new (struct GNUNET_REST_Plugin);
1506 api->cls = &plugin;
1507 api->name = GNUNET_REST_API_NS_RECLAIM;
1508 api->process_request = &rest_identity_process_request;
1509 GNUNET_asprintf (&allow_methods,
1510 "%s, %s, %s, %s, %s",
1511 MHD_HTTP_METHOD_GET,
1512 MHD_HTTP_METHOD_POST,
1513 MHD_HTTP_METHOD_PUT,
1514 MHD_HTTP_METHOD_DELETE,
1515 MHD_HTTP_METHOD_OPTIONS);
1516 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1517 state = ID_REST_STATE_INIT;
1518 idp = GNUNET_RECLAIM_connect (cfg);
1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1520 _ ("Identity Provider REST API initialized\n"));
1521 return api;
1522}
1523
1524
1525/**
1526 * Exit point from the plugin.
1527 *
1528 * @param cls the plugin context (as returned by "init")
1529 * @return always NULL
1530 */
1531void *
1532libgnunet_plugin_rest_reclaim_done (void *cls)
1533{
1534 struct GNUNET_REST_Plugin *api = cls;
1535 struct Plugin *plugin = api->cls;
1536 struct RequestHandle *request;
1537 struct EgoEntry *ego_entry;
1538 struct EgoEntry *ego_tmp;
1539
1540 plugin->cfg = NULL;
1541 while (NULL != (request = requests_head))
1542 do_error (request);
1543 if (NULL != idp)
1544 GNUNET_RECLAIM_disconnect (idp);
1545 if (NULL != identity_handle)
1546 GNUNET_IDENTITY_disconnect (identity_handle);
1547 for (ego_entry = ego_head; NULL != ego_entry;)
1548 {
1549 ego_tmp = ego_entry;
1550 ego_entry = ego_entry->next;
1551 GNUNET_free (ego_tmp->identifier);
1552 GNUNET_free (ego_tmp->keystring);
1553 GNUNET_free (ego_tmp);
1554 }
1555
1556 GNUNET_free (allow_methods);
1557 GNUNET_free (api);
1558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1559 "Identity Provider REST plugin is finished\n");
1560 return NULL;
1561}
1562
1563
1564/* end of plugin_rest_reclaim.c */