aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim')
-rw-r--r--src/reclaim/.gitignore2
-rw-r--r--src/reclaim/Makefile.am174
-rw-r--r--src/reclaim/gnunet-reclaim.c924
-rw-r--r--src/reclaim/gnunet-service-reclaim.c2342
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.c1852
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.h280
-rw-r--r--src/reclaim/json_reclaim.c392
-rw-r--r--src/reclaim/json_reclaim.h57
-rw-r--r--src/reclaim/oidc_helper.c863
-rw-r--r--src/reclaim/oidc_helper.h159
-rw-r--r--src/reclaim/plugin_gnsrecord_reclaim.c198
-rw-r--r--src/reclaim/plugin_reclaim_attribute_basic.c181
-rw-r--r--src/reclaim/plugin_reclaim_credential_jwt.c435
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c2672
-rw-r--r--src/reclaim/plugin_rest_reclaim.c1546
-rw-r--r--src/reclaim/reclaim.conf19
-rw-r--r--src/reclaim/reclaim.h552
-rw-r--r--src/reclaim/reclaim_api.c1763
-rw-r--r--src/reclaim/reclaim_attribute.c550
-rw-r--r--src/reclaim/reclaim_attribute.h73
-rw-r--r--src/reclaim/reclaim_credential.c1037
-rw-r--r--src/reclaim/reclaim_credential.h99
-rw-r--r--src/reclaim/test_reclaim.conf34
-rwxr-xr-xsrc/reclaim/test_reclaim.sh31
-rw-r--r--src/reclaim/test_reclaim_attribute.c49
-rwxr-xr-xsrc/reclaim/test_reclaim_attribute.sh40
-rwxr-xr-xsrc/reclaim/test_reclaim_consume.sh43
-rw-r--r--src/reclaim/test_reclaim_defaults.conf24
-rwxr-xr-xsrc/reclaim/test_reclaim_issue.sh42
-rwxr-xr-xsrc/reclaim/test_reclaim_revoke.sh65
30 files changed, 0 insertions, 16498 deletions
diff --git a/src/reclaim/.gitignore b/src/reclaim/.gitignore
deleted file mode 100644
index 46472101b..000000000
--- a/src/reclaim/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
1gnunet-reclaim
2gnunet-service-reclaim
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am
deleted file mode 100644
index 9463f19d9..000000000
--- a/src/reclaim/Makefile.am
+++ /dev/null
@@ -1,174 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4 plugindir = $(libdir)/gnunet
5
6if USE_COVERAGE
7 AM_CFLAGS = --coverage -O0
8 XLIB = -lgcov
9endif
10
11
12REST_PLUGIN = \
13 libgnunet_plugin_rest_openid_connect.la \
14 libgnunet_plugin_rest_reclaim.la
15
16CREDENTIAL_PLUGIN = \
17 libgnunet_plugin_reclaim_credential_jwt.la
18
19EXTRA_DIST = \
20 reclaim.conf \
21 test_reclaim_defaults.conf \
22 test_reclaim.conf \
23 $(check_SCRIPTS)
24
25pkgcfgdir= $(pkgdatadir)/config.d/
26
27libexecdir= $(pkglibdir)/libexec/
28
29pkgcfg_DATA = \
30 reclaim.conf
31
32lib_LTLIBRARIES = \
33 libgnunetreclaim.la
34plugin_LTLIBRARIES = \
35 libgnunet_plugin_gnsrecord_reclaim.la \
36 libgnunet_plugin_reclaim_attribute_basic.la \
37 $(CREDENTIAL_PLUGIN) \
38 $(REST_PLUGIN)
39
40bin_PROGRAMS = \
41 gnunet-reclaim
42
43libexec_PROGRAMS = \
44 gnunet-service-reclaim
45
46libgnunet_plugin_rest_reclaim_la_SOURCES = \
47 plugin_rest_reclaim.c \
48 json_reclaim.h \
49 json_reclaim.c
50libgnunet_plugin_rest_reclaim_la_LIBADD = \
51 $(top_builddir)/src/identity/libgnunetidentity.la \
52 libgnunetreclaim.la \
53 $(top_builddir)/src/json/libgnunetjson.la \
54 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
55 $(top_builddir)/src/rest/libgnunetrest.la \
56 $(top_builddir)/src/namestore/libgnunetnamestore.la \
57 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
58 $(LTLIBINTL) -ljansson $(MHD_LIBS)
59libgnunet_plugin_rest_reclaim_la_DEPENDENCIES = \
60 $(top_builddir)/src/identity/libgnunetidentity.la \
61 libgnunetreclaim.la \
62 $(top_builddir)/src/json/libgnunetjson.la \
63 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
64 $(top_builddir)/src/rest/libgnunetrest.la \
65 $(top_builddir)/src/namestore/libgnunetnamestore.la \
66 $(top_builddir)/src/util/libgnunetutil.la
67libgnunet_plugin_rest_reclaim_la_LDFLAGS = \
68 $(GN_PLUGIN_LDFLAGS)
69libgnunet_plugin_rest_reclaim_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
70
71
72libgnunet_plugin_rest_openid_connect_la_SOURCES = \
73 plugin_rest_openid_connect.c \
74 oidc_helper.h \
75 oidc_helper.c
76libgnunet_plugin_rest_openid_connect_la_LIBADD = \
77 $(top_builddir)/src/identity/libgnunetidentity.la \
78 libgnunetreclaim.la \
79 $(top_builddir)/src/rest/libgnunetrest.la \
80 $(top_builddir)/src/namestore/libgnunetnamestore.la \
81 $(top_builddir)/src/gns/libgnunetgns.la \
82 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
83 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
84 $(LTLIBINTL) -ljansson $(MHD_LIBS) \
85 $(LIBGCRYPT_LIBS)
86libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \
87 $(GN_PLUGIN_LDFLAGS)
88libgnunet_plugin_rest_openid_connect_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
89
90
91libgnunet_plugin_gnsrecord_reclaim_la_SOURCES = \
92 plugin_gnsrecord_reclaim.c
93libgnunet_plugin_gnsrecord_reclaim_la_LIBADD = \
94 $(top_builddir)/src/util/libgnunetutil.la \
95 $(LTLIBINTL)
96libgnunet_plugin_gnsrecord_reclaim_la_LDFLAGS = \
97 $(GN_PLUGIN_LDFLAGS)
98
99
100gnunet_service_reclaim_SOURCES = \
101 gnunet-service-reclaim.c \
102 gnunet-service-reclaim_tickets.c \
103 gnunet-service-reclaim_tickets.h
104gnunet_service_reclaim_LDADD = \
105 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
106 $(top_builddir)/src/identity/libgnunetidentity.la \
107 $(top_builddir)/src/util/libgnunetutil.la \
108 $(top_builddir)/src/namestore/libgnunetnamestore.la \
109 $(top_builddir)/src/statistics/libgnunetstatistics.la \
110 libgnunetreclaim.la \
111 $(top_builddir)/src/gns/libgnunetgns.la \
112 $(GN_LIBINTL)
113
114libgnunetreclaim_la_SOURCES = \
115 reclaim_api.c \
116 reclaim.h \
117 reclaim_attribute.c \
118 reclaim_attribute.h \
119 reclaim_credential.c \
120 reclaim_credential.h
121libgnunetreclaim_la_LIBADD = \
122 $(top_builddir)/src/util/libgnunetutil.la \
123 $(GN_LIBINTL) $(XLIB)
124libgnunetreclaim_la_LDFLAGS = \
125 $(GN_LIB_LDFLAGS) \
126 -version-info 0:0:0
127
128
129libgnunet_plugin_reclaim_attribute_basic_la_SOURCES = \
130 plugin_reclaim_attribute_basic.c
131libgnunet_plugin_reclaim_attribute_basic_la_LIBADD = \
132 $(top_builddir)/src/util/libgnunetutil.la \
133 $(LTLIBINTL)
134libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \
135 $(GN_PLUGIN_LDFLAGS)
136
137libgnunet_plugin_reclaim_credential_jwt_la_SOURCES = \
138 plugin_reclaim_credential_jwt.c
139libgnunet_plugin_reclaim_credential_jwt_la_LIBADD = \
140 $(top_builddir)/src/util/libgnunetutil.la \
141 libgnunetreclaim.la \
142 -ljansson\
143 $(LTLIBINTL)
144libgnunet_plugin_reclaim_credential_jwt_la_LDFLAGS = \
145 $(GN_PLUGIN_LDFLAGS)
146
147gnunet_reclaim_SOURCES = \
148 gnunet-reclaim.c
149gnunet_reclaim_LDADD = \
150 $(top_builddir)/src/util/libgnunetutil.la \
151 $(top_builddir)/src/namestore/libgnunetnamestore.la \
152 libgnunetreclaim.la \
153 $(top_builddir)/src/identity/libgnunetidentity.la \
154 $(GN_LIBINTL)
155
156test_reclaim_attribute_SOURCES = \
157 test_reclaim_attribute.c
158test_reclaim_attribute_LDADD = \
159 $(top_builddir)/src/util/libgnunetutil.la \
160 libgnunetreclaim.la \
161 $(GN_LIBINTL)
162
163check_SCRIPTS = \
164 test_reclaim_attribute.sh \
165 test_reclaim_issue.sh \
166 test_reclaim_consume.sh
167
168check_PROGRAMS = \
169 test_reclaim_attribute
170
171if ENABLE_TEST_RUN
172 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
173 TESTS = $(check_SCRIPTS)
174endif
diff --git a/src/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c
deleted file mode 100644
index cefb66b8f..000000000
--- a/src/reclaim/gnunet-reclaim.c
+++ /dev/null
@@ -1,924 +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 * @file src/reclaim/gnunet-reclaim.c
23 * @brief Identity Provider utility
24 *
25 */
26#include "platform.h"
27#include <inttypes.h>
28
29#include "gnunet_util_lib.h"
30
31#include "gnunet_identity_service.h"
32#include "gnunet_namestore_service.h"
33#include "gnunet_reclaim_service.h"
34#include "gnunet_signatures.h"
35/**
36 * return value
37 */
38static int ret;
39
40/**
41 * List attribute flag
42 */
43static int list;
44
45/**
46 * List credentials flag
47 */
48static int list_credentials;
49
50/**
51 * Credential ID string
52 */
53static char *credential_id;
54
55/**
56 * Credential ID
57 */
58static struct GNUNET_RECLAIM_Identifier credential;
59
60/**
61 * Credential name
62 */
63static char *credential_name;
64
65/**
66 * Credential type
67 */
68static char *credential_type;
69
70/**
71 * Credential exists
72 */
73static int credential_exists;
74
75/**
76 * Relying party
77 */
78static char *rp;
79
80/**
81 * The attribute
82 */
83static char *attr_name;
84
85/**
86 * Attribute value
87 */
88static char *attr_value;
89
90/**
91 * Attributes to issue
92 */
93static char *issue_attrs;
94
95/**
96 * Ticket to consume
97 */
98static char *consume_ticket;
99
100/**
101 * Attribute type
102 */
103static char *type_str;
104
105/**
106 * Ticket to revoke
107 */
108static char *revoke_ticket;
109
110/**
111 * Ticket listing
112 */
113static int list_tickets;
114
115/**
116 * Ego name
117 */
118static char *ego_name;
119
120/**
121 * Identity handle
122 */
123static struct GNUNET_IDENTITY_Handle *identity_handle;
124
125/**
126 * reclaim handle
127 */
128static struct GNUNET_RECLAIM_Handle *reclaim_handle;
129
130/**
131 * reclaim operation
132 */
133static struct GNUNET_RECLAIM_Operation *reclaim_op;
134
135/**
136 * Attribute iterator
137 */
138static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
139
140/**
141 * Credential iterator
142 */
143static struct GNUNET_RECLAIM_CredentialIterator *cred_iterator;
144
145
146/**
147 * Ticket iterator
148 */
149static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator;
150
151
152/**
153 * ego private key
154 */
155static const struct GNUNET_IDENTITY_PrivateKey *pkey;
156
157/**
158 * rp public key
159 */
160static struct GNUNET_IDENTITY_PublicKey rp_key;
161
162/**
163 * Ticket to consume
164 */
165static struct GNUNET_RECLAIM_Ticket ticket;
166
167/**
168 * Attribute list
169 */
170static struct GNUNET_RECLAIM_AttributeList *attr_list;
171
172/**
173 * Attribute expiration interval
174 */
175static struct GNUNET_TIME_Relative exp_interval;
176
177/**
178 * Timeout task
179 */
180static struct GNUNET_SCHEDULER_Task *timeout;
181
182/**
183 * Cleanup task
184 */
185static struct GNUNET_SCHEDULER_Task *cleanup_task;
186
187/**
188 * Claim to store
189 */
190struct GNUNET_RECLAIM_Attribute *claim;
191
192/**
193 * Claim to delete
194 */
195static char *attr_delete;
196
197/**
198 * Claim object to delete
199 */
200static struct GNUNET_RECLAIM_Attribute *attr_to_delete;
201
202static void
203do_cleanup (void *cls)
204{
205 cleanup_task = NULL;
206 if (NULL != timeout)
207 GNUNET_SCHEDULER_cancel (timeout);
208 if (NULL != reclaim_op)
209 GNUNET_RECLAIM_cancel (reclaim_op);
210 if (NULL != attr_iterator)
211 GNUNET_RECLAIM_get_attributes_stop (attr_iterator);
212 if (NULL != cred_iterator)
213 GNUNET_RECLAIM_get_credentials_stop (cred_iterator);
214 if (NULL != ticket_iterator)
215 GNUNET_RECLAIM_ticket_iteration_stop (ticket_iterator);
216 if (NULL != reclaim_handle)
217 GNUNET_RECLAIM_disconnect (reclaim_handle);
218 if (NULL != identity_handle)
219 GNUNET_IDENTITY_disconnect (identity_handle);
220 if (NULL != attr_list)
221 GNUNET_free (attr_list);
222 if (NULL != attr_to_delete)
223 GNUNET_free (attr_to_delete);
224 if (NULL == credential_type)
225 GNUNET_free (credential_type);
226}
227
228
229static void
230ticket_issue_cb (void *cls,
231 const struct GNUNET_RECLAIM_Ticket *ticket,
232 const struct GNUNET_RECLAIM_PresentationList *presentations)
233{
234 char *ticket_str;
235
236 reclaim_op = NULL;
237 if (NULL != ticket)
238 {
239 ticket_str =
240 GNUNET_STRINGS_data_to_string_alloc (ticket,
241 sizeof(
242 struct GNUNET_RECLAIM_Ticket));
243 printf ("%s\n", ticket_str);
244 GNUNET_free (ticket_str);
245 }
246 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
247}
248
249
250static void
251store_cont (void *cls, int32_t success, const char *emsg)
252{
253 reclaim_op = NULL;
254 if (GNUNET_SYSERR == success)
255 {
256 fprintf (stderr, "%s\n", emsg);
257 }
258 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
259}
260
261
262static void
263process_attrs (void *cls,
264 const struct GNUNET_IDENTITY_PublicKey *identity,
265 const struct GNUNET_RECLAIM_Attribute *attr,
266 const struct GNUNET_RECLAIM_Presentation *presentation)
267{
268 char *value_str;
269 char *id;
270 const char *attr_type;
271
272 if (NULL == identity)
273 {
274 reclaim_op = NULL;
275 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
276 return;
277 }
278 if (NULL == attr)
279 {
280 ret = 1;
281 return;
282 }
283 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
284 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
285 value_str = NULL;
286 if (NULL == presentation)
287 {
288 value_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
289 attr->data,
290 attr->data_size);
291 }
292 else
293 {
294 struct GNUNET_RECLAIM_AttributeListEntry *ale;
295 struct GNUNET_RECLAIM_AttributeList *al
296 = GNUNET_RECLAIM_presentation_get_attributes (presentation);
297
298 for (ale = al->list_head; NULL != ale; ale = ale->next)
299 {
300 if (0 != strncmp (attr->data, ale->attribute->name, attr->data_size))
301 continue;
302 value_str
303 = GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
304 ale->attribute->data,
305 ale->attribute->data_size);
306 break;
307 }
308 }
309 fprintf (stdout,
310 "Name: %s; Value: %s (%s); Flag %u; ID: %s %s\n",
311 attr->name,
312 (NULL != value_str) ? value_str : "???",
313 attr_type,
314 attr->flag,
315 id,
316 (NULL == presentation) ? "" : "(ATTESTED)");
317 GNUNET_free (value_str);
318 GNUNET_free (id);
319}
320
321
322static void
323ticket_iter_err (void *cls)
324{
325 ticket_iterator = NULL;
326 fprintf (stderr, "Failed to iterate over tickets\n");
327 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
328}
329
330
331static void
332ticket_iter_fin (void *cls)
333{
334 ticket_iterator = NULL;
335 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
336}
337
338
339static void
340ticket_iter (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
341{
342 char *aud;
343 char *ref;
344 char *tkt;
345
346 aud =
347 GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
348 sizeof(struct
349 GNUNET_IDENTITY_PublicKey));
350 ref = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
351 tkt =
352 GNUNET_STRINGS_data_to_string_alloc (ticket,
353 sizeof(struct GNUNET_RECLAIM_Ticket));
354 fprintf (stdout, "Ticket: %s | ID: %s | Audience: %s\n", tkt, ref, aud);
355 GNUNET_free (aud);
356 GNUNET_free (ref);
357 GNUNET_free (tkt);
358 GNUNET_RECLAIM_ticket_iteration_next (ticket_iterator);
359}
360
361
362static void
363iter_error (void *cls)
364{
365 attr_iterator = NULL;
366 cred_iterator = NULL;
367 fprintf (stderr, "Failed\n");
368
369 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
370}
371
372
373static void
374timeout_task (void *cls)
375{
376 timeout = NULL;
377 ret = 1;
378 fprintf (stderr, "Timeout\n");
379 if (NULL == cleanup_task)
380 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
381}
382
383
384static void
385process_rvk (void *cls, int success, const char *msg)
386{
387 reclaim_op = NULL;
388 if (GNUNET_OK != success)
389 {
390 fprintf (stderr, "Revocation failed.\n");
391 ret = 1;
392 }
393 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
394}
395
396
397static void
398process_delete (void *cls, int success, const char *msg)
399{
400 reclaim_op = NULL;
401 if (GNUNET_OK != success)
402 {
403 fprintf (stderr, "Deletion failed.\n");
404 ret = 1;
405 }
406 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
407}
408
409
410static void
411iter_finished (void *cls)
412{
413 char *data;
414 size_t data_size;
415 int type;
416
417 attr_iterator = NULL;
418 if (list)
419 {
420 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
421 return;
422 }
423
424 if (issue_attrs)
425 {
426 reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
427 pkey,
428 &rp_key,
429 attr_list,
430 &ticket_issue_cb,
431 NULL);
432 return;
433 }
434 if (consume_ticket)
435 {
436 reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
437 pkey,
438 &ticket,
439 &process_attrs,
440 NULL);
441 timeout = GNUNET_SCHEDULER_add_delayed (
442 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
443 &timeout_task,
444 NULL);
445 return;
446 }
447 if (revoke_ticket)
448 {
449 reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
450 pkey,
451 &ticket,
452 &process_rvk,
453 NULL);
454 return;
455 }
456 if (attr_delete)
457 {
458 if (NULL == attr_to_delete)
459 {
460 fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
461 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
462 return;
463 }
464 reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle,
465 pkey,
466 attr_to_delete,
467 &process_delete,
468 NULL);
469 return;
470 }
471 if (attr_name)
472 {
473 if (NULL == type_str)
474 type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
475 else
476 type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
477
478 GNUNET_assert (GNUNET_SYSERR !=
479 GNUNET_RECLAIM_attribute_string_to_value (type,
480 attr_value,
481 (void **) &data,
482 &data_size));
483 if (NULL != claim)
484 {
485 claim->type = type;
486 claim->data = data;
487 claim->data_size = data_size;
488 }
489 else
490 {
491 claim =
492 GNUNET_RECLAIM_attribute_new (attr_name, NULL, type, data, data_size);
493 }
494 if (NULL != credential_id)
495 {
496 claim->credential = credential;
497 }
498 reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
499 pkey,
500 claim,
501 &exp_interval,
502 &store_cont,
503 NULL);
504 GNUNET_free (data);
505 GNUNET_free (claim);
506 return;
507 }
508 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
509}
510
511
512static void
513iter_cb (void *cls,
514 const struct GNUNET_IDENTITY_PublicKey *identity,
515 const struct GNUNET_RECLAIM_Attribute *attr)
516{
517 struct GNUNET_RECLAIM_AttributeListEntry *le;
518 char *attrs_tmp;
519 char *attr_str;
520 char *label;
521 char *id;
522 const char *attr_type;
523
524 if ((NULL != attr_name) && (NULL != claim))
525 {
526 if (0 == strcasecmp (attr_name, attr->name))
527 {
528 claim = GNUNET_RECLAIM_attribute_new (attr->name,
529 &attr->credential,
530 attr->type,
531 attr->data,
532 attr->data_size);
533 }
534 }
535 else if (issue_attrs)
536 {
537 attrs_tmp = GNUNET_strdup (issue_attrs);
538 attr_str = strtok (attrs_tmp, ",");
539 while (NULL != attr_str)
540 {
541 if (0 != strcasecmp (attr_str, attr->name))
542 {
543 attr_str = strtok (NULL, ",");
544 continue;
545 }
546 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
547 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
548 &attr->credential,
549 attr->type,
550 attr->data,
551 attr->data_size);
552 le->attribute->flag = attr->flag;
553 le->attribute->id = attr->id;
554 GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
555 attr_list->list_tail,
556 le);
557 break;
558 }
559 GNUNET_free (attrs_tmp);
560 }
561 else if (attr_delete && (NULL == attr_to_delete))
562 {
563 label = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
564 if (0 == strcasecmp (attr_delete, label))
565 {
566 attr_to_delete = GNUNET_RECLAIM_attribute_new (attr->name,
567 &attr->credential,
568 attr->type,
569 attr->data,
570 attr->data_size);
571 attr_to_delete->id = attr->id;
572 }
573 GNUNET_free (label);
574 }
575 else if (list)
576 {
577 attr_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
578 attr->data,
579 attr->data_size);
580 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
581 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
582 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->credential))
583 {
584 fprintf (stdout,
585 "%s: ``%s'' (%s); ID: %s\n",
586 attr->name,
587 attr_str,
588 attr_type,
589 id);
590 }
591 else
592 {
593 char *cred_id =
594 GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
595 sizeof(attr->credential));
596 fprintf (stdout,
597 "%s: ``%s'' in credential presentation `%s' (%s); ID: %s\n",
598 attr->name,
599 attr_str,
600 cred_id,
601 attr_type,
602 id);
603 GNUNET_free (cred_id);
604
605 }
606 GNUNET_free (id);
607 }
608 GNUNET_RECLAIM_get_attributes_next (attr_iterator);
609}
610
611
612static void
613cred_iter_finished (void *cls)
614{
615 cred_iterator = NULL;
616
617 // Add new credential
618 if ((NULL != credential_name) &&
619 (NULL != attr_value))
620 {
621 enum GNUNET_RECLAIM_CredentialType ctype =
622 GNUNET_RECLAIM_credential_typename_to_number (credential_type);
623 struct GNUNET_RECLAIM_Credential *credential =
624 GNUNET_RECLAIM_credential_new (credential_name,
625 ctype,
626 attr_value,
627 strlen (attr_value));
628 reclaim_op = GNUNET_RECLAIM_credential_store (reclaim_handle,
629 pkey,
630 credential,
631 &exp_interval,
632 store_cont,
633 NULL);
634 return;
635
636 }
637 if (list_credentials)
638 {
639 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
640 return;
641 }
642 attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
643 pkey,
644 &iter_error,
645 NULL,
646 &iter_cb,
647 NULL,
648 &iter_finished,
649 NULL);
650
651}
652
653
654static void
655cred_iter_cb (void *cls,
656 const struct GNUNET_IDENTITY_PublicKey *identity,
657 const struct GNUNET_RECLAIM_Credential *cred)
658{
659 char *cred_str;
660 char *attr_str;
661 char *id;
662 const char *cred_type;
663 struct GNUNET_RECLAIM_AttributeListEntry *ale;
664
665 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&credential,
666 &cred->id))
667 credential_exists = GNUNET_YES;
668 if (list_credentials)
669 {
670 cred_str = GNUNET_RECLAIM_credential_value_to_string (cred->type,
671 cred->data,
672 cred->data_size);
673 cred_type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
674 id = GNUNET_STRINGS_data_to_string_alloc (&cred->id, sizeof(cred->id));
675 fprintf (stdout,
676 "%s: ``%s'' (%s); ID: %s\n",
677 cred->name,
678 cred_str,
679 cred_type,
680 id);
681 struct GNUNET_RECLAIM_AttributeList *attrs =
682 GNUNET_RECLAIM_credential_get_attributes (cred);
683 if (NULL != attrs)
684 {
685 fprintf (stdout,
686 "\t Attributes:\n");
687 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
688 {
689 attr_str = GNUNET_RECLAIM_attribute_value_to_string (
690 ale->attribute->type,
691 ale->attribute->data,
692 ale->attribute->data_size);
693 fprintf (stdout,
694 "\t %s: %s\n", ale->attribute->name, attr_str);
695 GNUNET_free (attr_str);
696 }
697 GNUNET_RECLAIM_attribute_list_destroy (attrs);
698 }
699 GNUNET_free (id);
700 }
701 GNUNET_RECLAIM_get_credentials_next (cred_iterator);
702}
703
704
705static void
706start_process ()
707{
708 if (NULL == pkey)
709 {
710 fprintf (stderr, "Ego %s not found\n", ego_name);
711 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
712 return;
713 }
714 if (NULL == credential_type)
715 credential_type = GNUNET_strdup ("JWT");
716 credential = GNUNET_RECLAIM_ID_ZERO;
717 if (NULL != credential_id)
718 GNUNET_STRINGS_string_to_data (credential_id,
719 strlen (credential_id),
720 &credential, sizeof(credential));
721 credential_exists = GNUNET_NO;
722 if (list_tickets)
723 {
724 ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (reclaim_handle,
725 pkey,
726 &ticket_iter_err,
727 NULL,
728 &ticket_iter,
729 NULL,
730 &ticket_iter_fin,
731 NULL);
732 return;
733 }
734
735 if ((NULL != rp) &&
736 (GNUNET_OK !=
737 GNUNET_IDENTITY_public_key_from_string (rp, &rp_key)) )
738 {
739 fprintf (stderr, "%s is not a public key!\n", rp);
740 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
741 return;
742 }
743 if (NULL != consume_ticket)
744 GNUNET_STRINGS_string_to_data (consume_ticket,
745 strlen (consume_ticket),
746 &ticket,
747 sizeof(struct GNUNET_RECLAIM_Ticket));
748 if (NULL != revoke_ticket)
749 GNUNET_STRINGS_string_to_data (revoke_ticket,
750 strlen (revoke_ticket),
751 &ticket,
752 sizeof(struct GNUNET_RECLAIM_Ticket));
753
754 attr_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
755 claim = NULL;
756 cred_iterator = GNUNET_RECLAIM_get_credentials_start (reclaim_handle,
757 pkey,
758 &iter_error,
759 NULL,
760 &cred_iter_cb,
761 NULL,
762 &cred_iter_finished,
763 NULL);
764
765}
766
767
768static int init = GNUNET_YES;
769
770static void
771ego_cb (void *cls,
772 struct GNUNET_IDENTITY_Ego *ego,
773 void **ctx,
774 const char *name)
775{
776 if (NULL == name)
777 {
778 if (GNUNET_YES == init)
779 {
780 init = GNUNET_NO;
781 start_process ();
782 }
783 return;
784 }
785 if (0 != strcmp (name, ego_name))
786 return;
787 pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
788}
789
790
791static void
792run (void *cls,
793 char *const *args,
794 const char *cfgfile,
795 const struct GNUNET_CONFIGURATION_Handle *c)
796{
797 ret = 0;
798 if (NULL == ego_name)
799 {
800 ret = 1;
801 fprintf (stderr, _ ("Ego is required\n"));
802 return;
803 }
804
805 if ((NULL == attr_value) && (NULL != attr_name))
806 {
807 ret = 1;
808 fprintf (stderr, _ ("Attribute value missing!\n"));
809 return;
810 }
811
812 if ((NULL == rp) && (NULL != issue_attrs))
813 {
814 ret = 1;
815 fprintf (stderr, _ ("Requesting party key is required!\n"));
816 return;
817 }
818
819 reclaim_handle = GNUNET_RECLAIM_connect (c);
820 // Get Ego
821 identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, NULL);
822}
823
824
825int
826main (int argc, char *const argv[])
827{
828 exp_interval = GNUNET_TIME_UNIT_HOURS;
829 struct GNUNET_GETOPT_CommandLineOption options[] = {
830 GNUNET_GETOPT_option_string ('a',
831 "add",
832 "NAME",
833 gettext_noop ("Add an attribute NAME"),
834 &attr_name),
835 GNUNET_GETOPT_option_string ('d',
836 "delete",
837 "ID",
838 gettext_noop ("Delete the attribute with ID"),
839 &attr_delete),
840 GNUNET_GETOPT_option_string ('V',
841 "value",
842 "VALUE",
843 gettext_noop ("The attribute VALUE"),
844 &attr_value),
845 GNUNET_GETOPT_option_string ('e',
846 "ego",
847 "EGO",
848 gettext_noop ("The EGO to use"),
849 &ego_name),
850 GNUNET_GETOPT_option_string ('r',
851 "rp",
852 "RP",
853 gettext_noop (
854 "Specify the relying party for issue"),
855 &rp),
856 GNUNET_GETOPT_option_flag ('D',
857 "dump",
858 gettext_noop ("List attributes for EGO"),
859 &list),
860 GNUNET_GETOPT_option_flag ('A',
861 "credentials",
862 gettext_noop ("List credentials for EGO"),
863 &list_credentials),
864 GNUNET_GETOPT_option_string ('I',
865 "credential-id",
866 "CREDENTIAL_ID",
867 gettext_noop (
868 "Credential to use for attribute"),
869 &credential_id),
870 GNUNET_GETOPT_option_string ('N',
871 "credential-name",
872 "NAME",
873 gettext_noop ("Credential name"),
874 &credential_name),
875 GNUNET_GETOPT_option_string ('i',
876 "issue",
877 "A1,A2,...",
878 gettext_noop (
879 "Issue a ticket for a set of attributes separated by comma"),
880 &issue_attrs),
881 GNUNET_GETOPT_option_string ('C',
882 "consume",
883 "TICKET",
884 gettext_noop ("Consume a ticket"),
885 &consume_ticket),
886 GNUNET_GETOPT_option_string ('R',
887 "revoke",
888 "TICKET",
889 gettext_noop ("Revoke a ticket"),
890 &revoke_ticket),
891 GNUNET_GETOPT_option_string ('t',
892 "type",
893 "TYPE",
894 gettext_noop ("Type of attribute"),
895 &type_str),
896 GNUNET_GETOPT_option_string ('u',
897 "credential-type",
898 "TYPE",
899 gettext_noop ("Type of credential"),
900 &credential_type),
901 GNUNET_GETOPT_option_flag ('T',
902 "tickets",
903 gettext_noop ("List tickets of ego"),
904 &list_tickets),
905 GNUNET_GETOPT_option_relative_time ('E',
906 "expiration",
907 "INTERVAL",
908 gettext_noop (
909 "Expiration interval of the attribute"),
910 &exp_interval),
911
912 GNUNET_GETOPT_OPTION_END
913 };
914 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
915 argv,
916 "gnunet-reclaim",
917 _ ("re:claimID command line tool"),
918 options,
919 &run,
920 NULL))
921 return 1;
922 else
923 return ret;
924}
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
deleted file mode 100644
index 5614f05db..000000000
--- a/src/reclaim/gnunet-service-reclaim.c
+++ /dev/null
@@ -1,2342 +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 * @file src/reclaim/gnunet-service-reclaim.c
23 * @brief reclaim Service
24 *
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet-service-reclaim_tickets.h"
29#include "gnunet_constants.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "gnunet_protocols.h"
32#include "gnunet_reclaim_lib.h"
33#include "gnunet_reclaim_service.h"
34#include "gnunet_signatures.h"
35#include "reclaim.h"
36
37
38/**
39 * Namestore handle
40 */
41static struct GNUNET_NAMESTORE_Handle *nsh;
42
43/**
44 * Timeout task
45 */
46static struct GNUNET_SCHEDULER_Task *timeout_task;
47
48/**
49 * Our configuration.
50 */
51static const struct GNUNET_CONFIGURATION_Handle *cfg;
52
53/**
54 * An idp client
55 */
56struct IdpClient;
57
58/**
59 * A ticket iteration operation.
60 */
61struct TicketIteration
62{
63 /**
64 * DLL
65 */
66 struct TicketIteration *next;
67
68 /**
69 * DLL
70 */
71 struct TicketIteration *prev;
72
73 /**
74 * Client which intiated this zone iteration
75 */
76 struct IdpClient *client;
77
78 /**
79 * The operation id fot the iteration in the response for the client
80 */
81 uint32_t r_id;
82
83 /**
84 * The ticket iterator
85 */
86 struct RECLAIM_TICKETS_Iterator *iter;
87};
88
89
90/**
91 * An attribute iteration operation.
92 */
93struct Iterator
94{
95 /**
96 * Next element in the DLL
97 */
98 struct Iterator *next;
99
100 /**
101 * Previous element in the DLL
102 */
103 struct Iterator *prev;
104
105 /**
106 * IDP client which intiated this zone iteration
107 */
108 struct IdpClient *client;
109
110 /**
111 * Key of the zone we are iterating over.
112 */
113 struct GNUNET_IDENTITY_PrivateKey identity;
114
115 /**
116 * Namestore iterator
117 */
118 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
119
120 /**
121 * The operation id fot the zone iteration in the response for the client
122 */
123 uint32_t request_id;
124
125 /**
126 * Context
127 */
128 void *ctx;
129};
130
131
132/**
133 * An idp client
134 */
135struct IdpClient
136{
137 /**
138 * DLL
139 */
140 struct IdpClient *prev;
141
142 /**
143 * DLL
144 */
145 struct IdpClient *next;
146
147 /**
148 * The client
149 */
150 struct GNUNET_SERVICE_Client *client;
151
152 /**
153 * Message queue for transmission to @e client
154 */
155 struct GNUNET_MQ_Handle *mq;
156
157 /**
158 * Head of the DLL of
159 * Attribute iteration operations in
160 * progress initiated by this client
161 */
162 struct Iterator *attr_iter_head;
163
164 /**
165 * Tail of the DLL of
166 * Attribute iteration operations
167 * in progress initiated by this client
168 */
169 struct Iterator *attr_iter_tail;
170
171 /**
172 * Head of the DLL of
173 * Credential iteration operations in
174 * progress initiated by this client
175 */
176 struct Iterator *cred_iter_head;
177
178 /**
179 * Tail of the DLL of
180 * Credential iteration operations
181 * in progress initiated by this client
182 */
183 struct Iterator *cred_iter_tail;
184
185 /**
186 * Head of DLL of ticket iteration ops
187 */
188 struct TicketIteration *ticket_iter_head;
189
190 /**
191 * Tail of DLL of ticket iteration ops
192 */
193 struct TicketIteration *ticket_iter_tail;
194
195 /**
196 * Head of DLL of ticket revocation ops
197 */
198 struct TicketRevocationOperation *revoke_op_head;
199
200 /**
201 * Tail of DLL of ticket revocation ops
202 */
203 struct TicketRevocationOperation *revoke_op_tail;
204
205 /**
206 * Head of DLL of ticket issue ops
207 */
208 struct TicketIssueOperation *issue_op_head;
209
210 /**
211 * Tail of DLL of ticket issue ops
212 */
213 struct TicketIssueOperation *issue_op_tail;
214
215 /**
216 * Head of DLL of ticket consume ops
217 */
218 struct ConsumeTicketOperation *consume_op_head;
219
220 /**
221 * Tail of DLL of ticket consume ops
222 */
223 struct ConsumeTicketOperation *consume_op_tail;
224
225 /**
226 * Head of DLL of attribute store ops
227 */
228 struct AttributeStoreHandle *store_op_head;
229
230 /**
231 * Tail of DLL of attribute store ops
232 */
233 struct AttributeStoreHandle *store_op_tail;
234 /**
235 * Head of DLL of attribute delete ops
236 */
237 struct AttributeDeleteHandle *delete_op_head;
238
239 /**
240 * Tail of DLL of attribute delete ops
241 */
242 struct AttributeDeleteHandle *delete_op_tail;
243};
244
245
246/**
247 * Handle for attribute deletion request
248 */
249struct AttributeDeleteHandle
250{
251 /**
252 * DLL
253 */
254 struct AttributeDeleteHandle *next;
255
256 /**
257 * DLL
258 */
259 struct AttributeDeleteHandle *prev;
260
261 /**
262 * Client connection
263 */
264 struct IdpClient *client;
265
266 /**
267 * Identity
268 */
269 struct GNUNET_IDENTITY_PrivateKey identity;
270
271
272 /**
273 * QueueEntry
274 */
275 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
276
277 /**
278 * Iterator
279 */
280 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
281
282 /**
283 * The attribute to delete
284 */
285 struct GNUNET_RECLAIM_Attribute *claim;
286
287 /**
288 * The credential to delete
289 */
290 struct GNUNET_RECLAIM_Credential *credential;
291
292 /**
293 * Tickets to update
294 */
295 struct TicketRecordsEntry *tickets_to_update_head;
296
297 /**
298 * Tickets to update
299 */
300 struct TicketRecordsEntry *tickets_to_update_tail;
301
302 /**
303 * Attribute label
304 */
305 char *label;
306
307 /**
308 * request id
309 */
310 uint32_t r_id;
311};
312
313
314/**
315 * Handle for attribute store request
316 */
317struct AttributeStoreHandle
318{
319 /**
320 * DLL
321 */
322 struct AttributeStoreHandle *next;
323
324 /**
325 * DLL
326 */
327 struct AttributeStoreHandle *prev;
328
329 /**
330 * Client connection
331 */
332 struct IdpClient *client;
333
334 /**
335 * Identity
336 */
337 struct GNUNET_IDENTITY_PrivateKey identity;
338
339 /**
340 * Identity pubkey
341 */
342 struct GNUNET_IDENTITY_PublicKey identity_pkey;
343
344 /**
345 * QueueEntry
346 */
347 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
348
349 /**
350 * The attribute to store
351 */
352 struct GNUNET_RECLAIM_Attribute *claim;
353
354 /**
355 * The credential to store
356 */
357 struct GNUNET_RECLAIM_Credential *credential;
358
359 /**
360 * The attribute expiration interval
361 */
362 struct GNUNET_TIME_Relative exp;
363
364 /**
365 * request id
366 */
367 uint32_t r_id;
368};
369
370
371/**
372 * Handle for ticket consume request
373 */
374struct ConsumeTicketOperation
375{
376 /**
377 * DLL
378 */
379 struct ConsumeTicketOperation *next;
380
381 /**
382 * DLL
383 */
384 struct ConsumeTicketOperation *prev;
385
386 /**
387 * Client connection
388 */
389 struct IdpClient *client;
390
391 /**
392 * request id
393 */
394 uint32_t r_id;
395
396 /**
397 * Ticket consume handle
398 */
399 struct RECLAIM_TICKETS_ConsumeHandle *ch;
400};
401
402
403/**
404 * Ticket revocation request handle
405 */
406struct TicketRevocationOperation
407{
408 /**
409 * DLL
410 */
411 struct TicketRevocationOperation *prev;
412
413 /**
414 * DLL
415 */
416 struct TicketRevocationOperation *next;
417
418 /**
419 * Client connection
420 */
421 struct IdpClient *client;
422
423 /**
424 * Revocation handle
425 */
426 struct RECLAIM_TICKETS_RevokeHandle *rh;
427
428 /**
429 * request id
430 */
431 uint32_t r_id;
432};
433
434
435/**
436 * Ticket issue operation handle
437 */
438struct TicketIssueOperation
439{
440 /**
441 * DLL
442 */
443 struct TicketIssueOperation *prev;
444
445 /**
446 * DLL
447 */
448 struct TicketIssueOperation *next;
449
450 /**
451 * Client connection
452 */
453 struct IdpClient *client;
454
455 /**
456 * request id
457 */
458 uint32_t r_id;
459};
460
461
462/**
463 * Client list
464 */
465static struct IdpClient *client_list_head = NULL;
466
467/**
468 * Client list
469 */
470static struct IdpClient *client_list_tail = NULL;
471
472
473/**
474 * Cleanup attribute delete handle
475 *
476 * @param adh the attribute to cleanup
477 */
478static void
479cleanup_adh (struct AttributeDeleteHandle *adh)
480{
481 struct TicketRecordsEntry *le;
482
483 if (NULL != adh->ns_it)
484 GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
485 if (NULL != adh->ns_qe)
486 GNUNET_NAMESTORE_cancel (adh->ns_qe);
487 if (NULL != adh->label)
488 GNUNET_free (adh->label);
489 if (NULL != adh->claim)
490 GNUNET_free (adh->claim);
491 if (NULL != adh->credential)
492 GNUNET_free (adh->credential);
493 while (NULL != (le = adh->tickets_to_update_head))
494 {
495 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
496 adh->tickets_to_update_tail,
497 le);
498 if (NULL != le->label)
499 GNUNET_free (le->label);
500 if (NULL != le->data)
501 GNUNET_free (le->data);
502 GNUNET_free (le);
503 }
504 GNUNET_free (adh);
505}
506
507
508/**
509 * Cleanup attribute store handle
510 *
511 * @param handle handle to clean up
512 */
513static void
514cleanup_as_handle (struct AttributeStoreHandle *ash)
515{
516 if (NULL != ash->ns_qe)
517 GNUNET_NAMESTORE_cancel (ash->ns_qe);
518 if (NULL != ash->claim)
519 GNUNET_free (ash->claim);
520 if (NULL != ash->credential)
521 GNUNET_free (ash->credential);
522 GNUNET_free (ash);
523}
524
525
526/**
527 * Cleanup client
528 *
529 * @param idp the client to clean up
530 */
531static void
532cleanup_client (struct IdpClient *idp)
533{
534 struct Iterator *ai;
535 struct TicketIteration *ti;
536 struct TicketRevocationOperation *rop;
537 struct TicketIssueOperation *iss;
538 struct ConsumeTicketOperation *ct;
539 struct AttributeStoreHandle *as;
540 struct AttributeDeleteHandle *adh;
541
542 while (NULL != (iss = idp->issue_op_head))
543 {
544 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
545 GNUNET_free (iss);
546 }
547 while (NULL != (ct = idp->consume_op_head))
548 {
549 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
550 idp->consume_op_tail,
551 ct);
552 if (NULL != ct->ch)
553 RECLAIM_TICKETS_consume_cancel (ct->ch);
554 GNUNET_free (ct);
555 }
556 while (NULL != (as = idp->store_op_head))
557 {
558 GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
559 cleanup_as_handle (as);
560 }
561 while (NULL != (adh = idp->delete_op_head))
562 {
563 GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
564 cleanup_adh (adh);
565 }
566
567 while (NULL != (ai = idp->attr_iter_head))
568 {
569 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
570 GNUNET_free (ai);
571 }
572 while (NULL != (ai = idp->cred_iter_head))
573 {
574 GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
575 ai);
576 GNUNET_free (ai);
577 }
578
579 while (NULL != (rop = idp->revoke_op_head))
580 {
581 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
582 if (NULL != rop->rh)
583 RECLAIM_TICKETS_revoke_cancel (rop->rh);
584 GNUNET_free (rop);
585 }
586 while (NULL != (ti = idp->ticket_iter_head))
587 {
588 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
589 idp->ticket_iter_tail,
590 ti);
591 if (NULL != ti->iter)
592 RECLAIM_TICKETS_iteration_stop (ti->iter);
593 GNUNET_free (ti);
594 }
595 GNUNET_free (idp);
596}
597
598
599/**
600 * Cleanup task
601 */
602static void
603cleanup ()
604{
605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
606
607 RECLAIM_TICKETS_deinit ();
608 if (NULL != timeout_task)
609 GNUNET_SCHEDULER_cancel (timeout_task);
610 if (NULL != nsh)
611 GNUNET_NAMESTORE_disconnect (nsh);
612}
613
614
615/**
616 * Shutdown task
617 *
618 * @param cls NULL
619 */
620static void
621do_shutdown (void *cls)
622{
623 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
624 cleanup ();
625}
626
627
628/**
629 * Sends a ticket result message to the client
630 *
631 * @param client the client to send to
632 * @param r_id the request message ID to reply to
633 * @param ticket the ticket to include (may be NULL)
634 * @param success the success status of the request
635 */
636static void
637send_ticket_result (const struct IdpClient *client,
638 uint32_t r_id,
639 const struct GNUNET_RECLAIM_Ticket *ticket,
640 const struct GNUNET_RECLAIM_PresentationList *presentations,
641 uint32_t success)
642{
643 struct TicketResultMessage *irm;
644 struct GNUNET_MQ_Envelope *env;
645 size_t pres_len = 0;
646
647 if (NULL != presentations)
648 {
649 pres_len =
650 GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
651 }
652 env = GNUNET_MQ_msg_extra (irm,
653 pres_len,
654 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
655 if (NULL != ticket)
656 {
657 irm->ticket = *ticket;
658 }
659 // TODO add success member
660 irm->id = htonl (r_id);
661 irm->presentations_len = htons (pres_len);
662 if (NULL != presentations)
663 {
664 GNUNET_RECLAIM_presentation_list_serialize (presentations,
665 (char*) &irm[1]);
666 }
667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
668 GNUNET_MQ_send (client->mq, env);
669}
670
671
672/**
673 * Issue ticket result
674 *
675 * @param cls out ticket issue operation handle
676 * @param ticket the issued ticket
677 * @param presentations newly created credential presentations (NULL on error)
678 * @param success issue success status (GNUNET_OK if successful)
679 * @param emsg error message (NULL of success is GNUNET_OK)
680 */
681static void
682issue_ticket_result_cb (void *cls,
683 struct GNUNET_RECLAIM_Ticket *ticket,
684 struct GNUNET_RECLAIM_PresentationList *presentations,
685 int32_t success,
686 const char *emsg)
687{
688 struct TicketIssueOperation *tio = cls;
689
690 if (GNUNET_OK != success)
691 {
692 send_ticket_result (tio->client, tio->r_id, NULL, NULL, GNUNET_SYSERR);
693 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
694 tio->client->issue_op_tail,
695 tio);
696 GNUNET_free (tio);
697 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
698 return;
699 }
700 send_ticket_result (tio->client, tio->r_id,
701 ticket, presentations, GNUNET_SYSERR);
702 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
703 tio->client->issue_op_tail,
704 tio);
705 GNUNET_free (tio);
706}
707
708
709/**
710 * Check issue ticket message
711 *
712 * @cls unused
713 * @im message to check
714 * @return GNUNET_OK if message is ok
715 */
716static int
717check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
718{
719 uint16_t size;
720
721 size = ntohs (im->header.size);
722 if (size <= sizeof(struct IssueTicketMessage))
723 {
724 GNUNET_break (0);
725 return GNUNET_SYSERR;
726 }
727 return GNUNET_OK;
728}
729
730
731/**
732 * Handle ticket issue message
733 *
734 * @param cls our client
735 * @param im the message
736 */
737static void
738handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
739{
740 struct TicketIssueOperation *tio;
741 struct IdpClient *idp = cls;
742 struct GNUNET_RECLAIM_AttributeList *attrs;
743 struct GNUNET_RECLAIM_AttributeListEntry *le;
744 size_t attrs_len;
745
746 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
747 tio = GNUNET_new (struct TicketIssueOperation);
748 attrs_len = ntohs (im->attr_len);
749 attrs = GNUNET_RECLAIM_attribute_list_deserialize ((char *) &im[1],
750 attrs_len);
751 for (le = attrs->list_head; NULL != le; le = le->next)
752 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
753 "List entry: %s\n", le->attribute->name);
754
755 tio->r_id = ntohl (im->id);
756 tio->client = idp;
757 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
758 RECLAIM_TICKETS_issue (&im->identity,
759 attrs,
760 &im->rp,
761 &issue_ticket_result_cb,
762 tio);
763 GNUNET_SERVICE_client_continue (idp->client);
764 GNUNET_RECLAIM_attribute_list_destroy (attrs);
765}
766
767
768/**********************************************************
769* Revocation
770**********************************************************/
771
772/**
773 * Handles revocation result
774 *
775 * @param cls our revocation operation handle
776 * @param success revocation result (GNUNET_OK if successful)
777 */
778static void
779revoke_result_cb (void *cls, int32_t success)
780{
781 struct TicketRevocationOperation *rop = cls;
782 struct GNUNET_MQ_Envelope *env;
783 struct RevokeTicketResultMessage *trm;
784
785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
786 "Sending REVOKE_TICKET_RESULT message\n");
787 rop->rh = NULL;
788 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
789 trm->id = htonl (rop->r_id);
790 trm->success = htonl (success);
791 GNUNET_MQ_send (rop->client->mq, env);
792 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
793 rop->client->revoke_op_tail,
794 rop);
795 GNUNET_free (rop);
796}
797
798
799/**
800 * Check revocation message format
801 *
802 * @param cls unused
803 * @param im the message to check
804 * @return GNUNET_OK if message is ok
805 */
806static int
807check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
808{
809 uint16_t size;
810
811 size = ntohs (im->header.size);
812 if (size != sizeof(struct RevokeTicketMessage))
813 {
814 GNUNET_break (0);
815 return GNUNET_SYSERR;
816 }
817 return GNUNET_OK;
818}
819
820
821/**
822 * Handle a revocation message to a ticket.
823 *
824 * @param cls our client
825 * @param rm the message to handle
826 */
827static void
828handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
829{
830 struct TicketRevocationOperation *rop;
831 struct IdpClient *idp = cls;
832
833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
834 rop = GNUNET_new (struct TicketRevocationOperation);
835 rop->r_id = ntohl (rm->id);
836 rop->client = idp;
837 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
838 rop->rh
839 = RECLAIM_TICKETS_revoke (&rm->ticket, &rm->identity, &revoke_result_cb,
840 rop);
841 GNUNET_SERVICE_client_continue (idp->client);
842}
843
844
845/**
846 * Handle a ticket consume result
847 *
848 * @param cls our consume ticket operation handle
849 * @param identity the attribute authority
850 * @param attrs the attribute/claim list
851 * @param success GNUNET_OK if successful
852 * @param emsg error message (NULL if success=GNUNET_OK)
853 */
854static void
855consume_result_cb (void *cls,
856 const struct GNUNET_IDENTITY_PublicKey *identity,
857 const struct GNUNET_RECLAIM_AttributeList *attrs,
858 const struct GNUNET_RECLAIM_PresentationList *presentations,
859 int32_t success,
860 const char *emsg)
861{
862 struct ConsumeTicketOperation *cop = cls;
863 struct ConsumeTicketResultMessage *crm;
864 struct GNUNET_MQ_Envelope *env;
865 char *data_tmp;
866 size_t attrs_len = 0;
867 size_t pres_len = 0;
868
869 if (GNUNET_OK != success)
870 {
871 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
872 }
873 attrs_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
874 pres_len = GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
876 "Sending CONSUME_TICKET_RESULT message\n");
877 env = GNUNET_MQ_msg_extra (crm,
878 attrs_len + pres_len,
879 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
880 crm->id = htonl (cop->r_id);
881 crm->attrs_len = htons (attrs_len);
882 crm->presentations_len = htons (pres_len);
883 crm->identity = *identity;
884 crm->result = htonl (success);
885 data_tmp = (char *) &crm[1];
886 GNUNET_RECLAIM_attribute_list_serialize (attrs, data_tmp);
887 data_tmp += attrs_len;
888 GNUNET_RECLAIM_presentation_list_serialize (presentations, data_tmp);
889 GNUNET_MQ_send (cop->client->mq, env);
890 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
891 cop->client->consume_op_tail,
892 cop);
893 GNUNET_free (cop);
894}
895
896
897/**
898 * Check a consume ticket message
899 *
900 * @param cls unused
901 * @param cm the message to handle
902 */
903static int
904check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
905{
906 uint16_t size;
907
908 size = ntohs (cm->header.size);
909 if (size != sizeof(struct ConsumeTicketMessage))
910 {
911 GNUNET_break (0);
912 return GNUNET_SYSERR;
913 }
914 return GNUNET_OK;
915}
916
917
918/**
919 * Handle a consume ticket message
920 *
921 * @param cls our client handle
922 * @cm the message to handle
923 */
924static void
925handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
926{
927 struct ConsumeTicketOperation *cop;
928 struct IdpClient *idp = cls;
929
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
931 cop = GNUNET_new (struct ConsumeTicketOperation);
932 cop->r_id = ntohl (cm->id);
933 cop->client = idp;
934 cop->ch
935 = RECLAIM_TICKETS_consume (&cm->identity, &cm->ticket, &consume_result_cb,
936 cop);
937 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
938 GNUNET_SERVICE_client_continue (idp->client);
939}
940
941
942/*****************************************
943* Attribute store
944*****************************************/
945
946
947/**
948 * Attribute store result handler
949 *
950 * @param cls our attribute store handle
951 * @param success GNUNET_OK if successful
952 * @param emsg error message (NULL if success=GNUNET_OK)
953 */
954static void
955attr_store_cont (void *cls, int32_t success, const char *emsg)
956{
957 struct AttributeStoreHandle *ash = cls;
958 struct GNUNET_MQ_Envelope *env;
959 struct SuccessResultMessage *acr_msg;
960
961 ash->ns_qe = NULL;
962 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
963 ash->client->store_op_tail,
964 ash);
965
966 if (GNUNET_SYSERR == success)
967 {
968 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
969 "Failed to store attribute %s\n",
970 emsg);
971 cleanup_as_handle (ash);
972 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
973 return;
974 }
975
976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
977 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
978 acr_msg->id = htonl (ash->r_id);
979 acr_msg->op_result = htonl (GNUNET_OK);
980 GNUNET_MQ_send (ash->client->mq, env);
981 cleanup_as_handle (ash);
982}
983
984
985/**
986 * Add a new attribute
987 *
988 * @param cls the AttributeStoreHandle
989 */
990static void
991attr_store_task (void *cls)
992{
993 struct AttributeStoreHandle *ash = cls;
994 struct GNUNET_GNSRECORD_Data rd[1];
995 char *buf;
996 char *label;
997 size_t buf_size;
998
999 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
1000 buf_size = GNUNET_RECLAIM_attribute_serialize_get_size (ash->claim);
1001 buf = GNUNET_malloc (buf_size);
1002 // Give the ash a new id if unset
1003 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->claim->id))
1004 GNUNET_RECLAIM_id_generate (&ash->claim->id);
1005 GNUNET_RECLAIM_attribute_serialize (ash->claim, buf);
1006 label
1007 = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id,
1008 sizeof (ash->claim->id));
1009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1010
1011 rd[0].data_size = buf_size;
1012 rd[0].data = buf;
1013 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE;
1014 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1015 rd[0].expiration_time = ash->exp.rel_value_us;
1016 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1017 &ash->identity,
1018 label,
1019 1,
1020 rd,
1021 &attr_store_cont,
1022 ash);
1023 GNUNET_free (buf);
1024 GNUNET_free (label);
1025}
1026
1027
1028/**
1029 * Check an attribute store message
1030 *
1031 * @param cls unused
1032 * @param sam the message to check
1033 */
1034static int
1035check_attribute_store_message (void *cls,
1036 const struct AttributeStoreMessage *sam)
1037{
1038 uint16_t size;
1039
1040 size = ntohs (sam->header.size);
1041 if (size <= sizeof(struct AttributeStoreMessage))
1042 {
1043 GNUNET_break (0);
1044 return GNUNET_SYSERR;
1045 }
1046 return GNUNET_OK;
1047}
1048
1049
1050/**
1051 * Handle an attribute store message
1052 *
1053 * @param cls our client
1054 * @param sam the message to handle
1055 */
1056static void
1057handle_attribute_store_message (void *cls,
1058 const struct AttributeStoreMessage *sam)
1059{
1060 struct AttributeStoreHandle *ash;
1061 struct IdpClient *idp = cls;
1062 size_t data_len;
1063
1064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1065
1066 data_len = ntohs (sam->attr_len);
1067
1068 ash = GNUNET_new (struct AttributeStoreHandle);
1069 GNUNET_RECLAIM_attribute_deserialize ((char *) &sam[1],
1070 data_len,
1071 &ash->claim);
1072
1073 ash->r_id = ntohl (sam->id);
1074 ash->identity = sam->identity;
1075 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1076 GNUNET_IDENTITY_key_get_public (&sam->identity, &ash->identity_pkey);
1077
1078 GNUNET_SERVICE_client_continue (idp->client);
1079 ash->client = idp;
1080 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1081 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1082}
1083
1084
1085/**
1086 * Credential store result handler
1087 *
1088 * @param cls our attribute store handle
1089 * @param success GNUNET_OK if successful
1090 * @param emsg error message (NULL if success=GNUNET_OK)
1091 */
1092static void
1093cred_store_cont (void *cls, int32_t success, const char *emsg)
1094{
1095 struct AttributeStoreHandle *ash = cls;
1096 struct GNUNET_MQ_Envelope *env;
1097 struct SuccessResultMessage *acr_msg;
1098
1099 ash->ns_qe = NULL;
1100 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1101 ash->client->store_op_tail,
1102 ash);
1103
1104 if (GNUNET_SYSERR == success)
1105 {
1106 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1107 "Failed to store credential: %s\n",
1108 emsg);
1109 cleanup_as_handle (ash);
1110 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1111 return;
1112 }
1113
1114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1115 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1116 acr_msg->id = htonl (ash->r_id);
1117 acr_msg->op_result = htonl (GNUNET_OK);
1118 GNUNET_MQ_send (ash->client->mq, env);
1119 cleanup_as_handle (ash);
1120}
1121
1122
1123/**
1124 * Error looking up potential credential. Abort.
1125 *
1126 * @param cls our attribute store handle
1127 */
1128static void
1129cred_error (void *cls)
1130{
1131 struct AttributeStoreHandle *ash = cls;
1132 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1133 "Failed to check for existing credential.\n");
1134 cleanup_as_handle (ash);
1135 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1136 return;
1137}
1138
1139
1140/**
1141* Check for existing record before storing credential
1142*
1143* @param cls our attribute store handle
1144* @param zone zone we are iterating
1145* @param label label of the records
1146* @param rd_count record count
1147* @param rd records
1148*/
1149static void
1150cred_add_cb (void *cls,
1151 const struct GNUNET_IDENTITY_PrivateKey *zone,
1152 const char *label,
1153 unsigned int rd_count,
1154 const struct GNUNET_GNSRECORD_Data *rd)
1155{
1156 struct AttributeStoreHandle *ash = cls;
1157 struct GNUNET_GNSRECORD_Data rd_new[1];
1158 char *buf;
1159 size_t buf_size;
1160
1161 buf_size = GNUNET_RECLAIM_credential_serialize_get_size (ash->credential);
1162 buf = GNUNET_malloc (buf_size);
1163 GNUNET_RECLAIM_credential_serialize (ash->credential, buf);
1164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1165 "Storing new credential under `%s'.\n",
1166 label);
1167 rd_new[0].data_size = buf_size;
1168 rd_new[0].data = buf;
1169 rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL;
1170 rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1171 rd_new[0].expiration_time = ash->exp.rel_value_us;
1172 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1173 &ash->identity,
1174 label,
1175 1,
1176 rd_new,
1177 &cred_store_cont,
1178 ash);
1179 GNUNET_free (buf);
1180 return;
1181}
1182
1183
1184/**
1185 * Add a new credential
1186 *
1187 * @param cls the AttributeStoreHandle
1188 */
1189static void
1190cred_store_task (void *cls)
1191{
1192 struct AttributeStoreHandle *ash = cls;
1193 char *label;
1194
1195 // Give the ash a new id if unset
1196 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->credential->id))
1197 GNUNET_RECLAIM_id_generate (&ash->credential->id);
1198 label = GNUNET_STRINGS_data_to_string_alloc (&ash->credential->id,
1199 sizeof (ash->credential->id));
1200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1201 "Looking up existing data under label `%s'\n", label);
1202 ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1203 &ash->identity,
1204 label,
1205 &cred_error,
1206 ash,
1207 &cred_add_cb,
1208 ash);
1209 GNUNET_free (label);
1210}
1211
1212
1213/**
1214 * Check an credential store message
1215 *
1216 * @param cls unused
1217 * @param sam the message to check
1218 */
1219static int
1220check_credential_store_message (void *cls,
1221 const struct AttributeStoreMessage *sam)
1222{
1223 uint16_t size;
1224
1225 size = ntohs (sam->header.size);
1226 if (size <= sizeof(struct AttributeStoreMessage))
1227 {
1228 GNUNET_break (0);
1229 return GNUNET_SYSERR;
1230 }
1231 return GNUNET_OK;
1232}
1233
1234
1235/**
1236* Handle a credential store message
1237*
1238* @param cls our client
1239* @param sam the message to handle
1240*/
1241static void
1242handle_credential_store_message (void *cls,
1243 const struct AttributeStoreMessage *sam)
1244{
1245 struct AttributeStoreHandle *ash;
1246 struct IdpClient *idp = cls;
1247 size_t data_len;
1248
1249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_STORE message\n");
1250
1251 data_len = ntohs (sam->attr_len);
1252
1253 ash = GNUNET_new (struct AttributeStoreHandle);
1254 ash->credential = GNUNET_RECLAIM_credential_deserialize ((char *) &sam[1],
1255 data_len);
1256
1257 ash->r_id = ntohl (sam->id);
1258 ash->identity = sam->identity;
1259 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1260 GNUNET_IDENTITY_key_get_public (&sam->identity, &ash->identity_pkey);
1261
1262 GNUNET_SERVICE_client_continue (idp->client);
1263 ash->client = idp;
1264 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1265 GNUNET_SCHEDULER_add_now (&cred_store_task, ash);
1266}
1267
1268
1269/**
1270 * Send a deletion success response
1271 *
1272 * @param adh our attribute deletion handle
1273 * @param success the success status
1274 */
1275static void
1276send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1277{
1278 struct GNUNET_MQ_Envelope *env;
1279 struct SuccessResultMessage *acr_msg;
1280
1281 GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1282 adh->client->delete_op_tail,
1283 adh);
1284
1285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1286 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1287 acr_msg->id = htonl (adh->r_id);
1288 acr_msg->op_result = htonl (success);
1289 GNUNET_MQ_send (adh->client->mq, env);
1290}
1291
1292
1293/**
1294 * Namestore iteration within attribute deletion.
1295 * We need to reissue tickets with the deleted attribute removed.
1296 *
1297 * @param cls our attribute deletion handle
1298 * @param zone the private key of the ticket issuer
1299 * @param label the label of the record
1300 * @param rd_count number of records
1301 * @param rd record data
1302 */
1303static void
1304ticket_iter (void *cls,
1305 const struct GNUNET_IDENTITY_PrivateKey *zone,
1306 const char *label,
1307 unsigned int rd_count,
1308 const struct GNUNET_GNSRECORD_Data *rd)
1309{
1310 struct AttributeDeleteHandle *adh = cls;
1311 struct TicketRecordsEntry *le;
1312 int has_changed = GNUNET_NO;
1313 for (int i = 0; i < rd_count; i++)
1314 {
1315 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
1316 continue;
1317 if (adh->claim != NULL)
1318 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
1319 &adh->claim->id))
1320 continue;
1321 if (adh->credential != NULL)
1322 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
1323 &adh->credential->id))
1324 continue;
1325 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1326 "Attribute to delete found (%s)\n",
1327 adh->label);
1328 has_changed = GNUNET_YES;
1329 break;
1330 }
1331 if (GNUNET_YES == has_changed)
1332 {
1333 le = GNUNET_new (struct TicketRecordsEntry);
1334 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1335 le->data = GNUNET_malloc (le->data_size);
1336 le->rd_count = rd_count;
1337 le->label = GNUNET_strdup (label);
1338 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1339 GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1340 adh->tickets_to_update_tail,
1341 le);
1342 }
1343 GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1344}
1345
1346
1347/**
1348 * Recursion prototype for function
1349 * @param cls our deletion handle
1350 */
1351static void
1352update_tickets (void *cls);
1353
1354
1355/**
1356 * Callback called when a ticket was updated
1357 *
1358 * @param cls our attribute deletion handle
1359 * @param success GNUNET_OK if successful
1360 * @param emsg error message (NULL if success=GNUNET_OK)
1361 */
1362static void
1363ticket_updated (void *cls, int32_t success, const char *emsg)
1364{
1365 struct AttributeDeleteHandle *adh = cls;
1366
1367 adh->ns_qe = NULL;
1368 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1369}
1370
1371
1372/**
1373 * Update tickets: Remove shared attribute which has just been deleted.
1374 * This method is called recursively until all tickets are processed.
1375 * Eventually, the updated tickets are stored using ``update_tickets''.
1376 *
1377 * @param cls our attribute deletion handle
1378 */
1379static void
1380update_tickets (void *cls)
1381{
1382 struct AttributeDeleteHandle *adh = cls;
1383 struct TicketRecordsEntry *le;
1384
1385 if (NULL == adh->tickets_to_update_head)
1386 {
1387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1388 "Finished updating tickets, success\n");
1389 send_delete_response (adh, GNUNET_OK);
1390 cleanup_adh (adh);
1391 return;
1392 }
1393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1394 "Updating %s\n",
1395 adh->tickets_to_update_head->label);
1396 le = adh->tickets_to_update_head;
1397 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1398 adh->tickets_to_update_tail,
1399 le);
1400 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1401 struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1402 if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
1403 le->data,
1404 le->rd_count,
1405 rd))
1406 {
1407 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1408 "Unable to deserialize record data!\n");
1409 send_delete_response (adh, GNUNET_SYSERR);
1410 cleanup_adh (adh);
1411 return;
1412 }
1413 int j = 0;
1414 for (int i = 0; i < le->rd_count; i++)
1415 {
1416 if (adh->claim != NULL)
1417 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1418 && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1419 &adh->claim->id)))
1420 continue;
1421 if (adh->credential != NULL)
1422 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1423 && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1424 &adh->credential->id)))
1425 continue;
1426 rd_new[j] = rd[i];
1427 j++;
1428 }
1429 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1430 &adh->identity,
1431 le->label,
1432 j,
1433 rd_new,
1434 &ticket_updated,
1435 adh);
1436 GNUNET_free (le->label);
1437 GNUNET_free (le->data);
1438 GNUNET_free (le);
1439}
1440
1441
1442/**
1443 * Done collecting affected tickets, start updating.
1444 *
1445 * @param cls our attribute deletion handle
1446 */
1447static void
1448ticket_iter_fin (void *cls)
1449{
1450 struct AttributeDeleteHandle *adh = cls;
1451 adh->ns_it = NULL;
1452 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1453}
1454
1455
1456/**
1457 * Error collecting affected tickets. Abort.
1458 *
1459 * @param cls our attribute deletion handle
1460 */
1461static void
1462ticket_iter_err (void *cls)
1463{
1464 struct AttributeDeleteHandle *adh = cls;
1465
1466 adh->ns_it = NULL;
1467 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1468 "Namestore error on delete %s\n",
1469 adh->label);
1470 send_delete_response (adh, GNUNET_SYSERR);
1471 cleanup_adh (adh);
1472}
1473
1474
1475/**
1476 * Start processing tickets which may still contain reference to deleted
1477 * attribute.
1478 *
1479 * @param cls attribute deletion handle
1480 */
1481static void
1482start_ticket_update (void *cls)
1483{
1484 struct AttributeDeleteHandle *adh = cls;
1485
1486 adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1487 &adh->identity,
1488 &ticket_iter_err,
1489 adh,
1490 &ticket_iter,
1491 adh,
1492 &ticket_iter_fin,
1493 adh);
1494}
1495
1496
1497/**
1498 * Attribute deleted callback
1499 *
1500 * @param cls our handle
1501 * @param success success status
1502 * @param emsg error message (NULL if success=GNUNET_OK)
1503 */
1504static void
1505attr_delete_cont (void *cls, int32_t success, const char *emsg)
1506{
1507 struct AttributeDeleteHandle *adh = cls;
1508
1509 adh->ns_qe = NULL;
1510 if (GNUNET_SYSERR == success)
1511 {
1512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1513 "Error deleting attribute %s\n",
1514 adh->label);
1515 send_delete_response (adh, GNUNET_SYSERR);
1516 cleanup_adh (adh);
1517 return;
1518 }
1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1520 GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1521}
1522
1523
1524/**
1525 * Check attribute delete message format
1526 *
1527 * @cls unused
1528 * @dam message to check
1529 */
1530static int
1531check_attribute_delete_message (void *cls,
1532 const struct AttributeDeleteMessage *dam)
1533{
1534 uint16_t size;
1535
1536 size = ntohs (dam->header.size);
1537 if (size <= sizeof(struct AttributeDeleteMessage))
1538 {
1539 GNUNET_break (0);
1540 return GNUNET_SYSERR;
1541 }
1542 return GNUNET_OK;
1543}
1544
1545
1546/**
1547 * Handle attribute deletion
1548 *
1549 * @param cls our client
1550 * @param dam deletion message
1551 */
1552static void
1553handle_attribute_delete_message (void *cls,
1554 const struct AttributeDeleteMessage *dam)
1555{
1556 struct AttributeDeleteHandle *adh;
1557 struct IdpClient *idp = cls;
1558 size_t data_len;
1559
1560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1561
1562 data_len = ntohs (dam->attr_len);
1563
1564 adh = GNUNET_new (struct AttributeDeleteHandle);
1565 GNUNET_RECLAIM_attribute_deserialize ((char *) &dam[1],
1566 data_len,
1567 &adh->claim);
1568 adh->credential = NULL;
1569
1570 adh->r_id = ntohl (dam->id);
1571 adh->identity = dam->identity;
1572 adh->label
1573 = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id,
1574 sizeof(adh->claim->id));
1575 GNUNET_SERVICE_client_continue (idp->client);
1576 adh->client = idp;
1577 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1578 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1579 &adh->identity,
1580 adh->label,
1581 0,
1582 NULL,
1583 &attr_delete_cont,
1584 adh);
1585}
1586
1587
1588/**
1589 * Credential deleted callback
1590 *
1591 * @param cls our handle
1592 * @param success success status
1593 * @param emsg error message (NULL if success=GNUNET_OK)
1594 */
1595static void
1596cred_delete_cont (void *cls, int32_t success, const char *emsg)
1597{
1598 struct AttributeDeleteHandle *adh = cls;
1599
1600 adh->ns_qe = NULL;
1601 if (GNUNET_SYSERR == success)
1602 {
1603 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1604 "Error deleting credential `%s'\n",
1605 adh->label);
1606 send_delete_response (adh, GNUNET_SYSERR);
1607 cleanup_adh (adh);
1608 return;
1609 }
1610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1611 GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1612}
1613
1614
1615/**
1616 * Check credential delete message format
1617 *
1618 * @cls unused
1619 * @dam message to check
1620 */
1621static int
1622check_credential_delete_message (void *cls,
1623 const struct AttributeDeleteMessage *dam)
1624{
1625 uint16_t size;
1626
1627 size = ntohs (dam->header.size);
1628 if (size <= sizeof(struct AttributeDeleteMessage))
1629 {
1630 GNUNET_break (0);
1631 return GNUNET_SYSERR;
1632 }
1633 return GNUNET_OK;
1634}
1635
1636
1637/**
1638 * Handle credential deletion
1639 *
1640 * @param cls our client
1641 * @param dam deletion message
1642 */
1643static void
1644handle_credential_delete_message (void *cls,
1645 const struct AttributeDeleteMessage *dam)
1646{
1647 struct AttributeDeleteHandle *adh;
1648 struct IdpClient *idp = cls;
1649 size_t data_len;
1650
1651 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_DELETE message\n");
1652
1653 data_len = ntohs (dam->attr_len);
1654
1655 adh = GNUNET_new (struct AttributeDeleteHandle);
1656 adh->credential = GNUNET_RECLAIM_credential_deserialize ((char *) &dam[1],
1657 data_len);
1658 adh->claim = NULL;
1659
1660 adh->r_id = ntohl (dam->id);
1661 adh->identity = dam->identity;
1662 adh->label
1663 = GNUNET_STRINGS_data_to_string_alloc (&adh->credential->id,
1664 sizeof(adh->credential->id));
1665 GNUNET_SERVICE_client_continue (idp->client);
1666 adh->client = idp;
1667 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1668 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1669 &adh->identity,
1670 adh->label,
1671 0,
1672 NULL,
1673 &cred_delete_cont,
1674 adh);
1675}
1676
1677
1678/*************************************************
1679* Attrubute iteration
1680*************************************************/
1681
1682
1683/**
1684 * Done iterating over attributes
1685 *
1686 * @param cls our iterator handle
1687 */
1688static void
1689attr_iter_finished (void *cls)
1690{
1691 struct Iterator *ai = cls;
1692 struct GNUNET_MQ_Envelope *env;
1693 struct AttributeResultMessage *arm;
1694
1695 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1696 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1697 arm->id = htonl (ai->request_id);
1698 arm->attr_len = htons (0);
1699 GNUNET_MQ_send (ai->client->mq, env);
1700 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1701 ai->client->attr_iter_tail,
1702 ai);
1703 GNUNET_free (ai);
1704}
1705
1706
1707/**
1708 * Error iterating over attributes. Abort.
1709 *
1710 * @param cls our attribute iteration handle
1711 */
1712static void
1713attr_iter_error (void *cls)
1714{
1715 struct Iterator *ai = cls;
1716
1717 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1718 attr_iter_finished (ai);
1719}
1720
1721
1722/**
1723 * Got record. Return if it is an attribute.
1724 *
1725 * @param cls our attribute iterator
1726 * @param zone zone we are iterating
1727 * @param label label of the records
1728 * @param rd_count record count
1729 * @param rd records
1730 */
1731static void
1732attr_iter_cb (void *cls,
1733 const struct GNUNET_IDENTITY_PrivateKey *zone,
1734 const char *label,
1735 unsigned int rd_count,
1736 const struct GNUNET_GNSRECORD_Data *rd)
1737{
1738 struct Iterator *ai = cls;
1739 struct GNUNET_MQ_Envelope *env;
1740 char *data_tmp;
1741
1742 if ((rd_count != 1) ||
1743 (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd->record_type))
1744 {
1745 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1746 return;
1747 }
1748 struct AttributeResultMessage *arm;
1749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
1750 label);
1751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1752 "Sending ATTRIBUTE_RESULT message\n");
1753 env = GNUNET_MQ_msg_extra (arm,
1754 rd->data_size,
1755 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1756 arm->id = htonl (ai->request_id);
1757 arm->attr_len = htons (rd->data_size);
1758 GNUNET_IDENTITY_key_get_public (zone, &arm->identity);
1759 data_tmp = (char *) &arm[1];
1760 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1761 GNUNET_MQ_send (ai->client->mq, env);
1762}
1763
1764
1765/**
1766 * Iterate over zone to get attributes
1767 *
1768 * @param cls our client
1769 * @param ais_msg the iteration message to start
1770 */
1771static void
1772handle_iteration_start (void *cls,
1773 const struct AttributeIterationStartMessage *ais_msg)
1774{
1775 struct IdpClient *idp = cls;
1776 struct Iterator *ai;
1777
1778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1779 "Received ATTRIBUTE_ITERATION_START message\n");
1780 ai = GNUNET_new (struct Iterator);
1781 ai->request_id = ntohl (ais_msg->id);
1782 ai->client = idp;
1783 ai->identity = ais_msg->identity;
1784
1785 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1786 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1787 &ai->identity,
1788 &attr_iter_error,
1789 ai,
1790 &attr_iter_cb,
1791 ai,
1792 &attr_iter_finished,
1793 ai);
1794 GNUNET_SERVICE_client_continue (idp->client);
1795}
1796
1797
1798/**
1799 * Handle iteration stop message from client
1800 *
1801 * @param cls the client
1802 * @param ais_msg the stop message
1803 */
1804static void
1805handle_iteration_stop (void *cls,
1806 const struct AttributeIterationStopMessage *ais_msg)
1807{
1808 struct IdpClient *idp = cls;
1809 struct Iterator *ai;
1810 uint32_t rid;
1811
1812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1813 "Received `%s' message\n",
1814 "ATTRIBUTE_ITERATION_STOP");
1815 rid = ntohl (ais_msg->id);
1816 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1817 if (ai->request_id == rid)
1818 break;
1819 if (NULL == ai)
1820 {
1821 GNUNET_break (0);
1822 GNUNET_SERVICE_client_drop (idp->client);
1823 return;
1824 }
1825 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1826 GNUNET_free (ai);
1827 GNUNET_SERVICE_client_continue (idp->client);
1828}
1829
1830
1831/**
1832 * Client requests next attribute from iterator
1833 *
1834 * @param cls the client
1835 * @param ais_msg the message
1836 */
1837static void
1838handle_iteration_next (void *cls,
1839 const struct AttributeIterationNextMessage *ais_msg)
1840{
1841 struct IdpClient *idp = cls;
1842 struct Iterator *ai;
1843 uint32_t rid;
1844
1845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1846 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1847 rid = ntohl (ais_msg->id);
1848 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1849 if (ai->request_id == rid)
1850 break;
1851 if (NULL == ai)
1852 {
1853 GNUNET_break (0);
1854 GNUNET_SERVICE_client_drop (idp->client);
1855 return;
1856 }
1857 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1858 GNUNET_SERVICE_client_continue (idp->client);
1859}
1860
1861
1862/*************************************************
1863* Credential iteration
1864*************************************************/
1865
1866
1867/**
1868 * Done iterating over credentials
1869 *
1870 * @param cls our iterator handle
1871 */
1872static void
1873cred_iter_finished (void *cls)
1874{
1875 struct Iterator *ai = cls;
1876 struct GNUNET_MQ_Envelope *env;
1877 struct CredentialResultMessage *arm;
1878
1879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CREDENTIAL_RESULT message\n");
1880 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
1881 arm->id = htonl (ai->request_id);
1882 arm->credential_len = htons (0);
1883 GNUNET_MQ_send (ai->client->mq, env);
1884 GNUNET_CONTAINER_DLL_remove (ai->client->cred_iter_head,
1885 ai->client->cred_iter_tail,
1886 ai);
1887 GNUNET_free (ai);
1888}
1889
1890
1891/**
1892 * Error iterating over credentials. Abort.
1893 *
1894 * @param cls our attribute iteration handle
1895 */
1896static void
1897cred_iter_error (void *cls)
1898{
1899 struct Iterator *ai = cls;
1900
1901 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over credentials\n");
1902 cred_iter_finished (ai);
1903}
1904
1905
1906/**
1907 * Got record. Return credential.
1908 *
1909 * @param cls our attribute iterator
1910 * @param zone zone we are iterating
1911 * @param label label of the records
1912 * @param rd_count record count
1913 * @param rd records
1914 */
1915static void
1916cred_iter_cb (void *cls,
1917 const struct GNUNET_IDENTITY_PrivateKey *zone,
1918 const char *label,
1919 unsigned int rd_count,
1920 const struct GNUNET_GNSRECORD_Data *rd)
1921{
1922 struct Iterator *ai = cls;
1923 struct GNUNET_MQ_Envelope *env;
1924 struct CredentialResultMessage *arm;
1925 char *data_tmp;
1926
1927 if ((rd_count != 1) ||
1928 (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL != rd->record_type))
1929 {
1930 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1931 return;
1932 }
1933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found credential under: %s\n",
1934 label);
1935 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1936 "Sending CREDENTIAL_RESULT message\n");
1937 env = GNUNET_MQ_msg_extra (arm,
1938 rd->data_size,
1939 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
1940 arm->id = htonl (ai->request_id);
1941 arm->credential_len = htons (rd->data_size);
1942 GNUNET_IDENTITY_key_get_public (zone, &arm->identity);
1943 data_tmp = (char *) &arm[1];
1944 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1945
1946 GNUNET_MQ_send (ai->client->mq, env);
1947}
1948
1949
1950/**
1951 * Iterate over zone to get attributes
1952 *
1953 * @param cls our client
1954 * @param ais_msg the iteration message to start
1955 */
1956static void
1957handle_credential_iteration_start (void *cls,
1958 const struct
1959 CredentialIterationStartMessage *ais_msg)
1960{
1961 struct IdpClient *idp = cls;
1962 struct Iterator *ai;
1963
1964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1965 "Received CREDENTIAL_ITERATION_START message\n");
1966 ai = GNUNET_new (struct Iterator);
1967 ai->request_id = ntohl (ais_msg->id);
1968 ai->client = idp;
1969 ai->identity = ais_msg->identity;
1970
1971 GNUNET_CONTAINER_DLL_insert (idp->cred_iter_head, idp->cred_iter_tail,
1972 ai);
1973 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1974 &ai->identity,
1975 &cred_iter_error,
1976 ai,
1977 &cred_iter_cb,
1978 ai,
1979 &cred_iter_finished,
1980 ai);
1981 GNUNET_SERVICE_client_continue (idp->client);
1982}
1983
1984
1985/**
1986 * Handle iteration stop message from client
1987 *
1988 * @param cls the client
1989 * @param ais_msg the stop message
1990 */
1991static void
1992handle_credential_iteration_stop (void *cls,
1993 const struct
1994 CredentialIterationStopMessage *ais_msg)
1995{
1996 struct IdpClient *idp = cls;
1997 struct Iterator *ai;
1998 uint32_t rid;
1999
2000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2001 "Received `%s' message\n",
2002 "CREDENTIAL_ITERATION_STOP");
2003 rid = ntohl (ais_msg->id);
2004 for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
2005 if (ai->request_id == rid)
2006 break;
2007 if (NULL == ai)
2008 {
2009 GNUNET_break (0);
2010 GNUNET_SERVICE_client_drop (idp->client);
2011 return;
2012 }
2013 GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
2014 ai);
2015 GNUNET_free (ai);
2016 GNUNET_SERVICE_client_continue (idp->client);
2017}
2018
2019
2020/**
2021 * Client requests next credential from iterator
2022 *
2023 * @param cls the client
2024 * @param ais_msg the message
2025 */
2026static void
2027handle_credential_iteration_next (void *cls,
2028 const struct
2029 CredentialIterationNextMessage *ais_msg)
2030{
2031 struct IdpClient *idp = cls;
2032 struct Iterator *ai;
2033 uint32_t rid;
2034
2035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2036 "Received CREDENTIAL_ITERATION_NEXT message\n");
2037 rid = ntohl (ais_msg->id);
2038 for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
2039 if (ai->request_id == rid)
2040 break;
2041 if (NULL == ai)
2042 {
2043 GNUNET_break (0);
2044 GNUNET_SERVICE_client_drop (idp->client);
2045 return;
2046 }
2047 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2048 GNUNET_SERVICE_client_continue (idp->client);
2049}
2050
2051
2052/******************************************************
2053* Ticket iteration
2054******************************************************/
2055
2056/**
2057 * Got a ticket. Return to client
2058 *
2059 * @param cls our ticket iterator
2060 * @param ticket the ticket
2061 */
2062static void
2063ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
2064{
2065 struct TicketIteration *ti = cls;
2066 struct GNUNET_MQ_Envelope *env;
2067 struct TicketResultMessage *trm;
2068
2069 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
2070 if (NULL == ticket)
2071 {
2072 /* send empty response to indicate end of list */
2073 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2074 ti->client->ticket_iter_tail,
2075 ti);
2076 }
2077 else
2078 {
2079 trm->ticket = *ticket;
2080 }
2081 trm->id = htonl (ti->r_id);
2082 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
2083 GNUNET_MQ_send (ti->client->mq, env);
2084 if (NULL == ticket)
2085 GNUNET_free (ti);
2086}
2087
2088
2089/**
2090 * Client requests a ticket iteration
2091 *
2092 * @param cls the client
2093 * @param tis_msg the iteration request message
2094 */
2095static void
2096handle_ticket_iteration_start (
2097 void *cls,
2098 const struct TicketIterationStartMessage *tis_msg)
2099{
2100 struct IdpClient *client = cls;
2101 struct TicketIteration *ti;
2102
2103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2104 "Received TICKET_ITERATION_START message\n");
2105 ti = GNUNET_new (struct TicketIteration);
2106 ti->r_id = ntohl (tis_msg->id);
2107 ti->client = client;
2108
2109 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2110 client->ticket_iter_tail,
2111 ti);
2112 ti->iter
2113 = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
2114 GNUNET_SERVICE_client_continue (client->client);
2115}
2116
2117
2118/**
2119 * Client has had enough tickets
2120 *
2121 * @param cls the client
2122 * @param tis_msg the stop message
2123 */
2124static void
2125handle_ticket_iteration_stop (void *cls,
2126 const struct TicketIterationStopMessage *tis_msg)
2127{
2128 struct IdpClient *client = cls;
2129 struct TicketIteration *ti;
2130 uint32_t rid;
2131
2132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2133 "Received `%s' message\n",
2134 "TICKET_ITERATION_STOP");
2135 rid = ntohl (tis_msg->id);
2136 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2137 if (ti->r_id == rid)
2138 break;
2139 if (NULL == ti)
2140 {
2141 GNUNET_break (0);
2142 GNUNET_SERVICE_client_drop (client->client);
2143 return;
2144 }
2145 RECLAIM_TICKETS_iteration_stop (ti->iter);
2146 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2147 client->ticket_iter_tail,
2148 ti);
2149 GNUNET_free (ti);
2150 GNUNET_SERVICE_client_continue (client->client);
2151}
2152
2153
2154/**
2155 * Client requests next result.
2156 *
2157 * @param cls the client
2158 * @param tis_msg the message
2159 */
2160static void
2161handle_ticket_iteration_next (void *cls,
2162 const struct TicketIterationNextMessage *tis_msg)
2163{
2164 struct IdpClient *client = cls;
2165 struct TicketIteration *ti;
2166 uint32_t rid;
2167
2168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2169 "Received TICKET_ITERATION_NEXT message\n");
2170 rid = ntohl (tis_msg->id);
2171 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2172 if (ti->r_id == rid)
2173 break;
2174 if (NULL == ti)
2175 {
2176 GNUNET_break (0);
2177 GNUNET_SERVICE_client_drop (client->client);
2178 return;
2179 }
2180 RECLAIM_TICKETS_iteration_next (ti->iter);
2181 GNUNET_SERVICE_client_continue (client->client);
2182}
2183
2184
2185/**
2186 * Main function that will be run
2187 *
2188 * @param cls closure
2189 * @param c the configuration used
2190 * @param server the service handle
2191 */
2192static void
2193run (void *cls,
2194 const struct GNUNET_CONFIGURATION_Handle *c,
2195 struct GNUNET_SERVICE_Handle *server)
2196{
2197 cfg = c;
2198
2199 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
2200 {
2201 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2202 "Unable to initialize TICKETS subsystem.\n");
2203 GNUNET_SCHEDULER_shutdown ();
2204 return;
2205 }
2206 // Connect to identity and namestore services
2207 nsh = GNUNET_NAMESTORE_connect (cfg);
2208 if (NULL == nsh)
2209 {
2210 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
2211 "error connecting to namestore");
2212 }
2213
2214 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2215}
2216
2217
2218/**
2219 * Called whenever a client is disconnected.
2220 *
2221 * @param cls closure
2222 * @param client identification of the client
2223 * @param app_ctx @a client
2224 */
2225static void
2226client_disconnect_cb (void *cls,
2227 struct GNUNET_SERVICE_Client *client,
2228 void *app_ctx)
2229{
2230 struct IdpClient *idp = app_ctx;
2231
2232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
2233 GNUNET_CONTAINER_DLL_remove (client_list_head,
2234 client_list_tail,
2235 idp);
2236 cleanup_client (idp);
2237}
2238
2239
2240/**
2241 * Add a client to our list of active clients.
2242 *
2243 * @param cls NULL
2244 * @param client client to add
2245 * @param mq message queue for @a client
2246 * @return internal namestore client structure for this client
2247 */
2248static void *
2249client_connect_cb (void *cls,
2250 struct GNUNET_SERVICE_Client *client,
2251 struct GNUNET_MQ_Handle *mq)
2252{
2253 struct IdpClient *idp;
2254
2255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
2256 idp = GNUNET_new (struct IdpClient);
2257 idp->client = client;
2258 idp->mq = mq;
2259 GNUNET_CONTAINER_DLL_insert (client_list_head,
2260 client_list_tail,
2261 idp);
2262 return idp;
2263}
2264
2265
2266/**
2267 * Define "main" method using service macro.
2268 */
2269GNUNET_SERVICE_MAIN (
2270 "reclaim",
2271 GNUNET_SERVICE_OPTION_NONE,
2272 &run,
2273 &client_connect_cb,
2274 &client_disconnect_cb,
2275 NULL,
2276 GNUNET_MQ_hd_var_size (attribute_store_message,
2277 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2278 struct AttributeStoreMessage,
2279 NULL),
2280 GNUNET_MQ_hd_var_size (credential_store_message,
2281 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE,
2282 struct AttributeStoreMessage,
2283 NULL),
2284 GNUNET_MQ_hd_var_size (attribute_delete_message,
2285 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
2286 struct AttributeDeleteMessage,
2287 NULL),
2288 GNUNET_MQ_hd_var_size (credential_delete_message,
2289 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE,
2290 struct AttributeDeleteMessage,
2291 NULL),
2292 GNUNET_MQ_hd_fixed_size (iteration_start,
2293 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
2294 struct AttributeIterationStartMessage,
2295 NULL),
2296 GNUNET_MQ_hd_fixed_size (iteration_next,
2297 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
2298 struct AttributeIterationNextMessage,
2299 NULL),
2300 GNUNET_MQ_hd_fixed_size (iteration_stop,
2301 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2302 struct AttributeIterationStopMessage,
2303 NULL),
2304 GNUNET_MQ_hd_fixed_size (credential_iteration_start,
2305 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START,
2306 struct CredentialIterationStartMessage,
2307 NULL),
2308 GNUNET_MQ_hd_fixed_size (credential_iteration_next,
2309 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT,
2310 struct CredentialIterationNextMessage,
2311 NULL),
2312 GNUNET_MQ_hd_fixed_size (credential_iteration_stop,
2313 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP,
2314 struct CredentialIterationStopMessage,
2315 NULL),
2316
2317 GNUNET_MQ_hd_var_size (issue_ticket_message,
2318 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
2319 struct IssueTicketMessage,
2320 NULL),
2321 GNUNET_MQ_hd_var_size (consume_ticket_message,
2322 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
2323 struct ConsumeTicketMessage,
2324 NULL),
2325 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2326 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
2327 struct TicketIterationStartMessage,
2328 NULL),
2329 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2330 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
2331 struct TicketIterationNextMessage,
2332 NULL),
2333 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2334 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
2335 struct TicketIterationStopMessage,
2336 NULL),
2337 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2338 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
2339 struct RevokeTicketMessage,
2340 NULL),
2341 GNUNET_MQ_handler_end ());
2342/* end of gnunet-service-reclaim.c */
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c b/src/reclaim/gnunet-service-reclaim_tickets.c
deleted file mode 100644
index 0b1730bec..000000000
--- a/src/reclaim/gnunet-service-reclaim_tickets.c
+++ /dev/null
@@ -1,1852 +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/**
22 * @author Martin Schanzenbach
23 * @file src/reclaim/gnunet-service-reclaim_tickets.c
24 * @brief reclaim tickets
25 *
26 */
27#include <inttypes.h>
28#include "gnunet-service-reclaim_tickets.h"
29
30
31/**
32 * FIXME: the defaul ticket iteration interval should probably
33 * be the minimim attribute expiration.
34 */
35#define DEFAULT_TICKET_REFRESH_INTERVAL GNUNET_TIME_UNIT_HOURS
36
37/**
38 * Handle for a parallel GNS lookup job
39 * (Declaration further below)
40 */
41struct ParallelLookup;
42
43
44/**
45 * A reference to a ticket stored in GNS
46 */
47struct TicketReference
48{
49 /**
50 * DLL
51 */
52 struct TicketReference *next;
53
54 /**
55 * DLL
56 */
57 struct TicketReference *prev;
58
59 /**
60 * Attributes
61 */
62 struct GNUNET_RECLAIM_AttributeList *attrs;
63
64 /**
65 * Tickets
66 */
67 struct GNUNET_RECLAIM_Ticket ticket;
68};
69
70
71/**
72 * Handle to a consume operation
73 */
74struct RECLAIM_TICKETS_ConsumeHandle
75{
76 /**
77 * Ticket
78 */
79 struct GNUNET_RECLAIM_Ticket ticket;
80
81 /**
82 * LookupRequest
83 */
84 struct GNUNET_GNS_LookupRequest *lookup_request;
85
86 /**
87 * Audience Key
88 */
89 struct GNUNET_IDENTITY_PrivateKey identity;
90
91 /**
92 * Audience Key
93 */
94 struct GNUNET_IDENTITY_PublicKey identity_pub;
95
96 /**
97 * Lookup DLL
98 */
99 struct ParallelLookup *parallel_lookups_head;
100
101 /**
102 * Lookup DLL
103 */
104 struct ParallelLookup *parallel_lookups_tail;
105
106 /**
107 * Kill task
108 */
109 struct GNUNET_SCHEDULER_Task *kill_task;
110
111 /**
112 * Attributes
113 */
114 struct GNUNET_RECLAIM_AttributeList *attrs;
115
116 /**
117 * Presentations
118 */
119 struct GNUNET_RECLAIM_PresentationList *presentations;
120
121 /**
122 * Lookup time
123 */
124 struct GNUNET_TIME_Absolute lookup_start_time;
125
126 /**
127 * Callback
128 */
129 RECLAIM_TICKETS_ConsumeCallback cb;
130
131 /**
132 * Callbacl closure
133 */
134 void *cb_cls;
135};
136
137
138/**
139 * Handle for a parallel GNS lookup job
140 */
141struct ParallelLookup
142{
143 /* DLL */
144 struct ParallelLookup *next;
145
146 /* DLL */
147 struct ParallelLookup *prev;
148
149 /* The GNS request */
150 struct GNUNET_GNS_LookupRequest *lookup_request;
151
152 /* The handle the return to */
153 struct RECLAIM_TICKETS_ConsumeHandle *handle;
154
155 /**
156 * Lookup time
157 */
158 struct GNUNET_TIME_Absolute lookup_start_time;
159
160 /* The label to look up */
161 char *label;
162};
163
164
165/**
166 * Ticket issue request handle
167 */
168struct TicketIssueHandle
169{
170 /**
171 * Attributes to issue
172 */
173 struct GNUNET_RECLAIM_AttributeList *attrs;
174
175 /**
176 * Presentations to add
177 */
178 struct GNUNET_RECLAIM_PresentationList *presentations;
179
180 /**
181 * Issuer Key
182 */
183 struct GNUNET_IDENTITY_PrivateKey identity;
184
185 /**
186 * Ticket to issue
187 */
188 struct GNUNET_RECLAIM_Ticket ticket;
189
190 /**
191 * QueueEntry
192 */
193 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
194
195 /**
196 * Namestore Iterator
197 */
198 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
199
200 /**
201 * Callback
202 */
203 RECLAIM_TICKETS_TicketResult cb;
204
205 /**
206 * Callback cls
207 */
208 void *cb_cls;
209};
210
211
212/**
213 * Ticket iterator
214 */
215struct RECLAIM_TICKETS_Iterator
216{
217 /**
218 * Namestore queue entry
219 */
220 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
221
222 /**
223 * Iter callback
224 */
225 RECLAIM_TICKETS_TicketIter cb;
226
227 /**
228 * Iter cls
229 */
230 void *cb_cls;
231};
232
233
234struct RevokedAttributeEntry
235{
236 /**
237 * DLL
238 */
239 struct RevokedAttributeEntry *next;
240
241 /**
242 * DLL
243 */
244 struct RevokedAttributeEntry *prev;
245
246 /**
247 * Old ID of the attribute
248 */
249 struct GNUNET_RECLAIM_Identifier old_id;
250
251 /**
252 * New ID of the attribute
253 */
254 struct GNUNET_RECLAIM_Identifier new_id;
255};
256
257
258/**
259 * Ticket revocation request handle
260 */
261struct RECLAIM_TICKETS_RevokeHandle
262{
263 /**
264 * Issuer Key
265 */
266 struct GNUNET_IDENTITY_PrivateKey identity;
267
268 /**
269 * Callback
270 */
271 RECLAIM_TICKETS_RevokeCallback cb;
272
273 /**
274 * Callback cls
275 */
276 void *cb_cls;
277
278 /**
279 * Ticket to issue
280 */
281 struct GNUNET_RECLAIM_Ticket ticket;
282
283 /**
284 * QueueEntry
285 */
286 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
287
288 /**
289 * Namestore iterator
290 */
291 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
292
293 /**
294 * Revoked attributes
295 */
296 struct RevokedAttributeEntry *attrs_head;
297
298 /**
299 * Revoked attributes
300 */
301 struct RevokedAttributeEntry *attrs_tail;
302
303 /**
304 * Current attribute to move
305 */
306 struct RevokedAttributeEntry *move_attr;
307
308 /**
309 * Number of attributes in ticket
310 */
311 unsigned int ticket_attrs;
312
313 /**
314 * Tickets to update
315 */
316 struct TicketRecordsEntry *tickets_to_update_head;
317
318 /**
319 * Tickets to update
320 */
321 struct TicketRecordsEntry *tickets_to_update_tail;
322};
323
324
325/**
326 * Ticket expiration interval
327 */
328static struct GNUNET_TIME_Relative ticket_refresh_interval;
329
330
331/* Namestore handle */
332static struct GNUNET_NAMESTORE_Handle *nsh;
333
334
335/* GNS handle */
336static struct GNUNET_GNS_Handle *gns;
337
338
339/* Handle to the statistics service */
340static struct GNUNET_STATISTICS_Handle *stats;
341
342
343/**
344 * Cleanup revoke handle
345 *
346 * @param rh the ticket revocation handle
347 */
348static void
349cleanup_rvk (struct RECLAIM_TICKETS_RevokeHandle *rh)
350{
351 struct RevokedAttributeEntry *ae;
352 struct TicketRecordsEntry *le;
353
354 if (NULL != rh->ns_qe)
355 GNUNET_NAMESTORE_cancel (rh->ns_qe);
356 if (NULL != rh->ns_it)
357 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
358 while (NULL != (ae = rh->attrs_head))
359 {
360 GNUNET_CONTAINER_DLL_remove (rh->attrs_head, rh->attrs_tail, ae);
361 GNUNET_free (ae);
362 }
363 while (NULL != (le = rh->tickets_to_update_head))
364 {
365 GNUNET_CONTAINER_DLL_remove (rh->tickets_to_update_head,
366 rh->tickets_to_update_head,
367 le);
368 if (NULL != le->data)
369 GNUNET_free (le->data);
370 if (NULL != le->label)
371 GNUNET_free (le->label);
372 GNUNET_free (le);
373 }
374 GNUNET_free (rh);
375}
376
377
378/**
379 * For each ticket, store new, updated attribute references
380 * (Implementation further below)
381 *
382 * @param cls handle to the operation
383 */
384static void
385process_tickets (void *cls);
386
387
388/**
389 * Finished storing updated attribute references.
390 * Abort on error, else continue processing tickets
391 *
392 * @param cls handle to the operation
393 * @param success result of namestore operation
394 * @param emsg (NULL on success)
395 */
396static void
397ticket_processed (void *cls, int32_t success, const char *emsg)
398{
399 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
400
401 rvk->ns_qe = NULL;
402 GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
403}
404
405
406/**
407 * For each ticket, store new, updated attribute references
408 *
409 * @param cls handle to the operation
410 */
411static void
412process_tickets (void *cls)
413{
414 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
415 struct TicketRecordsEntry *le;
416 struct RevokedAttributeEntry *ae;
417
418 if (NULL == rvk->tickets_to_update_head)
419 {
420 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
421 "Finished updatding tickets, success\n");
422 rvk->cb (rvk->cb_cls, GNUNET_OK);
423 cleanup_rvk (rvk);
424 return;
425 }
426 le = rvk->tickets_to_update_head;
427 GNUNET_CONTAINER_DLL_remove (rvk->tickets_to_update_head,
428 rvk->tickets_to_update_tail,
429 le);
430 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
431 if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
432 le->data,
433 le->rd_count,
434 rd))
435 {
436 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
437 "Unable to deserialize ticket record(s)\n");
438 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
439 cleanup_rvk (rvk);
440 return;
441 }
442 for (int i = 0; i < le->rd_count; i++)
443 {
444 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
445 continue;
446 for (ae = rvk->attrs_head; NULL != ae; ae = ae->next)
447 {
448 if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id)))
449 continue;
450 rd[i].data = &ae->new_id;
451 }
452 }
453 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
454 &rvk->identity,
455 le->label,
456 le->rd_count,
457 rd,
458 &ticket_processed,
459 rvk);
460 GNUNET_free (le->label);
461 GNUNET_free (le->data);
462 GNUNET_free (le);
463}
464
465
466/**
467 * Done collecting tickets. Start processing.
468 *
469 * @param cls handle to the operation
470 */
471static void
472rvk_ticket_update_finished (void *cls)
473{
474 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
475
476 rvk->ns_it = NULL;
477 GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
478}
479
480
481/**
482 * We need to update all other tickets with the new attribute IDs.
483 * We first collect them all. Processing after.
484 *
485 * @param cls handle to the operation
486 * @param zone ticket issuer private key
487 * @param label ticket rnd
488 * @param rd_cound size of record set
489 * @param rd record set
490 */
491static void
492rvk_ticket_update (void *cls,
493 const struct GNUNET_IDENTITY_PrivateKey *zone,
494 const char *label,
495 unsigned int rd_count,
496 const struct GNUNET_GNSRECORD_Data *rd)
497{
498 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
499 struct TicketRecordsEntry *le;
500 struct RevokedAttributeEntry *ae;
501 int has_changed = GNUNET_NO;
502
503 /** Let everything point to the old record **/
504 for (int i = 0; i < rd_count; i++)
505 {
506 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
507 continue;
508 for (ae = rvk->attrs_head; NULL != ae; ae = ae->next)
509 {
510 if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id)))
511 continue;
512 has_changed = GNUNET_YES;
513 break;
514 }
515 if (GNUNET_YES == has_changed)
516 break;
517 }
518 if (GNUNET_YES == has_changed)
519 {
520 le = GNUNET_new (struct TicketRecordsEntry);
521 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
522 le->data = GNUNET_malloc (le->data_size);
523 le->rd_count = rd_count;
524 le->label = GNUNET_strdup (label);
525 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
526 GNUNET_CONTAINER_DLL_insert (rvk->tickets_to_update_head,
527 rvk->tickets_to_update_tail,
528 le);
529 }
530 GNUNET_NAMESTORE_zone_iterator_next (rvk->ns_it, 1);
531}
532
533
534/**
535 * Error iterating namestore. Abort.
536 *
537 * @param cls handle to the operation
538 */
539static void
540rvk_ns_iter_err (void *cls)
541{
542 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
543
544 rvk->ns_it = NULL;
545 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
546 cleanup_rvk (rvk);
547}
548
549
550/**
551 * Error storing new attribute in namestore. Abort
552 *
553 * @param cls handle to the operation
554 */
555static void
556rvk_ns_err (void *cls)
557{
558 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
559
560 rvk->ns_qe = NULL;
561 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
562 cleanup_rvk (rvk);
563}
564
565
566/**
567 * We change every attribute ID of the ticket attributes we
568 * want to revoke.
569 * When we are done, we need to update any other ticket which
570 * included references to any of the changed attributes.
571 * (Implementation further below)
572 *
573 * @param rvk handle to the operation
574 */
575static void
576move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rh);
577
578
579/**
580 * Delayed continuation for move_attrs
581 *
582 * @param cls handle to the operation.
583 */
584static void
585move_attrs_cont (void *cls)
586{
587 move_attrs ((struct RECLAIM_TICKETS_RevokeHandle *) cls);
588}
589
590
591/**
592 * Done deleting the old record. Abort on error.
593 * Else, continue updating attribute IDs.
594 *
595 * @param cls handle to the operation
596 * @param success result of the namestore operation
597 * @param emsg error message (NULL on success)
598 */
599static void
600del_attr_finished (void *cls, int32_t success, const char *emsg)
601{
602 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
603
604 rvk->ns_qe = NULL;
605 if (GNUNET_SYSERR == success)
606 {
607 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
608 "Error removing attribute: %s\n",
609 emsg);
610 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
611 cleanup_rvk (rvk);
612 return;
613 }
614 rvk->move_attr = rvk->move_attr->next;
615 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
616}
617
618
619/**
620 * Updated an attribute ID.
621 * Abort on error if namestore operation failed.
622 * Else, we have to delete the old record.
623 *
624 * @param cls handle to the operation
625 * @param success result of the store operation
626 * @param emsg error message (NULL on success)
627 */
628static void
629move_attr_finished (void *cls, int32_t success, const char *emsg)
630{
631 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
632 char *label;
633
634 rvk->ns_qe = NULL;
635 if (GNUNET_SYSERR == success)
636 {
637 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error moving attribute: %s\n", emsg);
638 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
639 cleanup_rvk (rvk);
640 return;
641 }
642 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
643 sizeof(rvk->move_attr->old_id));
644 GNUNET_assert (NULL != label);
645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing attribute %s\n", label);
646 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
647 &rvk->identity,
648 label,
649 0,
650 NULL,
651 &del_attr_finished,
652 rvk);
653 GNUNET_free (label);
654}
655
656
657/**
658 * Got the referenced attribute. Updating the ID
659 *
660 * @param cls handle to the operation
661 * @param zone issuer identity
662 * @param label attribute ID
663 * @param rd_count size of record set (should be 1)
664 * @param rd record set (the attribute)
665 */
666static void
667rvk_move_attr_cb (void *cls,
668 const struct GNUNET_IDENTITY_PrivateKey *zone,
669 const char *label,
670 unsigned int rd_count,
671 const struct GNUNET_GNSRECORD_Data *rd)
672{
673 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
674 struct GNUNET_GNSRECORD_Data new_rd[rd_count];
675 struct RevokedAttributeEntry *le;
676 char *new_label;
677 char *attr_data;
678
679 rvk->ns_qe = NULL;
680 if (0 == rd_count)
681 {
682 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
683 "The claim %s no longer exists!\n",
684 label);
685 le = rvk->move_attr;
686 rvk->move_attr = le->next;
687 GNUNET_CONTAINER_DLL_remove (rvk->attrs_head, rvk->attrs_tail, le);
688 GNUNET_free (le);
689 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
690 return;
691 }
692 GNUNET_RECLAIM_id_generate (&rvk->move_attr->new_id);
693 new_label = NULL;
694 attr_data = NULL;
695 // new_rd = *rd;
696 for (int i = 0; i < rd_count; i++)
697 {
698 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type)
699 {
700 /** find a new place for this attribute **/
701 struct GNUNET_RECLAIM_Attribute *claim;
702 GNUNET_RECLAIM_attribute_deserialize (rd[i].data,
703 rd[i].data_size,
704 &claim);
705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
706 "Attribute to update: Name=%s\n",
707 claim->name);
708 claim->id = rvk->move_attr->new_id;
709 new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize_get_size (claim);
710 attr_data = GNUNET_malloc (rd[i].data_size);
711 new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize (claim,
712 attr_data);
713 new_rd[i].data = attr_data;
714 new_rd[i].record_type = rd[i].record_type;
715 new_rd[i].flags = rd[i].flags;
716 new_rd[i].expiration_time = rd[i].expiration_time;
717 new_label =
718 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
719 sizeof (rvk->move_attr->new_id));
720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
721 GNUNET_free (claim);
722 }
723 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
724 {
725 struct GNUNET_RECLAIM_Credential *credential;
726 credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
727 rd[i].data_size);
728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
729 "Credential to update: Name=%s\n",
730 credential->name);
731 credential->id = rvk->move_attr->new_id;
732 new_rd[i].data_size =
733 GNUNET_RECLAIM_credential_serialize_get_size (credential);
734 attr_data = GNUNET_malloc (rd[i].data_size);
735 new_rd[i].data_size = GNUNET_RECLAIM_credential_serialize (credential,
736 attr_data);
737 new_rd[i].data = attr_data;
738 new_rd[i].record_type = rd[i].record_type;
739 new_rd[i].flags = rd[i].flags;
740 new_rd[i].expiration_time = rd[i].expiration_time;
741 new_label =
742 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
743 sizeof (rvk->move_attr->new_id));
744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n",
745 new_label);
746 GNUNET_free (credential);
747 }
748 }
749 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
750 &rvk->identity,
751 new_label,
752 rd_count,
753 new_rd,
754 &move_attr_finished,
755 rvk);
756 GNUNET_free (new_label);
757 GNUNET_free (attr_data);
758}
759
760
761/**
762 * We change every attribute ID of the ticket attributes we
763 * want to revoke.
764 * When we are done, we need to update any other ticket which
765 * included references to any of the changed attributes.
766 *
767 * @param rvk handle to the operation
768 */
769static void
770move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk)
771{
772 char *label;
773
774 if (NULL == rvk->move_attr)
775 {
776 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished moving attributes\n");
777 rvk->ns_it =
778 GNUNET_NAMESTORE_zone_iteration_start (nsh,
779 &rvk->identity,
780 &rvk_ns_iter_err,
781 rvk,
782 &rvk_ticket_update,
783 rvk,
784 &rvk_ticket_update_finished,
785 rvk);
786 return;
787 }
788 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
789 sizeof (rvk->move_attr->old_id));
790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving claim %s\n", label);
791
792 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
793 &rvk->identity,
794 label,
795 &rvk_ns_err,
796 rvk,
797 &rvk_move_attr_cb,
798 rvk);
799 GNUNET_free (label);
800}
801
802
803/**
804 * Finished deleting ticket and attribute references.
805 * Abort on failure.
806 * Else, we start changing every attribute ID in the
807 * found attribute references so that access is no longer
808 * possible.
809 *
810 * @param cls handle to the operation
811 * @param success Namestore operation return value
812 * @param emsg error message (NULL on success)
813 */
814static void
815remove_ticket_cont (void *cls, int32_t success, const char *emsg)
816{
817 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
818
819 rvk->ns_qe = NULL;
820 if (GNUNET_SYSERR == success)
821 {
822 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
823 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
824 cleanup_rvk (rvk);
825 return;
826 }
827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted ticket\n");
828 if (0 == rvk->ticket_attrs)
829 {
830 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
831 "No attributes to move... strange\n");
832 rvk->cb (rvk->cb_cls, GNUNET_OK);
833 cleanup_rvk (rvk);
834 return;
835 }
836 rvk->move_attr = rvk->attrs_head;
837 move_attrs (rvk);
838}
839
840
841/**
842 * We found the attribute references.
843 * Store them for later and remove the record set.
844 *
845 * @param cls handle to the operation
846 * @param zone the issuer key
847 * @param label ticket rnd
848 * @param rd_cound size of record set
849 * @param rd record set
850 */
851static void
852revoke_attrs_cb (void *cls,
853 const struct GNUNET_IDENTITY_PrivateKey *zone,
854 const char *label,
855 unsigned int rd_count,
856 const struct GNUNET_GNSRECORD_Data *rd)
857
858{
859 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
860 struct RevokedAttributeEntry *le;
861
862 rvk->ns_qe = NULL;
863 /**
864 * Temporarily store attribute references.
865 * We need it later.
866 */
867 for (int i = 0; i < rd_count; i++)
868 {
869 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
870 continue;
871 le = GNUNET_new (struct RevokedAttributeEntry);
872 le->old_id = *((struct GNUNET_RECLAIM_Identifier *) rd[i].data);
873 GNUNET_CONTAINER_DLL_insert (rvk->attrs_head, rvk->attrs_tail, le);
874 rvk->ticket_attrs++;
875 }
876
877 /** Remove attribute references **/
878 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
879 &rvk->identity,
880 label,
881 0,
882 NULL,
883 &remove_ticket_cont,
884 rvk);
885}
886
887
888/**
889 * Failed to query namestore. Abort operation
890 *
891 * @param cls handle to the operation
892 */
893static void
894rvk_attrs_err_cb (void *cls)
895{
896 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
897
898 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
899 cleanup_rvk (rvk);
900}
901
902
903/**
904 * Revoke a ticket.
905 * We start by looking up attribute references in order
906 * to change attribute IDs.
907 *
908 * @param ticket ticket to revoke
909 * @param identity private key of issuer
910 * @param cb revocation status callback
911 * @param cb_cls callback closure
912 * @return handle to the operation
913 */
914struct RECLAIM_TICKETS_RevokeHandle *
915RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket,
916 const struct GNUNET_IDENTITY_PrivateKey *identity,
917 RECLAIM_TICKETS_RevokeCallback cb,
918 void *cb_cls)
919{
920 struct RECLAIM_TICKETS_RevokeHandle *rvk;
921 char *label;
922
923 rvk = GNUNET_new (struct RECLAIM_TICKETS_RevokeHandle);
924 rvk->cb = cb;
925 rvk->cb_cls = cb_cls;
926 rvk->identity = *identity;
927 rvk->ticket = *ticket;
928 GNUNET_IDENTITY_key_get_public (&rvk->identity, &rvk->ticket.identity);
929 /** Get shared attributes **/
930 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
931 sizeof(ticket->rnd));
932 GNUNET_assert (NULL != label);
933 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
934 identity,
935 label,
936 &rvk_attrs_err_cb,
937 rvk,
938 &revoke_attrs_cb,
939 rvk);
940 GNUNET_free (label);
941 return rvk;
942}
943
944
945/**
946 * Cancel a revocation.
947 *
948 * @param rh handle to the operation
949 */
950void
951RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh)
952{
953 GNUNET_assert (NULL != rh);
954 cleanup_rvk (rh);
955}
956
957
958/*******************************
959* Ticket consume
960*******************************/
961
962/**
963 * Cleanup ticket consume handle
964 *
965 * @param cth the handle to clean up
966 */
967static void
968cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
969{
970 struct ParallelLookup *lu;
971
972 if (NULL != cth->lookup_request)
973 GNUNET_GNS_lookup_cancel (cth->lookup_request);
974 if (NULL != cth->kill_task)
975 GNUNET_SCHEDULER_cancel (cth->kill_task);
976 while (NULL != (lu = cth->parallel_lookups_head))
977 {
978 if (NULL != lu->lookup_request)
979 GNUNET_GNS_lookup_cancel (lu->lookup_request);
980 GNUNET_free (lu->label);
981 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
982 cth->parallel_lookups_tail,
983 lu);
984 GNUNET_free (lu);
985 }
986
987 if (NULL != cth->attrs)
988 GNUNET_RECLAIM_attribute_list_destroy (cth->attrs);
989 if (NULL != cth->presentations)
990 GNUNET_RECLAIM_presentation_list_destroy (cth->presentations);
991 GNUNET_free (cth);
992}
993
994
995/**
996 * We found an attribute record.
997 *
998 * @param cls handle to the operation
999 * @param rd_cound size of record set
1000 * @param rd record set
1001 */
1002static void
1003process_parallel_lookup_result (void *cls,
1004 uint32_t rd_count,
1005 const struct GNUNET_GNSRECORD_Data *rd)
1006{
1007 struct ParallelLookup *parallel_lookup = cls;
1008 struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle;
1009 struct GNUNET_RECLAIM_AttributeListEntry *attr_le;
1010
1011 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1012 "Parallel lookup finished (count=%u)\n",
1013 rd_count);
1014
1015 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
1016 cth->parallel_lookups_tail,
1017 parallel_lookup);
1018 GNUNET_free (parallel_lookup->label);
1019
1020 GNUNET_STATISTICS_update (stats,
1021 "attribute_lookup_time_total",
1022 GNUNET_TIME_absolute_get_duration (
1023 parallel_lookup->lookup_start_time)
1024 .rel_value_us,
1025 GNUNET_YES);
1026 GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES);
1027
1028
1029 GNUNET_free (parallel_lookup);
1030 if (0 == rd_count)
1031 GNUNET_break (0);
1032 // REMARK: It is possible now to find rd_count > 1
1033 for (int i = 0; i < rd_count; i++)
1034 {
1035 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type)
1036 continue;
1037 attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1038 GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size,
1039 &attr_le->attribute);
1040 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
1041 cth->attrs->list_tail,
1042 attr_le);
1043 }
1044 if (NULL != cth->parallel_lookups_head)
1045 return; // Wait for more
1046 /* Else we are done */
1047 cth->cb (cth->cb_cls, &cth->ticket.identity,
1048 cth->attrs, cth->presentations, GNUNET_OK, NULL);
1049 cleanup_cth (cth);
1050}
1051
1052
1053/**
1054 * Cancel the lookups for attribute records
1055 *
1056 * @param cls handle to the operation
1057 */
1058static void
1059abort_parallel_lookups (void *cls)
1060{
1061 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
1062 struct ParallelLookup *lu;
1063 struct ParallelLookup *tmp;
1064
1065 cth->kill_task = NULL;
1066 for (lu = cth->parallel_lookups_head; NULL != lu;)
1067 {
1068 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1069 GNUNET_free (lu->label);
1070 tmp = lu->next;
1071 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
1072 cth->parallel_lookups_tail,
1073 lu);
1074 GNUNET_free (lu);
1075 lu = tmp;
1076 }
1077 cth->cb (cth->cb_cls, NULL, NULL, NULL, GNUNET_SYSERR, "Aborted");
1078}
1079
1080
1081/**
1082 * GNS result with attribute references.
1083 * For each result, we start a (parallel) lookup of the actual
1084 * attribute record under the referenced label.
1085 *
1086 * @param cls handle to the operation
1087 * @param rd_cound size of the record set
1088 * @param rd record set
1089 */
1090static void
1091lookup_authz_cb (void *cls,
1092 uint32_t rd_count,
1093 const struct GNUNET_GNSRECORD_Data *rd)
1094{
1095 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
1096 struct ParallelLookup *parallel_lookup;
1097 char *lbl;
1098 struct GNUNET_RECLAIM_PresentationListEntry *ale;
1099
1100 cth->lookup_request = NULL;
1101
1102 GNUNET_STATISTICS_update (stats,
1103 "reclaim_authz_lookup_time_total",
1104 GNUNET_TIME_absolute_get_duration (
1105 cth->lookup_start_time)
1106 .rel_value_us,
1107 GNUNET_YES);
1108 GNUNET_STATISTICS_update (stats,
1109 "reclaim_authz_lookups_count",
1110 1,
1111 GNUNET_YES);
1112
1113 for (int i = 0; i < rd_count; i++)
1114 {
1115 /**
1116 * Check if record is a credential presentation or an attribute
1117 * reference.
1118 */
1119 switch (rd[i].record_type)
1120 {
1121 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
1122 ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1123 ale->presentation =
1124 GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1125 rd[i].data_size);
1126 GNUNET_CONTAINER_DLL_insert (cth->presentations->list_head,
1127 cth->presentations->list_tail,
1128 ale);
1129 break;
1130 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
1131 lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
1132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl);
1133 parallel_lookup = GNUNET_new (struct ParallelLookup);
1134 parallel_lookup->handle = cth;
1135 parallel_lookup->label = lbl;
1136 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
1137 parallel_lookup->lookup_request =
1138 GNUNET_GNS_lookup (gns,
1139 lbl,
1140 &cth->ticket.identity,
1141 GNUNET_GNSRECORD_TYPE_ANY,
1142 GNUNET_GNS_LO_DEFAULT,
1143 &process_parallel_lookup_result,
1144 parallel_lookup);
1145 GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
1146 cth->parallel_lookups_tail,
1147 parallel_lookup);
1148 break;
1149 default:
1150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1151 "Ignoring unknown record type %d", rd[i].record_type);
1152 }
1153 }
1154 /**
1155 * We started lookups. Add a timeout task.
1156 * FIXME: Really needed here?
1157 */
1158 if (NULL != cth->parallel_lookups_head)
1159 {
1160 cth->kill_task = GNUNET_SCHEDULER_add_delayed (
1161 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3),
1162 &abort_parallel_lookups,
1163 cth);
1164 return;
1165 }
1166 /**
1167 * No references found, return empty attribute list
1168 */
1169 cth->cb (cth->cb_cls, &cth->ticket.identity,
1170 cth->attrs, NULL, GNUNET_OK, NULL);
1171 cleanup_cth (cth);
1172}
1173
1174
1175/**
1176 * Consume a ticket.
1177 * We first looking attribute references under the label
1178 * ticket.rnd in GNS.
1179 *
1180 * @param id the audience of the ticket
1181 * @param ticket the ticket to consume
1182 * @param cb callback to call with attributes of ticket
1183 * @param cb_cls callback closure
1184 * @return handle to the operation
1185 */
1186struct RECLAIM_TICKETS_ConsumeHandle *
1187RECLAIM_TICKETS_consume (const struct GNUNET_IDENTITY_PrivateKey *id,
1188 const struct GNUNET_RECLAIM_Ticket *ticket,
1189 RECLAIM_TICKETS_ConsumeCallback cb,
1190 void *cb_cls)
1191{
1192 struct RECLAIM_TICKETS_ConsumeHandle *cth;
1193 char *label;
1194
1195 cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle);
1196
1197 cth->identity = *id;
1198 GNUNET_IDENTITY_key_get_public (&cth->identity, &cth->identity_pub);
1199 cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1200 cth->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1201 cth->ticket = *ticket;
1202 cth->cb = cb;
1203 cth->cb_cls = cb_cls;
1204 label =
1205 GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd,
1206 sizeof(cth->ticket.rnd));
1207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1208 "Looking for AuthZ info under %s\n",
1209 label);
1210 cth->lookup_start_time = GNUNET_TIME_absolute_get ();
1211 cth->lookup_request =
1212 GNUNET_GNS_lookup (gns,
1213 label,
1214 &cth->ticket.identity,
1215 GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF,
1216 GNUNET_GNS_LO_DEFAULT,
1217 &lookup_authz_cb,
1218 cth);
1219 GNUNET_free (label);
1220 return cth;
1221}
1222
1223
1224/**
1225 * Cancel a consume operation
1226 *
1227 * @param cth the operation to cancel
1228 */
1229void
1230RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
1231{
1232 cleanup_cth (cth);
1233 return;
1234}
1235
1236
1237/*******************************
1238 * Ticket issue
1239 *******************************/
1240
1241/**
1242 * Cleanup ticket consume handle
1243 * @param handle the handle to clean up
1244 */
1245static void
1246cleanup_issue_handle (struct TicketIssueHandle *handle)
1247{
1248 if (NULL != handle->ns_qe)
1249 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1250 GNUNET_free (handle);
1251}
1252
1253
1254/**
1255 * Store finished, abort on error.
1256 * Else, return new ticket to caller.
1257 *
1258 * @param cls handle to the operation
1259 * @param success store operation result
1260 * @param emsg error message (or NULL on success)
1261 */
1262static void
1263store_ticket_issue_cont (void *cls, int32_t success, const char *emsg)
1264{
1265 struct TicketIssueHandle *handle = cls;
1266
1267 handle->ns_qe = NULL;
1268 if (GNUNET_SYSERR == success)
1269 {
1270 handle->cb (handle->cb_cls,
1271 &handle->ticket,
1272 NULL,
1273 GNUNET_SYSERR,
1274 "Error storing AuthZ ticket in GNS");
1275 return;
1276 }
1277 handle->cb (handle->cb_cls,
1278 &handle->ticket,
1279 handle->presentations,
1280 GNUNET_OK, NULL);
1281 cleanup_issue_handle (handle);
1282}
1283
1284
1285/**
1286 * Issue a new ticket.
1287 * We store references to attribute record labels and the ticket itself
1288 * under the label base64(ticket.rnd).
1289 *
1290 * @param ih handle to the operation containing relevant metadata
1291 */
1292static void
1293issue_ticket (struct TicketIssueHandle *ih)
1294{
1295 struct GNUNET_RECLAIM_AttributeListEntry *le;
1296 struct GNUNET_RECLAIM_PresentationListEntry *ple;
1297 struct GNUNET_GNSRECORD_Data *attrs_record;
1298 char *label;
1299 int i;
1300 int j;
1301 int attrs_count = 0;
1302
1303 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1304 attrs_count++;
1305
1306 // Worst case we have one presentation per attribute
1307 attrs_record =
1308 GNUNET_malloc (2 * attrs_count * sizeof(struct GNUNET_GNSRECORD_Data));
1309 i = 0;
1310 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1311 {
1312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1313 "Adding list entry: %s\n", le->attribute->name);
1314
1315 attrs_record[i].data = &le->attribute->id;
1316 attrs_record[i].data_size = sizeof(le->attribute->id);
1317 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1318 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF;
1319 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1320 i++;
1321 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
1322 {
1323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1324 "Attribute is backed by credential. Adding...\n");
1325 struct GNUNET_RECLAIM_Presentation *pres = NULL;
1326 for (j = 0; j < i; j++)
1327 {
1328 if (attrs_record[j].record_type
1329 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
1330 continue;
1331 pres = GNUNET_RECLAIM_presentation_deserialize (attrs_record[j].data,
1332 attrs_record[j].
1333 data_size);
1334 if (NULL == pres)
1335 {
1336 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1337 "Failed to deserialize presentation\n");
1338 continue;
1339 }
1340 if (0 == memcmp (&pres->credential_id,
1341 &le->attribute->credential,
1342 sizeof (le->attribute->credential)))
1343 break;
1344 GNUNET_free (pres);
1345 pres = NULL;
1346 }
1347 if (NULL != pres)
1348 {
1349 GNUNET_free (pres);
1350 continue; // Skip as we have already added this credential presentation.
1351 }
1352 for (ple = ih->presentations->list_head; NULL != ple; ple = ple->next)
1353 {
1354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1355 "Checking presentation....\n");
1356
1357 if (0 != memcmp (&le->attribute->credential,
1358 &ple->presentation->credential_id,
1359 sizeof (le->attribute->credential)))
1360 {
1361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1362 "Presentation does not match credential ID.\n");
1363 continue;
1364 }
1365 char *pres_buf;
1366 size_t pres_size;
1367 pres_size =
1368 GNUNET_RECLAIM_presentation_serialize_get_size (ple->presentation);
1369 pres_buf = GNUNET_malloc (pres_size);
1370 GNUNET_RECLAIM_presentation_serialize (ple->presentation,
1371 pres_buf);
1372 attrs_record[i].data = pres_buf;
1373 attrs_record[i].data_size = pres_size;
1374 attrs_record[i].expiration_time =
1375 ticket_refresh_interval.rel_value_us;
1376 attrs_record[i].record_type =
1377 GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION;
1378 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1379 i++;
1380 break;
1381 }
1382 }
1383 }
1384 attrs_record[i].data = &ih->ticket;
1385 attrs_record[i].data_size = sizeof(struct GNUNET_RECLAIM_Ticket);
1386 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1387 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET;
1388 attrs_record[i].flags =
1389 GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
1390 i++;
1391
1392 label =
1393 GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
1394 sizeof(ih->ticket.rnd));
1395 // Publish record
1396 ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1397 &ih->identity,
1398 label,
1399 i,
1400 attrs_record,
1401 &store_ticket_issue_cont,
1402 ih);
1403 for (j = 0; j > i; j++)
1404 {
1405 if (attrs_record[j].record_type
1406 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
1407 continue;
1408 // Yes, we are allowed to do this because we allocated it above
1409 char *ptr = (char*) attrs_record[j].data;
1410 GNUNET_free (ptr);
1411 }
1412 GNUNET_free (attrs_record);
1413 GNUNET_free (label);
1414}
1415
1416
1417/*************************************************
1418 * Ticket iteration (finding a specific ticket)
1419 *************************************************/
1420
1421
1422/**
1423 * Namestore error on issue. Abort.
1424 *
1425 * @param cls handle to the operation
1426 */
1427static void
1428filter_tickets_error_cb (void *cls)
1429{
1430 struct TicketIssueHandle *tih = cls;
1431
1432 tih->ns_it = NULL;
1433 tih->cb (tih->cb_cls,
1434 &tih->ticket,
1435 NULL,
1436 GNUNET_SYSERR,
1437 "Error storing AuthZ ticket in GNS");
1438 cleanup_issue_handle (tih);
1439}
1440
1441
1442/**
1443 * Iterator over records.
1444 * Check if any previously issued ticket already
1445 * matches what we need to prevent duplicates and
1446 * improve resolution synergy.
1447 *
1448 * @param cls handle to the operation
1449 * @param zone issuer identity
1450 * @param label ticket rnd
1451 * @param rd_count size of record set
1452 * @param rd record set
1453 */
1454static void
1455filter_tickets_cb (void *cls,
1456 const struct GNUNET_IDENTITY_PrivateKey *zone,
1457 const char *label,
1458 unsigned int rd_count,
1459 const struct GNUNET_GNSRECORD_Data *rd)
1460{
1461 struct TicketIssueHandle *tih = cls;
1462 struct GNUNET_RECLAIM_Ticket *ticket = NULL;
1463 struct GNUNET_RECLAIM_Presentation *pres;
1464 struct GNUNET_RECLAIM_PresentationList *ticket_presentations;
1465 struct GNUNET_RECLAIM_Credential *cred;
1466 struct GNUNET_RECLAIM_PresentationListEntry *ple;
1467 struct GNUNET_RECLAIM_AttributeListEntry *le;
1468 unsigned int attr_cnt = 0;
1469 unsigned int pres_cnt = 0;
1470
1471 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1472 {
1473 attr_cnt++;
1474 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
1475 pres_cnt++;
1476 }
1477
1478 // ticket search
1479 unsigned int found_attrs_cnt = 0;
1480 unsigned int found_pres_cnt = 0;
1481 ticket_presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1482
1483 for (int i = 0; i < rd_count; i++)
1484 {
1485 // found ticket
1486 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET == rd[i].record_type)
1487 {
1488 ticket = (struct GNUNET_RECLAIM_Ticket *) rd[i].data;
1489 // cmp audience
1490 if (0 == memcmp (&tih->ticket.audience,
1491 &ticket->audience,
1492 sizeof(struct GNUNET_IDENTITY_PublicKey)))
1493 {
1494 tih->ticket = *ticket;
1495 continue;
1496 }
1497 ticket = NULL;
1498 }
1499
1500 // cmp requested attributes with ticket attributes
1501 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1502 {
1503 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1504 {
1505 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1506 &le->attribute->id))
1507 found_attrs_cnt++;
1508 }
1509 }
1510 if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
1511 {
1512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1513 "Found credential...\n");
1514
1515 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1516 {
1517 cred = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
1518 rd[i].data_size);
1519 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (&cred->id,
1520 &le->attribute->credential))
1521 {
1522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1523 "No match.\n");
1524 GNUNET_free (cred);
1525 continue;
1526 }
1527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1528 "Match, creating presentation...\n");
1529 if (GNUNET_OK != GNUNET_RECLAIM_credential_get_presentation (
1530 cred,
1531 tih->attrs,
1532 &pres))
1533 {
1534 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1535 "Unable to retrieve presentation from credential\n");
1536 GNUNET_free (cred);
1537 continue;
1538 }
1539 ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1540 ple->presentation = pres;
1541 GNUNET_CONTAINER_DLL_insert (tih->presentations->list_head,
1542 tih->presentations->list_tail,
1543 ple);
1544 GNUNET_free (cred);
1545 }
1546 }
1547 if (GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION == rd[i].record_type)
1548 {
1549 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1550 {
1551 pres = GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1552 rd[i].data_size);
1553 if (NULL == pres)
1554 {
1555 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1556 "Failed to deserialize presentation\n");
1557 continue;
1558 }
1559 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&pres->credential_id,
1560 &le->attribute->credential))
1561 {
1562 found_pres_cnt++;
1563 ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1564 ple->presentation = pres;
1565 GNUNET_CONTAINER_DLL_insert (ticket_presentations->list_head,
1566 ticket_presentations->list_tail,
1567 ple);
1568 }
1569 }
1570 }
1571 }
1572
1573 /**
1574 * If we found a matching ticket, return that to the caller and
1575 * we are done.
1576 */
1577 if ((attr_cnt == found_attrs_cnt) &&
1578 (pres_cnt == found_pres_cnt) &&
1579 (NULL != ticket))
1580 {
1581 GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it);
1582 tih->cb (tih->cb_cls, &tih->ticket, ticket_presentations, GNUNET_OK, NULL);
1583 GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
1584 cleanup_issue_handle (tih);
1585 return;
1586 }
1587
1588 // ticket not found in current record, checking next record set
1589 GNUNET_NAMESTORE_zone_iterator_next (tih->ns_it, 1);
1590}
1591
1592
1593/**
1594 * Done iterating over tickets and we apparently did
1595 * not find an existing, matching ticket.
1596 * Continue by issuing a new ticket.
1597 *
1598 * @param cls handle to the operation
1599 */
1600static void
1601filter_tickets_finished_cb (void *cls)
1602{
1603 struct TicketIssueHandle *tih = cls;
1604
1605 GNUNET_IDENTITY_key_get_public (&tih->identity, &tih->ticket.identity);
1606 GNUNET_RECLAIM_id_generate (&tih->ticket.rnd);
1607 issue_ticket (tih);
1608}
1609
1610
1611/**
1612 * Issue a new reclaim ticket, thereby authorizing
1613 * the audience to access the set of provided attributes.
1614 *
1615 * @param identity the issuer
1616 * @param attrs the attributes to share
1617 * @param audience the audience to share the attributes with
1618 * @param cb the callback to call with the ticket result
1619 * @param cb_cls the callback closure
1620 * FIXME: Return handle??
1621 */
1622void
1623RECLAIM_TICKETS_issue (const struct GNUNET_IDENTITY_PrivateKey *identity,
1624 const struct GNUNET_RECLAIM_AttributeList *attrs,
1625 const struct GNUNET_IDENTITY_PublicKey *audience,
1626 RECLAIM_TICKETS_TicketResult cb,
1627 void *cb_cls)
1628{
1629 struct TicketIssueHandle *tih;
1630
1631 tih = GNUNET_new (struct TicketIssueHandle);
1632 tih->cb = cb;
1633 tih->cb_cls = cb_cls;
1634 tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs);
1635 tih->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1636 tih->identity = *identity;
1637 tih->ticket.audience = *audience;
1638
1639 // First check whether the ticket has already been issued
1640 tih->ns_it =
1641 GNUNET_NAMESTORE_zone_iteration_start (nsh,
1642 &tih->identity,
1643 &filter_tickets_error_cb,
1644 tih,
1645 &filter_tickets_cb,
1646 tih,
1647 &filter_tickets_finished_cb,
1648 tih);
1649}
1650
1651
1652/************************************
1653 * Ticket iteration
1654 ************************************/
1655
1656/**
1657 * Cleanup ticket iterator
1658 *
1659 * @param iter handle to the iteration
1660 */
1661static void
1662cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter)
1663{
1664 if (NULL != iter->ns_it)
1665 GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it);
1666 GNUNET_free (iter);
1667}
1668
1669
1670/**
1671 * Return each record of type @GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET
1672 * to the caller and proceed with the iteration.
1673 * FIXME: Should we _not_ proceed automatically here?
1674 *
1675 * @param cls handle to the iteration
1676 * @param zone the ticket issuer
1677 * @param label the ticket rnd
1678 * @param rd_count number of records in record set
1679 * @param rd record set containing a ticket
1680 */
1681static void
1682collect_tickets_cb (void *cls,
1683 const struct GNUNET_IDENTITY_PrivateKey *zone,
1684 const char *label,
1685 unsigned int rd_count,
1686 const struct GNUNET_GNSRECORD_Data *rd)
1687{
1688 struct RECLAIM_TICKETS_Iterator *iter = cls;
1689
1690 for (int i = 0; i < rd_count; i++)
1691 {
1692 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET != rd[i].record_type)
1693 continue;
1694 iter->cb (iter->cb_cls, (struct GNUNET_RECLAIM_Ticket *) rd[i].data);
1695 return;
1696 }
1697 GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1);
1698}
1699
1700
1701/**
1702 * Signal ticket iteration has finished
1703 *
1704 * @param cls handle to the iteration
1705 */
1706static void
1707collect_tickets_finished_cb (void *cls)
1708{
1709 struct RECLAIM_TICKETS_Iterator *iter = cls;
1710
1711 iter->ns_it = NULL;
1712 iter->cb (iter->cb_cls, NULL);
1713 cleanup_iter (iter);
1714}
1715
1716
1717/**
1718 * Cancel ticket iteration on namestore error
1719 *
1720 * @param cls the iteration handle
1721 */
1722static void
1723collect_tickets_error_cb (void *cls)
1724{
1725 struct RECLAIM_TICKETS_Iterator *iter = cls;
1726
1727 iter->ns_it = NULL;
1728 iter->cb (iter->cb_cls, NULL);
1729 cleanup_iter (iter);
1730}
1731
1732
1733/**
1734 * Continue ticket iteration
1735 *
1736 * @param iter the iteration to continue
1737 */
1738void
1739RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter)
1740{
1741 GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1);
1742}
1743
1744
1745/**
1746 * Stop a running ticket iteration
1747 *
1748 * @param iter iteration to cancel
1749 */
1750void
1751RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter)
1752{
1753 GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it);
1754 cleanup_iter (iter);
1755}
1756
1757
1758/**
1759 * Iterate over all tickets issued by an identity
1760 *
1761 * @param identity the issuing identity
1762 * @param cb ticket callback function
1763 * @param cb_cls callback closure
1764 * @return a handle to the iteration
1765 */
1766struct RECLAIM_TICKETS_Iterator *
1767RECLAIM_TICKETS_iteration_start (
1768 const struct GNUNET_IDENTITY_PrivateKey *identity,
1769 RECLAIM_TICKETS_TicketIter cb,
1770 void *cb_cls)
1771{
1772 struct RECLAIM_TICKETS_Iterator *iter;
1773
1774 iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator);
1775 iter->cb = cb;
1776 iter->cb_cls = cb_cls;
1777 iter->ns_it =
1778 GNUNET_NAMESTORE_zone_iteration_start (nsh,
1779 identity,
1780 &collect_tickets_error_cb,
1781 iter,
1782 &collect_tickets_cb,
1783 iter,
1784 &collect_tickets_finished_cb,
1785 iter);
1786 return iter;
1787}
1788
1789
1790/**
1791 * Initialize tickets component
1792 *
1793 * @param c the configuration
1794 * @return GNUNET_SYSERR on error
1795 */
1796int
1797RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
1798{
1799 // Get ticket expiration time (relative) from config
1800 if (GNUNET_OK ==
1801 GNUNET_CONFIGURATION_get_value_time (c,
1802 "reclaim",
1803 "TICKET_REFRESH_INTERVAL",
1804 &ticket_refresh_interval))
1805 {
1806 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1807 "Configured refresh interval for tickets: %s\n",
1808 GNUNET_STRINGS_relative_time_to_string (ticket_refresh_interval,
1809 GNUNET_YES));
1810 }
1811 else
1812 {
1813 ticket_refresh_interval = DEFAULT_TICKET_REFRESH_INTERVAL;
1814 }
1815 // Connect to identity and namestore services
1816 nsh = GNUNET_NAMESTORE_connect (c);
1817 if (NULL == nsh)
1818 {
1819 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1820 "error connecting to namestore");
1821 return GNUNET_SYSERR;
1822 }
1823 gns = GNUNET_GNS_connect (c);
1824 if (NULL == gns)
1825 {
1826 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1827 return GNUNET_SYSERR;
1828 }
1829 stats = GNUNET_STATISTICS_create ("reclaim", c);
1830 return GNUNET_OK;
1831}
1832
1833
1834/**
1835 * Close handles and clean up.
1836 * FIXME: cancel all pending operations (gns, ns etc)
1837 */
1838void
1839RECLAIM_TICKETS_deinit (void)
1840{
1841 if (NULL != nsh)
1842 GNUNET_NAMESTORE_disconnect (nsh);
1843 nsh = NULL;
1844 if (NULL != gns)
1845 GNUNET_GNS_disconnect (gns);
1846 gns = NULL;
1847 if (NULL != stats)
1848 {
1849 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
1850 stats = NULL;
1851 }
1852}
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.h b/src/reclaim/gnunet-service-reclaim_tickets.h
deleted file mode 100644
index 9c31a6143..000000000
--- a/src/reclaim/gnunet-service-reclaim_tickets.h
+++ /dev/null
@@ -1,280 +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/**
22 * @author Martin Schanzenbach
23 * @file src/reclaim/gnunet-service-reclaim_tickets.h
24 * @brief reclaim tickets
25 *
26 */
27
28#ifndef GNUNET_SERVICE_RECLAIM_TICKETS_H
29#define GNUNET_SERVICE_RECLAIM_TICKETS_H
30
31#include "platform.h"
32
33#include "gnunet_util_lib.h"
34
35#include "gnunet_constants.h"
36#include "gnunet_gns_service.h"
37#include "gnunet_gnsrecord_lib.h"
38#include "gnunet_protocols.h"
39#include "gnunet_reclaim_lib.h"
40#include "gnunet_reclaim_service.h"
41#include "gnunet_signatures.h"
42#include "gnunet_statistics_service.h"
43#include "reclaim.h"
44
45/**
46 * Ticket iterator
47 */
48struct RECLAIM_TICKETS_Iterator;
49
50
51/**
52 * Handle to a consume operation
53 */
54struct RECLAIM_TICKETS_ConsumeHandle;
55
56
57/**
58 * Ticket revocation request handle
59 */
60struct RECLAIM_TICKETS_RevokeHandle;
61
62
63/**
64 * List of tickets
65 */
66struct TicketRecordsEntry
67{
68 /**
69 * DLL
70 */
71 struct TicketRecordsEntry *next;
72
73 /**
74 * DLL
75 */
76 struct TicketRecordsEntry *prev;
77
78 /**
79 * Record count
80 */
81 unsigned int rd_count;
82
83 /**
84 * Data
85 */
86 char *data;
87
88 /**
89 * Data size
90 */
91 size_t data_size;
92
93 /**
94 * Label
95 */
96 char *label;
97};
98
99
100/**
101 * Continuation called with ticket.
102 *
103 * @param cls closure
104 * @param ticket the ticket
105 */
106typedef void (*RECLAIM_TICKETS_TicketIter) (
107 void *cls,
108 struct GNUNET_RECLAIM_Ticket *ticket);
109
110
111/**
112 * Continuation called with ticket.
113 *
114 * @param cls closure
115 * @param ticket the ticket
116 * @param presentations new presentations for ticket (NULL on error)
117 * @param success #GNUNET_SYSERR on failure (including timeout/queue
118 * drop/failure to validate) #GNUNET_OK on success
119 * @param emsg NULL on success, otherwise an error message
120 */
121typedef void (*RECLAIM_TICKETS_TicketResult) (
122 void *cls,
123 struct GNUNET_RECLAIM_Ticket *ticket,
124 struct GNUNET_RECLAIM_PresentationList *presentations,
125 int32_t success,
126 const char *emsg);
127
128
129/**
130 * Consume callback.
131 *
132 * @param cls closure
133 * @param identity the issuer of the ticket/attributes
134 * @param attributes attribute list retrieved through ticket
135 * @param presentations attribute presentations (may be NULL)
136 * @param success GNUNET_OK on success
137 * @param emsg error message (NULL on success)
138 */
139typedef void (*RECLAIM_TICKETS_ConsumeCallback) (
140 void *cls,
141 const struct GNUNET_IDENTITY_PublicKey *identity,
142 const struct GNUNET_RECLAIM_AttributeList *attributes,
143 const struct GNUNET_RECLAIM_PresentationList *presentations,
144 int32_t success,
145 const char *emsg);
146
147
148/**
149 * Revocation callback.
150 *
151 * @param cls closure
152 * @param success GNUNET_OK on success
153 */
154typedef void (*RECLAIM_TICKETS_RevokeCallback) (void *cls, int32_t success);
155
156
157/**
158 * Revoke a ticket.
159 * We start by looking up attribute references in order
160 * to change attribute IDs.
161 *
162 * @param ticket ticket to revoke
163 * @param identity private key of issuer
164 * @param cb revocation status callback
165 * @param cb_cls callback closure
166 * @return handle to the operation
167 */
168struct RECLAIM_TICKETS_RevokeHandle *
169RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket,
170 const struct GNUNET_IDENTITY_PrivateKey *identity,
171 RECLAIM_TICKETS_RevokeCallback cb,
172 void *cb_cls);
173
174
175/**
176 * Cancel a revocation.
177 *
178 * @param rh handle to the operation
179 */
180void
181RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh);
182
183
184/**
185 * Consume a ticket.
186 * We first looking attribute references under the label
187 * ticket.rnd in GNS.
188 *
189 * @param id the audience of the ticket
190 * @param ticket the ticket to consume
191 * @param cb callback to call with attributes of ticket
192 * @param cb_cls callback closure
193 * @return handle to the operation
194 */
195struct RECLAIM_TICKETS_ConsumeHandle *
196RECLAIM_TICKETS_consume (const struct GNUNET_IDENTITY_PrivateKey *id,
197 const struct GNUNET_RECLAIM_Ticket *ticket,
198 RECLAIM_TICKETS_ConsumeCallback cb,
199 void *cb_cls);
200
201
202/**
203 * Cancel a consume operation
204 *
205 * @param cth the operation to cancel
206 */
207void
208RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth);
209
210
211/**
212 * Issue a new reclaim ticket, thereby authorizing
213 * the audience to access the set of provided attributes.
214 *
215 * @param identity the issuer
216 * @param attrs the attributes to share
217 * @param audience the audience to share the attributes with
218 * @param cb the callback to call with the ticket result
219 * @param cb_cls the callback closure
220 * FIXME: Return handle??
221 */
222void
223RECLAIM_TICKETS_issue (const struct GNUNET_IDENTITY_PrivateKey *identity,
224 const struct GNUNET_RECLAIM_AttributeList *attrs,
225 const struct GNUNET_IDENTITY_PublicKey *audience,
226 RECLAIM_TICKETS_TicketResult cb,
227 void *cb_cls);
228
229
230/**
231 * Continue ticket iteration
232 *
233 * @param iter the iteration to continue
234 */
235void
236RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter);
237
238
239/**
240 * Stop a running ticket iteration
241 *
242 * @param iter iteration to cancel
243 */
244void
245RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter);
246
247
248/**
249 * Iterate over all tickets issued by an identity
250 *
251 * @param identity the issuing identity
252 * @param cb ticket callback function
253 * @param cb_cls callback closure
254 * @return a handle to the iteration
255 */
256struct RECLAIM_TICKETS_Iterator *
257RECLAIM_TICKETS_iteration_start (
258 const struct GNUNET_IDENTITY_PrivateKey *identity,
259 RECLAIM_TICKETS_TicketIter cb,
260 void *cb_cls);
261
262
263/**
264 * Initialize tickets component
265 *
266 * @param c the configuration
267 * @return GNUNET_SYSERR on error
268 */
269int
270RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c);
271
272
273/**
274 * Close handles and clean up.
275 * FIXME: cancel all pending operations (gns, ns etc)
276 */
277void
278RECLAIM_TICKETS_deinit (void);
279
280#endif
diff --git a/src/reclaim/json_reclaim.c b/src/reclaim/json_reclaim.c
deleted file mode 100644
index 8a3479b8a..000000000
--- a/src/reclaim/json_reclaim.c
+++ /dev/null
@@ -1,392 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2018 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/**
22 * @file rest-plugins/json_reclaim.c
23 * @brief JSON handling of reclaim data
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_json_lib.h"
29#include "gnunet_reclaim_lib.h"
30#include "gnunet_reclaim_service.h"
31
32
33/**
34 * Parse given JSON object to a claim
35 *
36 * @param cls closure, NULL
37 * @param root the json object representing data
38 * @param spec where to write the data
39 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
40 */
41static int
42parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
43{
44 struct GNUNET_RECLAIM_Attribute *attr;
45 const char *name_str = NULL;
46 const char *val_str = NULL;
47 const char *type_str = NULL;
48 const char *id_str = NULL;
49 const char *cred_str = NULL;
50 const char *flag_str = NULL;
51 char *data;
52 int unpack_state;
53 uint32_t type;
54 size_t data_size;
55
56 GNUNET_assert (NULL != root);
57
58 if (! json_is_object (root))
59 {
60 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
61 "Error json is not array nor object!\n");
62 return GNUNET_SYSERR;
63 }
64 // interpret single attribute
65 unpack_state = json_unpack (root,
66 "{s:s, s?s, s?s, s:s, s:s, s?s!}",
67 "name",
68 &name_str,
69 "id",
70 &id_str,
71 "credential",
72 &cred_str,
73 "type",
74 &type_str,
75 "value",
76 &val_str,
77 "flag",
78 &flag_str);
79 if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) ||
80 (NULL == type_str))
81 {
82 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
83 "Error json object has a wrong format!\n");
84 return GNUNET_SYSERR;
85 }
86 type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
87 if (GNUNET_SYSERR ==
88 (GNUNET_RECLAIM_attribute_string_to_value (type,
89 val_str,
90 (void **) &data,
91 &data_size)))
92 {
93 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Attribute value invalid!\n");
94 return GNUNET_SYSERR;
95 }
96 attr = GNUNET_RECLAIM_attribute_new (name_str, NULL,
97 type, data, data_size);
98 if ((NULL != cred_str) && (0 != strlen (cred_str)))
99 {
100 GNUNET_STRINGS_string_to_data (cred_str,
101 strlen (cred_str),
102 &attr->credential,
103 sizeof(attr->credential));
104 }
105 if ((NULL == id_str) || (0 == strlen (id_str)))
106 memset (&attr->id, 0, sizeof (attr->id));
107 else
108 GNUNET_STRINGS_string_to_data (id_str,
109 strlen (id_str),
110 &attr->id,
111 sizeof(attr->id));
112
113 *(struct GNUNET_RECLAIM_Attribute **) spec->ptr = attr;
114 return GNUNET_OK;
115}
116
117
118/**
119 * Cleanup data left from parsing RSA public key.
120 *
121 * @param cls closure, NULL
122 * @param[out] spec where to free the data
123 */
124static void
125clean_attr (void *cls, struct GNUNET_JSON_Specification *spec)
126{
127 struct GNUNET_RECLAIM_Attribute **attr;
128
129 attr = (struct GNUNET_RECLAIM_Attribute **) spec->ptr;
130 if (NULL != *attr)
131 {
132 GNUNET_free (*attr);
133 *attr = NULL;
134 }
135}
136
137
138/**
139 * JSON Specification for Reclaim claims.
140 *
141 * @param ticket struct of GNUNET_RECLAIM_Attribute to fill
142 * @return JSON Specification
143 */
144struct GNUNET_JSON_Specification
145GNUNET_RECLAIM_JSON_spec_attribute (struct GNUNET_RECLAIM_Attribute **attr)
146{
147 struct GNUNET_JSON_Specification ret = { .parser = &parse_attr,
148 .cleaner = &clean_attr,
149 .cls = NULL,
150 .field = NULL,
151 .ptr = attr,
152 .ptr_size = 0,
153 .size_ptr = NULL };
154
155 *attr = NULL;
156 return ret;
157}
158
159
160/**
161 * Parse given JSON object to a ticket
162 *
163 * @param cls closure, NULL
164 * @param root the json object representing data
165 * @param spec where to write the data
166 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
167 */
168static int
169parse_ticket (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
170{
171 struct GNUNET_RECLAIM_Ticket *ticket;
172 const char *rnd_str;
173 const char *aud_str;
174 const char *id_str;
175 int unpack_state;
176
177 GNUNET_assert (NULL != root);
178
179 if (! json_is_object (root))
180 {
181 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
182 "Error json is not array nor object!\n");
183 return GNUNET_SYSERR;
184 }
185 // interpret single ticket
186 unpack_state = json_unpack (root,
187 "{s:s, s:s, s:s!}",
188 "rnd",
189 &rnd_str,
190 "audience",
191 &aud_str,
192 "issuer",
193 &id_str);
194 if (0 != unpack_state)
195 {
196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
197 "Error json object has a wrong format!\n");
198 return GNUNET_SYSERR;
199 }
200 ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
201 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (rnd_str,
202 strlen (rnd_str),
203 &ticket->rnd,
204 sizeof(ticket->rnd)))
205 {
206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Rnd invalid\n");
207 GNUNET_free (ticket);
208 return GNUNET_SYSERR;
209 }
210 if (GNUNET_OK !=
211 GNUNET_STRINGS_string_to_data (id_str,
212 strlen (id_str),
213 &ticket->identity,
214 sizeof(
215 struct GNUNET_CRYPTO_EcdsaPublicKey)))
216 {
217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity invalid\n");
218 GNUNET_free (ticket);
219 return GNUNET_SYSERR;
220 }
221
222 if (GNUNET_OK !=
223 GNUNET_STRINGS_string_to_data (aud_str,
224 strlen (aud_str),
225 &ticket->audience,
226 sizeof(struct
227 GNUNET_CRYPTO_EcdsaPublicKey)))
228 {
229 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audience invalid\n");
230 GNUNET_free (ticket);
231 return GNUNET_SYSERR;
232 }
233
234 *(struct GNUNET_RECLAIM_Ticket **) spec->ptr = ticket;
235 return GNUNET_OK;
236}
237
238
239/**
240 * Cleanup data left from parsing RSA public key.
241 *
242 * @param cls closure, NULL
243 * @param[out] spec where to free the data
244 */
245static void
246clean_ticket (void *cls, struct GNUNET_JSON_Specification *spec)
247{
248 struct GNUNET_RECLAIM_Ticket **ticket;
249
250 ticket = (struct GNUNET_RECLAIM_Ticket **) spec->ptr;
251 if (NULL != *ticket)
252 {
253 GNUNET_free (*ticket);
254 *ticket = NULL;
255 }
256}
257
258
259/**
260 * JSON Specification for Reclaim tickets.
261 *
262 * @param ticket struct of GNUNET_RECLAIM_Ticket to fill
263 * @return JSON Specification
264 */
265struct GNUNET_JSON_Specification
266GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket)
267{
268 struct GNUNET_JSON_Specification ret = { .parser = &parse_ticket,
269 .cleaner = &clean_ticket,
270 .cls = NULL,
271 .field = NULL,
272 .ptr = ticket,
273 .ptr_size = 0,
274 .size_ptr = NULL };
275
276 *ticket = NULL;
277 return ret;
278}
279
280
281/**
282 * Parse given JSON object to a credential claim
283 *
284 * @param cls closure, NULL
285 * @param root the json object representing data
286 * @param spec where to write the data
287 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
288 */
289static int
290parse_credential (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
291{
292 struct GNUNET_RECLAIM_Credential *cred;
293 const char *name_str = NULL;
294 const char *val_str = NULL;
295 const char *type_str = NULL;
296 const char *id_str = NULL;
297 char *data;
298 int unpack_state;
299 uint32_t type;
300 size_t data_size;
301
302 GNUNET_assert (NULL != root);
303
304 if (! json_is_object (root))
305 {
306 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
307 "Error json is not array nor object!\n");
308 return GNUNET_SYSERR;
309 }
310 // interpret single attribute
311 unpack_state = json_unpack (root,
312 "{s:s, s?s, s:s, s:s!}",
313 "name",
314 &name_str,
315 "id",
316 &id_str,
317 "type",
318 &type_str,
319 "value",
320 &val_str);
321 if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) ||
322 (NULL == type_str))
323 {
324 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
325 "Error json object has a wrong format!\n");
326 return GNUNET_SYSERR;
327 }
328 type = GNUNET_RECLAIM_credential_typename_to_number (type_str);
329 if (GNUNET_SYSERR ==
330 (GNUNET_RECLAIM_credential_string_to_value (type,
331 val_str,
332 (void **) &data,
333 &data_size)))
334 {
335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Credential value invalid!\n");
336 return GNUNET_SYSERR;
337 }
338 cred = GNUNET_RECLAIM_credential_new (name_str, type, data, data_size);
339 if ((NULL == id_str) || (0 == strlen (id_str)))
340 memset (&cred->id, 0, sizeof (cred->id));
341 else
342 GNUNET_STRINGS_string_to_data (id_str,
343 strlen (id_str),
344 &cred->id,
345 sizeof(cred->id));
346
347 *(struct GNUNET_RECLAIM_Credential **) spec->ptr = cred;
348 return GNUNET_OK;
349}
350
351
352/**
353 * Cleanup data left from parsing RSA public key.
354 *
355 * @param cls closure, NULL
356 * @param[out] spec where to free the data
357 */
358static void
359clean_credential (void *cls, struct GNUNET_JSON_Specification *spec)
360{
361 struct GNUNET_RECLAIM_Credential **attr;
362
363 attr = (struct GNUNET_RECLAIM_Credential **) spec->ptr;
364 if (NULL != *attr)
365 {
366 GNUNET_free (*attr);
367 *attr = NULL;
368 }
369}
370
371
372/**
373 * JSON Specification for credential claims.
374 *
375 * @param attr struct of GNUNET_RECLAIM_Credential to fill
376 * @return JSON Specification
377 */
378struct GNUNET_JSON_Specification
379GNUNET_RECLAIM_JSON_spec_credential (struct
380 GNUNET_RECLAIM_Credential **cred)
381{
382 struct GNUNET_JSON_Specification ret = { .parser = &parse_credential,
383 .cleaner = &clean_credential,
384 .cls = NULL,
385 .field = NULL,
386 .ptr = cred,
387 .ptr_size = 0,
388 .size_ptr = NULL };
389
390 *cred = NULL;
391 return ret;
392}
diff --git a/src/reclaim/json_reclaim.h b/src/reclaim/json_reclaim.h
deleted file mode 100644
index 613ddf873..000000000
--- a/src/reclaim/json_reclaim.h
+++ /dev/null
@@ -1,57 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2018 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/**
22 * @file rest-plugins/json_reclaim.h
23 * @brief JSON handling of reclaim data
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_json_lib.h"
29#include "gnunet_reclaim_service.h"
30#include "gnunet_reclaim_lib.h"
31
32/**
33 * JSON Specification for Reclaim claims.
34 *
35 * @param attr struct of GNUNET_RECLAIM_Attribute to fill
36 * @return JSON Specification
37 */
38struct GNUNET_JSON_Specification
39GNUNET_RECLAIM_JSON_spec_attribute (struct GNUNET_RECLAIM_Attribute **attr);
40
41/**
42 * JSON Specification for Reclaim tickets.
43 *
44 * @param ticket struct of GNUNET_RECLAIM_Ticket to fill
45 * @return JSON Specification
46 */
47struct GNUNET_JSON_Specification
48GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket);
49
50/**
51 * JSON Specification for credentials.
52 *
53 * @param cred struct of GNUNET_RECLAIM_Credential to fill
54 * @return JSON Specification
55 */
56struct GNUNET_JSON_Specification
57GNUNET_RECLAIM_JSON_spec_credential (struct GNUNET_RECLAIM_Credential **cred);
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
deleted file mode 100644
index c6d56e02d..000000000
--- a/src/reclaim/oidc_helper.c
+++ /dev/null
@@ -1,863 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-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/**
22 * @file reclaim/oidc_helper.c
23 * @brief helper library for OIDC related functions
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include <inttypes.h>
28#include <jansson.h>
29#include "gnunet_util_lib.h"
30#include "gnunet_reclaim_lib.h"
31#include "gnunet_reclaim_service.h"
32#include "gnunet_signatures.h"
33#include "oidc_helper.h"
34// #include "benchmark.h"
35#include <gcrypt.h>
36
37GNUNET_NETWORK_STRUCT_BEGIN
38
39/**
40 * The signature used to generate the authorization code
41 */
42struct OIDC_Parameters
43{
44 /**
45 * The reclaim ticket
46 */
47 struct GNUNET_RECLAIM_Ticket ticket;
48
49 /**
50 * The nonce length
51 */
52 uint32_t nonce_len GNUNET_PACKED;
53
54 /**
55 * The length of the PKCE code_challenge
56 */
57 uint32_t code_challenge_len GNUNET_PACKED;
58
59 /**
60 * The length of the attributes list
61 */
62 uint32_t attr_list_len GNUNET_PACKED;
63
64 /**
65 * The length of the presentation list
66 */
67 uint32_t pres_list_len GNUNET_PACKED;
68};
69
70GNUNET_NETWORK_STRUCT_END
71
72/**
73 * Standard claims represented by the "profile" scope in OIDC
74 */
75static char OIDC_profile_claims[14][32] = {
76 "name", "family_name", "given_name", "middle_name", "nickname",
77 "preferred_username", "profile", "picture", "website", "gender", "birthdate",
78 "zoneinfo", "locale", "updated_at"
79};
80
81/**
82 * Standard claims represented by the "email" scope in OIDC
83 */
84static char OIDC_email_claims[2][16] = {
85 "email", "email_verified"
86};
87
88/**
89 * Standard claims represented by the "phone" scope in OIDC
90 */
91static char OIDC_phone_claims[2][32] = {
92 "phone_number", "phone_number_verified"
93};
94
95/**
96 * Standard claims represented by the "address" scope in OIDC
97 */
98static char OIDC_address_claims[5][32] = {
99 "street_address", "locality", "region", "postal_code", "country"
100};
101
102static enum GNUNET_GenericReturnValue
103is_claim_in_address_scope (const char *claim)
104{
105 int i;
106 for (i = 0; i < 5; i++)
107 {
108 if (0 == strcmp (claim, OIDC_address_claims[i]))
109 {
110 return GNUNET_YES;
111 }
112 }
113 return GNUNET_NO;
114}
115
116
117static char *
118create_jwt_header (void)
119{
120 json_t *root;
121 char *json_str;
122
123 root = json_object ();
124 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
125 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
126
127 json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
128 json_decref (root);
129 return json_str;
130}
131
132
133static void
134replace_char (char *str, char find, char replace)
135{
136 char *current_pos = strchr (str, find);
137
138 while (current_pos)
139 {
140 *current_pos = replace;
141 current_pos = strchr (current_pos, find);
142 }
143}
144
145
146// RFC4648
147static void
148fix_base64 (char *str)
149{
150 // Replace + with -
151 replace_char (str, '+', '-');
152
153 // Replace / with _
154 replace_char (str, '/', '_');
155}
156
157
158static json_t*
159generate_userinfo_json (const struct GNUNET_IDENTITY_PublicKey *sub_key,
160 const struct GNUNET_RECLAIM_AttributeList *attrs,
161 const struct
162 GNUNET_RECLAIM_PresentationList *presentations)
163{
164 struct GNUNET_RECLAIM_AttributeListEntry *le;
165 struct GNUNET_RECLAIM_PresentationListEntry *ple;
166 char *subject;
167 char *source_name;
168 char *attr_val_str;
169 char *pres_val_str;
170 json_t *body;
171 json_t *aggr_names;
172 json_t *aggr_sources;
173 json_t *aggr_sources_jwt;
174 json_t *addr_claim = NULL;
175 int num_presentations = 0;
176 for (le = attrs->list_head; NULL != le; le = le->next)
177 {
178 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
179 num_presentations++;
180 }
181
182 subject =
183 GNUNET_STRINGS_data_to_string_alloc (sub_key,
184 sizeof(struct
185 GNUNET_IDENTITY_PublicKey));
186 body = json_object ();
187 aggr_names = json_object ();
188 aggr_sources = json_object ();
189
190 // iss REQUIRED case sensitive server uri with https
191 // The issuer is the local reclaim instance (e.g.
192 // https://reclaim.id/api/openid)
193 json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
194 // sub REQUIRED public key identity, not exceed 255 ASCII length
195 json_object_set_new (body, "sub", json_string (subject));
196 pres_val_str = NULL;
197 source_name = NULL;
198 int i = 0;
199 for (ple = presentations->list_head; NULL != ple; ple = ple->next)
200 {
201 // New presentation
202 GNUNET_asprintf (&source_name,
203 "src%d",
204 i);
205 aggr_sources_jwt = json_object ();
206 pres_val_str =
207 GNUNET_RECLAIM_presentation_value_to_string (ple->presentation->type,
208 ple->presentation->data,
209 ple->presentation->data_size);
210 json_object_set_new (aggr_sources_jwt,
211 GNUNET_RECLAIM_presentation_number_to_typename (
212 ple->presentation->type),
213 json_string (pres_val_str) );
214 json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
215 GNUNET_free (pres_val_str);
216 GNUNET_free (source_name);
217 source_name = NULL;
218 i++;
219 }
220
221 for (le = attrs->list_head; NULL != le; le = le->next)
222 {
223
224 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
225 {
226
227 attr_val_str =
228 GNUNET_RECLAIM_attribute_value_to_string (le->attribute->type,
229 le->attribute->data,
230 le->attribute->data_size);
231 /**
232 * There is this wierd quirk that the individual address claim(s) must be
233 * inside a JSON object of the "address" claim.
234 * FIXME: Possibly include formatted claim here
235 */
236 if (GNUNET_YES == is_claim_in_address_scope (le->attribute->name))
237 {
238 if (NULL == addr_claim)
239 {
240 addr_claim = json_object ();
241 }
242 json_object_set_new (addr_claim, le->attribute->name,
243 json_string (attr_val_str));
244
245 }
246 else
247 {
248 json_object_set_new (body, le->attribute->name,
249 json_string (attr_val_str));
250 }
251 GNUNET_free (attr_val_str);
252 }
253 else
254 {
255 // Check if presentation is there
256 int j = 0;
257 for (ple = presentations->list_head; NULL != ple; ple = ple->next)
258 {
259 if (GNUNET_YES ==
260 GNUNET_RECLAIM_id_is_equal (&ple->presentation->credential_id,
261 &le->attribute->credential))
262 break;
263 j++;
264 }
265 if (NULL == ple)
266 {
267 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
268 "Presentation for `%s' missing...\n",
269 le->attribute->name);
270 continue;
271 }
272 // Presentation exists, hence take the respective source str
273 GNUNET_asprintf (&source_name,
274 "src%d",
275 j);
276 json_object_set_new (aggr_names, le->attribute->data,
277 json_string (source_name));
278 GNUNET_free (source_name);
279 }
280 }
281 if (NULL != addr_claim)
282 json_object_set_new (body, "address", addr_claim);
283 if (0 != i)
284 {
285 json_object_set_new (body, "_claim_names", aggr_names);
286 json_object_set_new (body, "_claim_sources", aggr_sources);
287 }
288
289 return body;
290}
291
292
293/**
294 * Generate userinfo JSON as string
295 *
296 * @param sub_key the subject (user)
297 * @param attrs user attribute list
298 * @param presentations credential presentation list (may be empty)
299 * @return Userinfo JSON
300 */
301char *
302OIDC_generate_userinfo (const struct GNUNET_IDENTITY_PublicKey *sub_key,
303 const struct GNUNET_RECLAIM_AttributeList *attrs,
304 const struct
305 GNUNET_RECLAIM_PresentationList *presentations)
306{
307 char *body_str;
308 json_t*body = generate_userinfo_json (sub_key,
309 attrs,
310 presentations);
311 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
312 json_decref (body);
313 return body_str;
314}
315
316
317/**
318 * Create a JWT from attributes
319 *
320 * @param aud_key the public of the audience
321 * @param sub_key the public key of the subject
322 * @param attrs the attribute list
323 * @param presentations credential presentation list (may be empty)
324 * @param expiration_time the validity of the token
325 * @param secret_key the key used to sign the JWT
326 * @return a new base64-encoded JWT string.
327 */
328char *
329OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key,
330 const struct GNUNET_IDENTITY_PublicKey *sub_key,
331 const struct GNUNET_RECLAIM_AttributeList *attrs,
332 const struct
333 GNUNET_RECLAIM_PresentationList *presentations,
334 const struct GNUNET_TIME_Relative *expiration_time,
335 const char *nonce,
336 const char *secret_key)
337{
338 struct GNUNET_HashCode signature;
339 struct GNUNET_TIME_Absolute exp_time;
340 struct GNUNET_TIME_Absolute time_now;
341 char *audience;
342 char *subject;
343 char *header;
344 char *body_str;
345 char *result;
346 char *header_base64;
347 char *body_base64;
348 char *signature_target;
349 char *signature_base64;
350 json_t *body;
351
352 body = generate_userinfo_json (sub_key,
353 attrs,
354 presentations);
355 // iat REQUIRED time now
356 time_now = GNUNET_TIME_absolute_get ();
357 // exp REQUIRED time expired from config
358 exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
359 // auth_time only if max_age
360 // nonce only if nonce
361 // OPTIONAL acr,amr,azp
362 subject =
363 GNUNET_STRINGS_data_to_string_alloc (sub_key,
364 sizeof(struct
365 GNUNET_IDENTITY_PublicKey));
366 audience =
367 GNUNET_STRINGS_data_to_string_alloc (aud_key,
368 sizeof(struct
369 GNUNET_IDENTITY_PublicKey));
370 header = create_jwt_header ();
371
372 // aud REQUIRED public key client_id must be there
373 json_object_set_new (body, "aud", json_string (audience));
374 // iat
375 json_object_set_new (body,
376 "iat",
377 json_integer (time_now.abs_value_us / (1000 * 1000)));
378 // exp
379 json_object_set_new (body,
380 "exp",
381 json_integer (exp_time.abs_value_us / (1000 * 1000)));
382 // nbf
383 json_object_set_new (body,
384 "nbf",
385 json_integer (time_now.abs_value_us / (1000 * 1000)));
386 // nonce
387 if (NULL != nonce)
388 json_object_set_new (body, "nonce", json_string (nonce));
389
390 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
391 json_decref (body);
392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
393
394 GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
395 fix_base64 (header_base64);
396
397 GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
398 fix_base64 (body_base64);
399
400 GNUNET_free (subject);
401 GNUNET_free (audience);
402
403 /**
404 * Creating the JWT signature. This might not be
405 * standards compliant, check.
406 */
407 GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
408 GNUNET_CRYPTO_hmac_raw (secret_key,
409 strlen (secret_key),
410 signature_target,
411 strlen (signature_target),
412 &signature);
413 GNUNET_STRINGS_base64url_encode ((const char *) &signature,
414 sizeof(struct GNUNET_HashCode),
415 &signature_base64);
416 fix_base64 (signature_base64);
417
418 GNUNET_asprintf (&result,
419 "%s.%s.%s",
420 header_base64,
421 body_base64,
422 signature_base64);
423
424 GNUNET_free (signature_target);
425 GNUNET_free (header);
426 GNUNET_free (body_str);
427 GNUNET_free (signature_base64);
428 GNUNET_free (body_base64);
429 GNUNET_free (header_base64);
430 return result;
431}
432
433
434/**
435 * Builds an OIDC authorization code including
436 * a reclaim ticket and nonce
437 *
438 * @param issuer the issuer of the ticket, used to sign the ticket and nonce
439 * @param ticket the ticket to include in the code
440 * @param attrs list of attributes which are shared
441 * @param presentations credential presentation list (may be empty)
442 * @param nonce the nonce to include in the code
443 * @param code_challenge PKCE code challenge
444 * @return a new authorization code (caller must free)
445 */
446char *
447OIDC_build_authz_code (const struct GNUNET_IDENTITY_PrivateKey *issuer,
448 const struct GNUNET_RECLAIM_Ticket *ticket,
449 const struct GNUNET_RECLAIM_AttributeList *attrs,
450 const struct
451 GNUNET_RECLAIM_PresentationList *presentations,
452 const char *nonce_str,
453 const char *code_challenge)
454{
455 struct OIDC_Parameters params;
456 char *code_payload;
457 char *payload;
458 char *tmp;
459 char *code_str;
460 char *buf_ptr = NULL;
461 size_t payload_len;
462 size_t code_payload_len;
463 size_t attr_list_len = 0;
464 size_t pres_list_len = 0;
465 size_t code_challenge_len = 0;
466 uint32_t nonce_len = 0;
467 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
468
469 /** PLAINTEXT **/
470 // Assign ticket
471 memset (&params, 0, sizeof(params));
472 params.ticket = *ticket;
473 // Assign nonce
474 payload_len = sizeof(struct OIDC_Parameters);
475 if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
476 {
477 nonce_len = strlen (nonce_str);
478 payload_len += nonce_len;
479 }
480 params.nonce_len = htonl (nonce_len);
481 // Assign code challenge
482 if (NULL != code_challenge)
483 code_challenge_len = strlen (code_challenge);
484 payload_len += code_challenge_len;
485 params.code_challenge_len = htonl (code_challenge_len);
486 // Assign attributes
487 if (NULL != attrs)
488 {
489 // Get length
490 attr_list_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
491 params.attr_list_len = htonl (attr_list_len);
492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
493 "Length of serialized attributes: %lu\n",
494 attr_list_len);
495 // Get serialized attributes
496 payload_len += attr_list_len;
497 }
498 if (NULL != presentations)
499 {
500 // Get length
501 pres_list_len =
502 GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
503 params.pres_list_len = htonl (pres_list_len);
504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
505 "Length of serialized presentations: %lu\n",
506 pres_list_len);
507 // Get serialized attributes
508 payload_len += pres_list_len;
509 }
510
511 // Get plaintext length
512 payload = GNUNET_malloc (payload_len);
513 memcpy (payload, &params, sizeof(params));
514 tmp = payload + sizeof(params);
515 if (0 < code_challenge_len)
516 {
517 memcpy (tmp, code_challenge, code_challenge_len);
518 tmp += code_challenge_len;
519 }
520 if (0 < nonce_len)
521 {
522 memcpy (tmp, nonce_str, nonce_len);
523 tmp += nonce_len;
524 }
525 if (0 < attr_list_len)
526 GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp);
527 if (0 < pres_list_len)
528 GNUNET_RECLAIM_presentation_list_serialize (presentations, tmp);
529
530 /** END **/
531
532 // Get length
533 code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
534 + payload_len + sizeof(struct
535 GNUNET_IDENTITY_Signature);
536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
537 "Length of data to encode: %lu\n",
538 code_payload_len);
539
540 // Initialize code payload
541 code_payload = GNUNET_malloc (code_payload_len);
542 GNUNET_assert (NULL != code_payload);
543 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
544 purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
545 + payload_len);
546 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
547 // Store pubkey
548 buf_ptr = (char *) &purpose[1];
549 memcpy (buf_ptr, payload, payload_len);
550 GNUNET_free (payload);
551 buf_ptr += payload_len;
552 // Sign and store signature
553 if (GNUNET_SYSERR ==
554 GNUNET_IDENTITY_sign_ (issuer,
555 purpose,
556 (struct GNUNET_IDENTITY_Signature *)
557 buf_ptr))
558 {
559 GNUNET_break (0);
560 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
561 GNUNET_free (code_payload);
562 return NULL;
563 }
564 GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
565 GNUNET_free (code_payload);
566 return code_str;
567}
568
569
570/**
571 * Parse reclaim ticket and nonce from
572 * authorization code.
573 * This also verifies the signature in the code.
574 *
575 * @param audience the expected audience of the code
576 * @param code the string representation of the code
577 * @param code_verfier PKCE code verifier. Optional, must be provided
578 * if used in request.
579 * @param ticket where to store the ticket
580 * @param attrs the attributes in the code
581 * @param presentations credential presentation list
582 * @param nonce_str where to store the nonce (if contained)
583 * @return GNUNET_OK if successful, else GNUNET_SYSERR
584 */
585int
586OIDC_parse_authz_code (const struct GNUNET_IDENTITY_PublicKey *audience,
587 const char *code,
588 const char *code_verifier,
589 struct GNUNET_RECLAIM_Ticket *ticket,
590 struct GNUNET_RECLAIM_AttributeList **attrs,
591 struct GNUNET_RECLAIM_PresentationList **presentations,
592 char **nonce_str)
593{
594 char *code_payload;
595 char *ptr;
596 char *plaintext;
597 char *attrs_ser;
598 char *presentations_ser;
599 char *expected_code_challenge;
600 char *code_challenge;
601 char *code_verifier_hash;
602 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
603 struct GNUNET_IDENTITY_Signature *signature;
604 uint32_t code_challenge_len;
605 uint32_t attrs_ser_len;
606 uint32_t pres_ser_len;
607 size_t plaintext_len;
608 size_t code_payload_len;
609 uint32_t nonce_len = 0;
610 struct OIDC_Parameters *params;
611
612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
613 code_payload = NULL;
614 code_payload_len =
615 GNUNET_STRINGS_base64url_decode (code, strlen (code),
616 (void **) &code_payload);
617 if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
618 + sizeof(struct OIDC_Parameters)
619 + sizeof(struct GNUNET_IDENTITY_Signature))
620 {
621 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
622 GNUNET_free (code_payload);
623 return GNUNET_SYSERR;
624 }
625
626 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
627 plaintext_len = code_payload_len;
628 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
629 ptr = (char *) &purpose[1];
630 plaintext_len -= sizeof(struct GNUNET_IDENTITY_Signature);
631 plaintext = ptr;
632 ptr += plaintext_len;
633 signature = (struct GNUNET_IDENTITY_Signature *) ptr;
634 params = (struct OIDC_Parameters *) plaintext;
635
636 // cmp code_challenge code_verifier
637 code_challenge_len = ntohl (params->code_challenge_len);
638 code_challenge = ((char *) &params[1]);
639 if (0 != code_challenge_len) /* Only check if this code requires a CV */
640 {
641 if (NULL == code_verifier)
642 {
643 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
644 "Expected code verifier!\n");
645 GNUNET_free (code_payload);
646 return GNUNET_SYSERR;
647 }
648 code_verifier_hash = GNUNET_malloc (256 / 8);
649 // hash code verifier
650 gcry_md_hash_buffer (GCRY_MD_SHA256,
651 code_verifier_hash,
652 code_verifier,
653 strlen (code_verifier));
654 // encode code verifier
655 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
656 &expected_code_challenge);
657 GNUNET_free (code_verifier_hash);
658 if (0 !=
659 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
660 {
661 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
662 "Invalid code verifier! Expected: %s, Got: %.*s\n",
663 expected_code_challenge,
664 code_challenge_len,
665 code_challenge);
666 GNUNET_free (code_payload);
667 GNUNET_free (expected_code_challenge);
668 return GNUNET_SYSERR;
669 }
670 GNUNET_free (expected_code_challenge);
671 }
672 nonce_len = ntohl (params->nonce_len);
673 if (0 != nonce_len)
674 {
675 *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
676 nonce_len);
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
678 }
679
680 // Ticket
681 memcpy (ticket, &params->ticket, sizeof(params->ticket));
682 // Signature
683 // GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
684 if (0 != GNUNET_memcmp (audience, &ticket->audience))
685 {
686 GNUNET_free (code_payload);
687 if (NULL != *nonce_str)
688 GNUNET_free (*nonce_str);
689 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
690 "Audience in ticket does not match client!\n");
691 return GNUNET_SYSERR;
692 }
693 if (GNUNET_OK !=
694 GNUNET_IDENTITY_signature_verify_ (
695 GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN,
696 purpose,
697 signature,
698 &(ticket->identity)))
699 {
700 GNUNET_free (code_payload);
701 if (NULL != *nonce_str)
702 GNUNET_free (*nonce_str);
703 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
704 return GNUNET_SYSERR;
705 }
706 // Attributes
707 attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
708 attrs_ser_len = ntohl (params->attr_list_len);
709 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
710 presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
711 pres_ser_len = ntohl (params->pres_list_len);
712 *presentations =
713 GNUNET_RECLAIM_presentation_list_deserialize (presentations_ser,
714 pres_ser_len);
715
716 GNUNET_free (code_payload);
717 return GNUNET_OK;
718}
719
720
721/**
722 * Build a token response for a token request
723 * TODO: Maybe we should add the scope here?
724 *
725 * @param access_token the access token to include
726 * @param id_token the id_token to include
727 * @param expiration_time the expiration time of the token(s)
728 * @param token_response where to store the response
729 */
730void
731OIDC_build_token_response (const char *access_token,
732 const char *id_token,
733 const struct GNUNET_TIME_Relative *expiration_time,
734 char **token_response)
735{
736 json_t *root_json;
737
738 root_json = json_object ();
739
740 GNUNET_assert (NULL != access_token);
741 GNUNET_assert (NULL != id_token);
742 GNUNET_assert (NULL != expiration_time);
743 json_object_set_new (root_json, "access_token", json_string (access_token));
744 json_object_set_new (root_json, "token_type", json_string ("Bearer"));
745 json_object_set_new (root_json,
746 "expires_in",
747 json_integer (expiration_time->rel_value_us
748 / (1000 * 1000)));
749 json_object_set_new (root_json, "id_token", json_string (id_token));
750 *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
751 json_decref (root_json);
752}
753
754
755/**
756 * Generate a new access token
757 */
758char *
759OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket)
760{
761 char *access_token;
762
763 GNUNET_STRINGS_base64_encode (ticket,
764 sizeof(*ticket),
765 &access_token);
766 return access_token;
767}
768
769
770/**
771 * Parse an access token
772 */
773int
774OIDC_access_token_parse (const char *token,
775 struct GNUNET_RECLAIM_Ticket **ticket)
776{
777 if (sizeof (struct GNUNET_RECLAIM_Ticket) !=
778 GNUNET_STRINGS_base64_decode (token,
779 strlen (token),
780 (void**) ticket))
781 return GNUNET_SYSERR;
782 return GNUNET_OK;
783}
784
785
786/**
787 * Checks if a claim is implicitly requested through standard
788 * scope(s) or explicitly through non-standard scope.
789 *
790 * @param scopes the scopes which have been requested
791 * @param attr the attribute name to check
792 * @return GNUNET_YES if attribute is implcitly requested
793 */
794enum GNUNET_GenericReturnValue
795OIDC_check_scopes_for_claim_request (const char*scopes,
796 const char*attr)
797{
798 char *scope_variables;
799 char *scope_variable;
800 char delimiter[] = " ";
801 int i;
802
803 scope_variables = GNUNET_strdup (scopes);
804 scope_variable = strtok (scope_variables, delimiter);
805 while (NULL != scope_variable)
806 {
807 if (0 == strcmp ("profile", scope_variable))
808 {
809 for (i = 0; i < 14; i++)
810 {
811 if (0 == strcmp (attr, OIDC_profile_claims[i]))
812 {
813 GNUNET_free (scope_variables);
814 return GNUNET_YES;
815 }
816 }
817 }
818 else if (0 == strcmp ("address", scope_variable))
819 {
820 for (i = 0; i < 5; i++)
821 {
822 if (0 == strcmp (attr, OIDC_address_claims[i]))
823 {
824 GNUNET_free (scope_variables);
825 return GNUNET_YES;
826 }
827 }
828 }
829 else if (0 == strcmp ("email", scope_variable))
830 {
831 for (i = 0; i < 2; i++)
832 {
833 if (0 == strcmp (attr, OIDC_email_claims[i]))
834 {
835 GNUNET_free (scope_variables);
836 return GNUNET_YES;
837 }
838 }
839 }
840 else if (0 == strcmp ("phone", scope_variable))
841 {
842 for (i = 0; i < 2; i++)
843 {
844 if (0 == strcmp (attr, OIDC_phone_claims[i]))
845 {
846 GNUNET_free (scope_variables);
847 return GNUNET_YES;
848 }
849 }
850
851 }
852 else if (0 == strcmp (attr, scope_variable))
853 {
854 /** attribute matches requested scope **/
855 GNUNET_free (scope_variables);
856 return GNUNET_YES;
857 }
858 scope_variable = strtok (NULL, delimiter);
859 }
860 GNUNET_free (scope_variables);
861 return GNUNET_NO;
862
863}
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
deleted file mode 100644
index eb1022423..000000000
--- a/src/reclaim/oidc_helper.h
+++ /dev/null
@@ -1,159 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-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/**
22 * @file reclaim/oidc_helper.h
23 * @brief helper library for OIDC related functions
24 * @author Martin Schanzenbach
25 */
26
27#ifndef JWT_H
28#define JWT_H
29
30#define JWT_ALG "alg"
31
32/* Use 512bit HMAC */
33#define JWT_ALG_VALUE "HS512"
34
35#define JWT_TYP "typ"
36
37#define JWT_TYP_VALUE "jwt"
38
39#define SERVER_ADDRESS "https://api.reclaim"
40
41/**
42 * Create a JWT from attributes
43 *
44 * @param aud_key the public of the audience
45 * @param sub_key the public key of the subject
46 * @param attrs the attribute list
47 * @param presentations credential presentation list (may be empty)
48 * @param expiration_time the validity of the token
49 * @param secret_key the key used to sign the JWT
50 * @return a new base64-encoded JWT string.
51 */
52char*
53OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key,
54 const struct GNUNET_IDENTITY_PublicKey *sub_key,
55 const struct GNUNET_RECLAIM_AttributeList *attrs,
56 const struct GNUNET_RECLAIM_PresentationList *presentations,
57 const struct GNUNET_TIME_Relative *expiration_time,
58 const char *nonce,
59 const char *secret_key);
60
61/**
62 * Builds an OIDC authorization code including
63 * a reclaim ticket and nonce
64 *
65 * @param issuer the issuer of the ticket, used to sign the ticket and nonce
66 * @param ticket the ticket to include in the code
67 * @param attrs list of attributes to share
68 * @param presentations credential presentation list
69 * @param nonce the nonce to include in the code
70 * @param code_challenge PKCE code challenge
71 * @return a new authorization code (caller must free)
72 */
73char*
74OIDC_build_authz_code (const struct GNUNET_IDENTITY_PrivateKey *issuer,
75 const struct GNUNET_RECLAIM_Ticket *ticket,
76 const struct GNUNET_RECLAIM_AttributeList *attrs,
77 const struct GNUNET_RECLAIM_PresentationList *presentations,
78 const char *nonce,
79 const char *code_challenge);
80
81/**
82 * Parse reclaim ticket and nonce from
83 * authorization code.
84 * This also verifies the signature in the code.
85 *
86 * @param ecdsa_priv the audience of the ticket
87 * @param code the string representation of the code
88 * @param code_verfier PKCE code verifier
89 * @param ticket where to store the ticket
90 * @param attrs the attributes found in the code
91 * @param presentations credential presentation list
92 * @param nonce where to store the nonce
93 * @return GNUNET_OK if successful, else GNUNET_SYSERR
94 */
95int
96OIDC_parse_authz_code (const struct GNUNET_IDENTITY_PublicKey *ecdsa_pub,
97 const char *code,
98 const char *code_verifier,
99 struct GNUNET_RECLAIM_Ticket *ticket,
100 struct GNUNET_RECLAIM_AttributeList **attrs,
101 struct GNUNET_RECLAIM_PresentationList **presentations,
102 char **nonce);
103
104/**
105 * Build a token response for a token request
106 * TODO: Maybe we should add the scope here?
107 *
108 * @param access_token the access token to include
109 * @param id_token the id_token to include
110 * @param expiration_time the expiration time of the token(s)
111 * @param token_response where to store the response
112 */
113void
114OIDC_build_token_response (const char *access_token,
115 const char *id_token,
116 const struct GNUNET_TIME_Relative *expiration_time,
117 char **token_response);
118
119/**
120 * Generate a new access token
121 */
122char*
123OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket);
124
125/**
126 * Parse an access token
127 */
128int
129OIDC_access_token_parse (const char* token,
130 struct GNUNET_RECLAIM_Ticket **ticket);
131
132
133/**
134 * Checks if a claim is implicitly requested through standard
135 * scope(s)
136 *
137 * @param scopes the scopes which have been requested
138 * @param attr the attribute name to check
139 * @return GNUNET_YES if attribute is implcitly requested
140 */
141enum GNUNET_GenericReturnValue
142OIDC_check_scopes_for_claim_request (const char *scopes,
143 const char *attr);
144
145
146/**
147 * Generate userinfo JSON as string
148 *
149 * @param sub_key the subject (user)
150 * @param attrs user attribute list
151 * @param presentations credential presentation list
152 * @return Userinfo JSON
153 */
154char *
155OIDC_generate_userinfo (const struct GNUNET_IDENTITY_PublicKey *sub_key,
156 const struct GNUNET_RECLAIM_AttributeList *attrs,
157 const struct GNUNET_RECLAIM_PresentationList *presentations);
158
159#endif
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c
deleted file mode 100644
index 60c49fd6a..000000000
--- a/src/reclaim/plugin_gnsrecord_reclaim.c
+++ /dev/null
@@ -1,198 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014 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/**
22 * @file reclaim/plugin_gnsrecord_reclaim.c
23 * @brief gnsrecord plugin to provide the API for identity records
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27
28#include "gnunet_util_lib.h"
29
30#include "gnunet_gnsrecord_lib.h"
31#include "gnunet_gnsrecord_plugin.h"
32
33/**
34 * Convert the 'value' of a record to a string.
35 *
36 * @param cls closure, unused
37 * @param type type of the record
38 * @param data value in binary encoding
39 * @param data_size number of bytes in @a data
40 * @return NULL on error, otherwise human-readable representation of the value
41 */
42static char *
43value_to_string (void *cls, uint32_t type, const void *data, size_t data_size)
44{
45 switch (type)
46 {
47 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT:
48 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT:
49 return GNUNET_strndup (data, data_size);
50 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
51 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
52 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
53 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
54 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
55 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
56 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
57
58 default:
59 return NULL;
60 }
61}
62
63
64/**
65 * Convert human-readable version of a 'value' of a record to the binary
66 * representation.
67 *
68 * @param cls closure, unused
69 * @param type type of the record
70 * @param s human-readable string
71 * @param data set to value in binary encoding (will be allocated)
72 * @param data_size set to number of bytes in @a data
73 * @return #GNUNET_OK on success
74 */
75static int
76string_to_value (void *cls, uint32_t type, const char *s, void **data,
77 size_t *data_size)
78{
79 if (NULL == s)
80 return GNUNET_SYSERR;
81 switch (type)
82 {
83 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT:
84 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT:
85 *data = GNUNET_strdup (s);
86 *data_size = strlen (s);
87 return GNUNET_OK;
88 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
89 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
90 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
91 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
92 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
93 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
94 return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
95
96 default:
97 return GNUNET_SYSERR;
98 }
99}
100
101
102/**
103 * Mapping of record type numbers to human-readable
104 * record type names.
105 */
106static struct
107{
108 const char *name;
109 uint32_t number;
110} name_map[] = {
111 { "RECLAIM_ATTRIBUTE", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE },
112 { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF },
113 { "RECLAIM_CREDENTIAL", GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL },
114 { "RECLAIM_PRESENTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION },
115 { "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER },
116 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
117 { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT },
118 { "RECLAIM_TICKET", GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET },
119 { NULL, UINT32_MAX }
120};
121
122
123/**
124 * Convert a type name (i.e. "AAAA") to the corresponding number.
125 *
126 * @param cls closure, unused
127 * @param dns_typename name to convert
128 * @return corresponding number, UINT32_MAX on error
129 */
130static uint32_t
131typename_to_number (void *cls, const char *dns_typename)
132{
133 unsigned int i;
134
135 i = 0;
136 while ((NULL != name_map[i].name) &&
137 (0 != strcasecmp (dns_typename, name_map[i].name)))
138 i++;
139 return name_map[i].number;
140}
141
142
143/**
144 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
145 *
146 * @param cls closure, unused
147 * @param type number of a type to convert
148 * @return corresponding typestring, NULL on error
149 */
150static const char *
151number_to_typename (void *cls, uint32_t type)
152{
153 unsigned int i;
154
155 i = 0;
156 while ((NULL != name_map[i].name) && (type != name_map[i].number))
157 i++;
158 return name_map[i].name;
159}
160
161
162/**
163 * Entry point for the plugin.
164 *
165 * @param cls NULL
166 * @return the exported block API
167 */
168void *
169libgnunet_plugin_gnsrecord_reclaim_init (void *cls)
170{
171 struct GNUNET_GNSRECORD_PluginFunctions *api;
172
173 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
174 api->value_to_string = &value_to_string;
175 api->string_to_value = &string_to_value;
176 api->typename_to_number = &typename_to_number;
177 api->number_to_typename = &number_to_typename;
178 return api;
179}
180
181
182/**
183 * Exit point from the plugin.
184 *
185 * @param cls the return value from #libgnunet_plugin_block_test_init
186 * @return NULL
187 */
188void *
189libgnunet_plugin_gnsrecord_reclaim_done (void *cls)
190{
191 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
192
193 GNUNET_free (api);
194 return NULL;
195}
196
197
198/* end of plugin_gnsrecord_dns.c */
diff --git a/src/reclaim/plugin_reclaim_attribute_basic.c b/src/reclaim/plugin_reclaim_attribute_basic.c
deleted file mode 100644
index 286186a93..000000000
--- a/src/reclaim/plugin_reclaim_attribute_basic.c
+++ /dev/null
@@ -1,181 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim-attribute/plugin_reclaim_attribute_gnuid.c
23 * @brief reclaim-attribute-plugin-gnuid attribute plugin to provide the API for
24 * fundamental
25 * attribute types.
26 *
27 * @author Martin Schanzenbach
28 */
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_reclaim_plugin.h"
32#include <inttypes.h>
33
34
35/**
36 * Convert the 'value' of an attribute to a string.
37 *
38 * @param cls closure, unused
39 * @param type type of the attribute
40 * @param data value in binary encoding
41 * @param data_size number of bytes in @a data
42 * @return NULL on error, otherwise human-readable representation of the value
43 */
44static char *
45basic_value_to_string (void *cls,
46 uint32_t type,
47 const void *data,
48 size_t data_size)
49{
50 switch (type)
51 {
52 case GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING:
53 return GNUNET_strndup (data, data_size);
54
55 default:
56 return NULL;
57 }
58}
59
60
61/**
62 * Convert human-readable version of a 'value' of an attribute to the binary
63 * representation.
64 *
65 * @param cls closure, unused
66 * @param type type of the attribute
67 * @param s human-readable string
68 * @param data set to value in binary encoding (will be allocated)
69 * @param data_size set to number of bytes in @a data
70 * @return #GNUNET_OK on success
71 */
72static int
73basic_string_to_value (void *cls,
74 uint32_t type,
75 const char *s,
76 void **data,
77 size_t *data_size)
78{
79 if (NULL == s)
80 return GNUNET_SYSERR;
81 switch (type)
82 {
83 case GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING:
84 *data = GNUNET_strdup (s);
85 *data_size = strlen (s);
86 return GNUNET_OK;
87
88 default:
89 return GNUNET_SYSERR;
90 }
91}
92
93
94/**
95 * Mapping of attribute type numbers to human-readable
96 * attribute type names.
97 */
98static struct
99{
100 const char *name;
101 uint32_t number;
102} basic_name_map[] = { { "STRING", GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING },
103 { NULL, UINT32_MAX } };
104
105
106/**
107 * Convert a type name to the corresponding number.
108 *
109 * @param cls closure, unused
110 * @param basic_typename name to convert
111 * @return corresponding number, UINT32_MAX on error
112 */
113static uint32_t
114basic_typename_to_number (void *cls, const char *basic_typename)
115{
116 unsigned int i;
117
118 i = 0;
119 while ((NULL != basic_name_map[i].name) &&
120 (0 != strcasecmp (basic_typename, basic_name_map[i].name)))
121 i++;
122 return basic_name_map[i].number;
123}
124
125
126/**
127 * Convert a type number (i.e. 1) to the corresponding type string
128 *
129 * @param cls closure, unused
130 * @param type number of a type to convert
131 * @return corresponding typestring, NULL on error
132 */
133static const char *
134basic_number_to_typename (void *cls, uint32_t type)
135{
136 unsigned int i;
137
138 i = 0;
139 while ((NULL != basic_name_map[i].name) && (type != basic_name_map[i].number))
140 i++;
141 return basic_name_map[i].name;
142}
143
144
145/**
146 * Entry point for the plugin.
147 *
148 * @param cls NULL
149 * @return the exported block API
150 */
151void *
152libgnunet_plugin_reclaim_attribute_basic_init (void *cls)
153{
154 struct GNUNET_RECLAIM_AttributePluginFunctions *api;
155
156 api = GNUNET_new (struct GNUNET_RECLAIM_AttributePluginFunctions);
157 api->value_to_string = &basic_value_to_string;
158 api->string_to_value = &basic_string_to_value;
159 api->typename_to_number = &basic_typename_to_number;
160 api->number_to_typename = &basic_number_to_typename;
161 return api;
162}
163
164
165/**
166 * Exit point from the plugin.
167 *
168 * @param cls the return value from #libgnunet_plugin_block_test_init()
169 * @return NULL
170 */
171void *
172libgnunet_plugin_reclaim_attribute_basic_done (void *cls)
173{
174 struct GNUNET_RECLAIM_AttributePluginFunctions *api = cls;
175
176 GNUNET_free (api);
177 return NULL;
178}
179
180
181/* end of plugin_reclaim_attribute_type_gnuid.c */
diff --git a/src/reclaim/plugin_reclaim_credential_jwt.c b/src/reclaim/plugin_reclaim_credential_jwt.c
deleted file mode 100644
index 6f52f3a4e..000000000
--- a/src/reclaim/plugin_reclaim_credential_jwt.c
+++ /dev/null
@@ -1,435 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/plugin_reclaim_credential_jwt.c
23 * @brief reclaim-credential-plugin-jwt attribute plugin to provide the API for
24 * JWT credentials.
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_reclaim_plugin.h"
31#include <inttypes.h>
32#include <jansson.h>
33
34/**
35 * Convert the 'value' of an credential to a string.
36 *
37 * @param cls closure, unused
38 * @param type type of the credential
39 * @param data value in binary encoding
40 * @param data_size number of bytes in @a data
41 * @return NULL on error, otherwise human-readable representation of the value
42 */
43static char *
44jwt_value_to_string (void *cls,
45 uint32_t type,
46 const void *data,
47 size_t data_size)
48{
49 switch (type)
50 {
51 case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
52 return GNUNET_strndup (data, data_size);
53
54 default:
55 return NULL;
56 }
57}
58
59
60/**
61 * Convert human-readable version of a 'value' of an credential to the binary
62 * representation.
63 *
64 * @param cls closure, unused
65 * @param type type of the credential
66 * @param s human-readable string
67 * @param data set to value in binary encoding (will be allocated)
68 * @param data_size set to number of bytes in @a data
69 * @return #GNUNET_OK on success
70 */
71static int
72jwt_string_to_value (void *cls,
73 uint32_t type,
74 const char *s,
75 void **data,
76 size_t *data_size)
77{
78 if (NULL == s)
79 return GNUNET_SYSERR;
80 switch (type)
81 {
82 case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
83 *data = GNUNET_strdup (s);
84 *data_size = strlen (s);
85 return GNUNET_OK;
86
87 default:
88 return GNUNET_SYSERR;
89 }
90}
91
92
93/**
94 * Mapping of credential type numbers to human-readable
95 * credential type names.
96 */
97static struct
98{
99 const char *name;
100 uint32_t number;
101} jwt_cred_name_map[] = { { "JWT", GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT },
102 { NULL, UINT32_MAX } };
103
104/**
105 * Convert a type name to the corresponding number.
106 *
107 * @param cls closure, unused
108 * @param jwt_typename name to convert
109 * @return corresponding number, UINT32_MAX on error
110 */
111static uint32_t
112jwt_typename_to_number (void *cls, const char *jwt_typename)
113{
114 unsigned int i;
115
116 i = 0;
117 while ((NULL != jwt_cred_name_map[i].name) &&
118 (0 != strcasecmp (jwt_typename, jwt_cred_name_map[i].name)))
119 i++;
120 return jwt_cred_name_map[i].number;
121}
122
123
124/**
125 * Convert a type number (i.e. 1) to the corresponding type string
126 *
127 * @param cls closure, unused
128 * @param type number of a type to convert
129 * @return corresponding typestring, NULL on error
130 */
131static const char *
132jwt_number_to_typename (void *cls, uint32_t type)
133{
134 unsigned int i;
135
136 i = 0;
137 while ((NULL != jwt_cred_name_map[i].name) && (type !=
138 jwt_cred_name_map[i].
139 number))
140 i++;
141 return jwt_cred_name_map[i].name;
142}
143
144
145/**
146 * Parse a JWT and return the respective claim value as Attribute
147 *
148 * @param cls the plugin
149 * @param cred the jwt credential
150 * @return a GNUNET_RECLAIM_Attribute, containing the new value
151 */
152struct GNUNET_RECLAIM_AttributeList *
153jwt_parse_attributes (void *cls,
154 const char *data)
155{
156 char *jwt_string;
157 struct GNUNET_RECLAIM_AttributeList *attrs;
158 char delim[] = ".";
159 char *val_str = NULL;
160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
161 char *decoded_jwt;
162 json_t *json_val;
163 json_error_t *json_err = NULL;
164
165 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
166
167 jwt_string = GNUNET_strdup (data);
168 const char *jwt_body = strtok (jwt_string, delim);
169 jwt_body = strtok (NULL, delim);
170 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
171 (void **) &decoded_jwt);
172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded JWT: %s\n", decoded_jwt);
173 GNUNET_assert (NULL != decoded_jwt);
174 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
175 const char *key;
176 json_t *value;
177 json_object_foreach (json_val, key, value) {
178 if (0 == strcmp ("iss", key))
179 continue;
180 if (0 == strcmp ("jti", key))
181 continue;
182 if (0 == strcmp ("exp", key))
183 continue;
184 if (0 == strcmp ("iat", key))
185 continue;
186 if (0 == strcmp ("nbf", key))
187 continue;
188 if (0 == strcmp ("aud", key))
189 continue;
190 val_str = json_dumps (value, JSON_ENCODE_ANY);
191 GNUNET_RECLAIM_attribute_list_add (attrs,
192 key,
193 NULL,
194 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,// FIXME
195 val_str,
196 strlen (val_str));
197 GNUNET_free (val_str);
198 }
199 GNUNET_free (jwt_string);
200 return attrs;
201}
202
203
204/**
205 * Parse a JWT and return the respective claim value as Attribute
206 *
207 * @param cls the plugin
208 * @param cred the jwt credential
209 * @return a GNUNET_RECLAIM_Attribute, containing the new value
210 */
211struct GNUNET_RECLAIM_AttributeList *
212jwt_parse_attributes_c (void *cls,
213 const struct GNUNET_RECLAIM_Credential *cred)
214{
215 return jwt_parse_attributes (cls, cred->data);
216}
217
218
219/**
220 * Parse a JWT and return the respective claim value as Attribute
221 *
222 * @param cls the plugin
223 * @param cred the jwt credential
224 * @return a GNUNET_RECLAIM_Attribute, containing the new value
225 */
226struct GNUNET_RECLAIM_AttributeList *
227jwt_parse_attributes_p (void *cls,
228 const struct GNUNET_RECLAIM_Presentation *cred)
229{
230 return jwt_parse_attributes (cls, cred->data);
231}
232
233
234/**
235 * Parse a JWT and return the issuer
236 *
237 * @param cls the plugin
238 * @param cred the jwt credential
239 * @return a string, containing the isser
240 */
241char *
242jwt_get_issuer (void *cls,
243 const char *data)
244{
245 const char *jwt_body;
246 char *jwt_string;
247 char delim[] = ".";
248 char *issuer = NULL;
249 char *decoded_jwt;
250 json_t *issuer_json;
251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
252 json_t *json_val;
253 json_error_t *json_err = NULL;
254
255 jwt_string = GNUNET_strdup (data);
256 jwt_body = strtok (jwt_string, delim);
257 jwt_body = strtok (NULL, delim);
258 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
259 (void **) &decoded_jwt);
260 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
261 issuer_json = json_object_get (json_val, "iss");
262 if ((NULL == issuer_json) || (! json_is_string (issuer_json)))
263 return NULL;
264 issuer = GNUNET_strdup (json_string_value (issuer_json));
265 GNUNET_free (jwt_string);
266 return issuer;
267}
268
269
270/**
271 * Parse a JWT and return the issuer
272 *
273 * @param cls the plugin
274 * @param cred the jwt credential
275 * @return a string, containing the isser
276 */
277char *
278jwt_get_issuer_c (void *cls,
279 const struct GNUNET_RECLAIM_Credential *cred)
280{
281 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
282 return NULL;
283 return jwt_get_issuer (cls, cred->data);
284}
285
286
287/**
288 * Parse a JWT and return the issuer
289 *
290 * @param cls the plugin
291 * @param cred the jwt credential
292 * @return a string, containing the isser
293 */
294char *
295jwt_get_issuer_p (void *cls,
296 const struct GNUNET_RECLAIM_Presentation *cred)
297{
298 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
299 return NULL;
300 return jwt_get_issuer (cls, cred->data);
301}
302
303
304/**
305 * Parse a JWT and return the expiration
306 *
307 * @param cls the plugin
308 * @param cred the jwt credential
309 * @return a string, containing the isser
310 */
311int
312jwt_get_expiration (void *cls,
313 const char *data,
314 struct GNUNET_TIME_Absolute *exp)
315{
316 const char *jwt_body;
317 char *jwt_string;
318 char delim[] = ".";
319 char *decoded_jwt;
320 json_t *exp_json;
321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
322 json_t *json_val;
323 json_error_t *json_err = NULL;
324
325 jwt_string = GNUNET_strdup (data);
326 jwt_body = strtok (jwt_string, delim);
327 jwt_body = strtok (NULL, delim);
328 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
329 (void **) &decoded_jwt);
330 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
331 exp_json = json_object_get (json_val, "exp");
332 if ((NULL == exp_json) || (! json_is_integer (exp_json)))
333 return GNUNET_SYSERR;
334 exp->abs_value_us = json_integer_value (exp_json) * 1000 * 1000;
335 GNUNET_free (jwt_string);
336 return GNUNET_OK;
337}
338
339
340/**
341 * Parse a JWT and return the expiration
342 *
343 * @param cls the plugin
344 * @param cred the jwt credential
345 * @return a string, containing the isser
346 */
347int
348jwt_get_expiration_c (void *cls,
349 const struct GNUNET_RECLAIM_Credential *cred,
350 struct GNUNET_TIME_Absolute *exp)
351{
352 return jwt_get_expiration (cls, cred->data, exp);
353}
354
355
356/**
357 * Parse a JWT and return the expiration
358 *
359 * @param cls the plugin
360 * @param cred the jwt credential
361 * @return a string, containing the isser
362 */
363int
364jwt_get_expiration_p (void *cls,
365 const struct GNUNET_RECLAIM_Presentation *cred,
366 struct GNUNET_TIME_Absolute *exp)
367{
368 return jwt_get_expiration (cls, cred->data, exp);
369}
370
371
372int
373jwt_create_presentation (void *cls,
374 const struct GNUNET_RECLAIM_Credential *cred,
375 const struct GNUNET_RECLAIM_AttributeList *attrs,
376 struct GNUNET_RECLAIM_Presentation **pres)
377{
378 // FIXME sanity checks??
379 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
380 return GNUNET_NO;
381 *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT,
382 cred->data,
383 cred->data_size);
384 return GNUNET_OK;
385}
386
387
388/**
389 * Entry point for the plugin.
390 *
391 * @param cls NULL
392 * @return the exported block API
393 */
394void *
395libgnunet_plugin_reclaim_credential_jwt_init (void *cls)
396{
397 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
398
399 api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions);
400 api->value_to_string = &jwt_value_to_string;
401 api->string_to_value = &jwt_string_to_value;
402 api->typename_to_number = &jwt_typename_to_number;
403 api->number_to_typename = &jwt_number_to_typename;
404 api->get_attributes = &jwt_parse_attributes_c;
405 api->get_issuer = &jwt_get_issuer_c;
406 api->get_expiration = &jwt_get_expiration_c;
407 api->value_to_string_p = &jwt_value_to_string;
408 api->string_to_value_p = &jwt_string_to_value;
409 api->typename_to_number_p = &jwt_typename_to_number;
410 api->number_to_typename_p = &jwt_number_to_typename;
411 api->get_attributes_p = &jwt_parse_attributes_p;
412 api->get_issuer_p = &jwt_get_issuer_p;
413 api->get_expiration_p = &jwt_get_expiration_p;
414 api->create_presentation = &jwt_create_presentation;
415 return api;
416}
417
418
419/**
420 * Exit point from the plugin.
421 *
422 * @param cls the return value from #libgnunet_plugin_block_test_init()
423 * @return NULL
424 */
425void *
426libgnunet_plugin_reclaim_credential_jwt_done (void *cls)
427{
428 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
429
430 GNUNET_free (api);
431 return NULL;
432}
433
434
435/* end of plugin_reclaim_credential_type_jwt.c */
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
deleted file mode 100644
index 7a8a886bd..000000000
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ /dev/null
@@ -1,2672 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2018 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 identity/plugin_rest_openid_connect.c
24 * @brief GNUnet Namestore REST plugin
25 *
26 */
27#include "platform.h"
28#include <inttypes.h>
29#include <jansson.h>
30
31#include "gnunet_buffer_lib.h"
32#include "gnunet_strings_lib.h"
33#include "gnunet_gns_service.h"
34#include "gnunet_gnsrecord_lib.h"
35#include "gnunet_identity_service.h"
36#include "gnunet_namestore_service.h"
37#include "gnunet_reclaim_lib.h"
38#include "gnunet_reclaim_service.h"
39#include "gnunet_rest_lib.h"
40#include "gnunet_rest_plugin.h"
41#include "gnunet_signatures.h"
42#include "microhttpd.h"
43#include "oidc_helper.h"
44
45/**
46 * REST root namespace
47 */
48#define GNUNET_REST_API_NS_OIDC "/openid"
49
50/**
51 * OIDC config
52 */
53#define GNUNET_REST_API_NS_OIDC_CONFIG "/.well-known/openid-configuration"
54
55/**
56 * Authorize endpoint
57 */
58#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
59
60/**
61 * Token endpoint
62 */
63#define GNUNET_REST_API_NS_TOKEN "/openid/token"
64
65/**
66 * UserInfo endpoint
67 */
68#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
69
70/**
71 * Login namespace
72 */
73#define GNUNET_REST_API_NS_LOGIN "/openid/login"
74
75/**
76 * State while collecting all egos
77 */
78#define ID_REST_STATE_INIT 0
79
80/**
81 * Done collecting egos
82 */
83#define ID_REST_STATE_POST_INIT 1
84
85/**
86 * OIDC grant_type key
87 */
88#define OIDC_GRANT_TYPE_KEY "grant_type"
89
90/**
91 * OIDC grant_type key
92 */
93#define OIDC_GRANT_TYPE_VALUE "authorization_code"
94
95/**
96 * OIDC code key
97 */
98#define OIDC_CODE_KEY "code"
99
100/**
101 * OIDC response_type key
102 */
103#define OIDC_RESPONSE_TYPE_KEY "response_type"
104
105/**
106 * OIDC client_id key
107 */
108#define OIDC_CLIENT_ID_KEY "client_id"
109
110/**
111 * OIDC scope key
112 */
113#define OIDC_SCOPE_KEY "scope"
114
115/**
116 * OIDC redirect_uri key
117 */
118#define OIDC_REDIRECT_URI_KEY "redirect_uri"
119
120/**
121 * OIDC state key
122 */
123#define OIDC_STATE_KEY "state"
124
125/**
126 * OIDC nonce key
127 */
128#define OIDC_NONCE_KEY "nonce"
129
130/**
131 * OIDC claims key
132 */
133#define OIDC_CLAIMS_KEY "claims"
134
135/**
136 * OIDC PKCE code challenge
137 */
138#define OIDC_CODE_CHALLENGE_KEY "code_challenge"
139
140/**
141 * OIDC PKCE code verifier
142 */
143#define OIDC_CODE_VERIFIER_KEY "code_verifier"
144
145/**
146 * OIDC cookie expiration (in seconds)
147 */
148#define OIDC_COOKIE_EXPIRATION 3
149
150/**
151 * OIDC cookie header key
152 */
153#define OIDC_COOKIE_HEADER_KEY "cookie"
154
155/**
156 * OIDC cookie header information key
157 */
158#define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
159
160/**
161 * OIDC cookie header information key
162 */
163#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
164
165/**
166 * OIDC cookie header if user cancelled
167 */
168#define OIDC_COOKIE_HEADER_ACCESS_DENIED "Identity=Denied"
169
170/**
171 * OIDC expected response_type while authorizing
172 */
173#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
174
175/**
176 * OIDC expected scope part while authorizing
177 */
178#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
179
180/**
181 * OIDC error key for invalid client
182 */
183#define OIDC_ERROR_KEY_INVALID_CLIENT "invalid_client"
184
185/**
186 * OIDC error key for invalid scopes
187 */
188#define OIDC_ERROR_KEY_INVALID_SCOPE "invalid_scope"
189
190/**
191 * OIDC error key for invalid requests
192 */
193#define OIDC_ERROR_KEY_INVALID_REQUEST "invalid_request"
194
195/**
196 * OIDC error key for invalid tokens
197 */
198#define OIDC_ERROR_KEY_INVALID_TOKEN "invalid_token"
199
200/**
201 * OIDC error key for invalid cookies
202 */
203#define OIDC_ERROR_KEY_INVALID_COOKIE "invalid_cookie"
204
205/**
206 * OIDC error key for generic server errors
207 */
208#define OIDC_ERROR_KEY_SERVER_ERROR "server_error"
209
210/**
211 * OIDC error key for unsupported grants
212 */
213#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE "unsupported_grant_type"
214
215/**
216 * OIDC error key for unsupported response types
217 */
218#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE "unsupported_response_type"
219
220/**
221 * OIDC error key for unauthorized clients
222 */
223#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT "unauthorized_client"
224
225/**
226 * OIDC error key for denied access
227 */
228#define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
229
230
231/**
232 * OIDC ignored parameter array
233 */
234static char *OIDC_ignored_parameter_array[] = { "display",
235 "prompt",
236 "ui_locales",
237 "response_mode",
238 "id_token_hint",
239 "login_hint",
240 "acr_values" };
241
242/**
243 * OIDC Hash map that keeps track of issued cookies
244 */
245struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map;
246
247/**
248 * The configuration handle
249 */
250const struct GNUNET_CONFIGURATION_Handle *cfg;
251
252/**
253 * HTTP methods allows for this plugin
254 */
255static char *allow_methods;
256
257/**
258 * Ego list
259 */
260static struct EgoEntry *ego_head;
261
262/**
263 * Ego list
264 */
265static struct EgoEntry *ego_tail;
266
267/**
268 * The processing state
269 */
270static int state;
271
272/**
273 * Handle to Identity service.
274 */
275static struct GNUNET_IDENTITY_Handle *identity_handle;
276
277/**
278 * GNS handle
279 */
280static struct GNUNET_GNS_Handle *gns_handle;
281
282/**
283 * Identity Provider
284 */
285static struct GNUNET_RECLAIM_Handle *idp;
286
287/**
288 * @brief struct returned by the initialization function of the plugin
289 */
290struct Plugin
291{
292 const struct GNUNET_CONFIGURATION_Handle *cfg;
293};
294
295/**
296 * OIDC needed variables
297 */
298struct OIDC_Variables
299{
300 /**
301 * The RP client public key
302 */
303 struct GNUNET_IDENTITY_PublicKey client_pkey;
304
305 /**
306 * The OIDC client id of the RP
307 */
308 char *client_id;
309
310 /**
311 * The OIDC redirect uri
312 */
313 char *redirect_uri;
314
315 /**
316 * The list of oidc scopes
317 */
318 char *scope;
319
320 /**
321 * The OIDC state
322 */
323 char *state;
324
325 /**
326 * The OIDC nonce
327 */
328 char *nonce;
329
330 /**
331 * The OIDC claims
332 */
333 char *claims;
334
335 /**
336 * The OIDC response type
337 */
338 char *response_type;
339
340 /**
341 * The identity chosen by the user to login
342 */
343 char *login_identity;
344
345 /**
346 * User cancelled authorization/login
347 */
348 int user_cancelled;
349
350 /**
351 * The PKCE code_challenge
352 */
353 char *code_challenge;
354
355 /**
356 * The PKCE code_verifier
357 */
358 char *code_verifier;
359
360};
361
362/**
363 * The ego list
364 */
365struct EgoEntry
366{
367 /**
368 * DLL
369 */
370 struct EgoEntry *next;
371
372 /**
373 * DLL
374 */
375 struct EgoEntry *prev;
376
377 /**
378 * Ego Identifier
379 */
380 char *identifier;
381
382 /**
383 * Public key string
384 */
385 char *keystring;
386
387 /**
388 * The Ego
389 */
390 struct GNUNET_IDENTITY_Ego *ego;
391};
392
393
394struct RequestHandle
395{
396 /**
397 * DLL
398 */
399 struct RequestHandle *next;
400
401 /**
402 * DLL
403 */
404 struct RequestHandle *prev;
405
406 /**
407 * Selected ego
408 */
409 struct EgoEntry *ego_entry;
410
411 /**
412 * Pointer to ego private key
413 */
414 struct GNUNET_IDENTITY_PrivateKey priv_key;
415
416 /**
417 * OIDC variables
418 */
419 struct OIDC_Variables *oidc;
420
421 /**
422 * GNS lookup op
423 */
424 struct GNUNET_GNS_LookupRequest *gns_op;
425
426 /**
427 * Rest connection
428 */
429 struct GNUNET_REST_RequestHandle *rest_handle;
430
431 /**
432 * Attribute claim list for id_token
433 */
434 struct GNUNET_RECLAIM_AttributeList *attr_idtoken_list;
435
436 /**
437 * Attribute claim list for userinfo
438 */
439 struct GNUNET_RECLAIM_AttributeList *attr_userinfo_list;
440
441 /**
442 * Credentials
443 */
444 struct GNUNET_RECLAIM_CredentialList *credentials;
445
446 /**
447 * Presentations
448 */
449 struct GNUNET_RECLAIM_PresentationList *presentations;
450
451 /**
452 * IDENTITY Operation
453 */
454 struct GNUNET_IDENTITY_Operation *op;
455
456
457 /**
458 * Idp Operation
459 */
460 struct GNUNET_RECLAIM_Operation *idp_op;
461
462 /**
463 * Attribute iterator
464 */
465 struct GNUNET_RECLAIM_AttributeIterator *attr_it;
466
467 /**
468 * Credential iterator
469 */
470 struct GNUNET_RECLAIM_CredentialIterator *cred_it;
471
472
473 /**
474 * Ticket iterator
475 */
476 struct GNUNET_RECLAIM_TicketIterator *ticket_it;
477
478 /**
479 * A ticket
480 */
481 struct GNUNET_RECLAIM_Ticket ticket;
482
483 /**
484 * Desired timeout for the lookup (default is no timeout).
485 */
486 struct GNUNET_TIME_Relative timeout;
487
488 /**
489 * ID of a task associated with the resolution process.
490 */
491 struct GNUNET_SCHEDULER_Task *timeout_task;
492
493 /**
494 * The plugin result processor
495 */
496 GNUNET_REST_ResultProcessor proc;
497
498 /**
499 * The closure of the result processor
500 */
501 void *proc_cls;
502
503 /**
504 * The url
505 */
506 char *url;
507
508 /**
509 * The tld for redirect
510 */
511 char *tld;
512
513 /**
514 * The redirect prefix
515 */
516 char *redirect_prefix;
517
518 /**
519 * The redirect suffix
520 */
521 char *redirect_suffix;
522
523 /**
524 * Error response message
525 */
526 char *emsg;
527
528 /**
529 * Error response description
530 */
531 char *edesc;
532
533 /**
534 * Reponse code
535 */
536 int response_code;
537
538 /**
539 * Public client
540 */
541 int public_client;
542};
543
544/**
545 * DLL
546 */
547static struct RequestHandle *requests_head;
548
549/**
550 * DLL
551 */
552static struct RequestHandle *requests_tail;
553
554
555/**
556 * Cleanup lookup handle
557 * @param handle Handle to clean up
558 */
559static void
560cleanup_handle (struct RequestHandle *handle)
561{
562
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
564 if (NULL != handle->timeout_task)
565 GNUNET_SCHEDULER_cancel (handle->timeout_task);
566 if (NULL != handle->attr_it)
567 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
568 if (NULL != handle->cred_it)
569 GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
570 if (NULL != handle->ticket_it)
571 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
572 if (NULL != handle->idp_op)
573 GNUNET_RECLAIM_cancel (handle->idp_op);
574 GNUNET_free (handle->url);
575 GNUNET_free (handle->tld);
576 GNUNET_free (handle->redirect_prefix);
577 GNUNET_free (handle->redirect_suffix);
578 GNUNET_free (handle->emsg);
579 GNUNET_free (handle->edesc);
580 if (NULL != handle->gns_op)
581 GNUNET_GNS_lookup_cancel (handle->gns_op);
582 if (NULL != handle->oidc)
583 {
584 GNUNET_free (handle->oidc->client_id);
585 GNUNET_free (handle->oidc->login_identity);
586 GNUNET_free (handle->oidc->nonce);
587 GNUNET_free (handle->oidc->redirect_uri);
588 GNUNET_free (handle->oidc->response_type);
589 GNUNET_free (handle->oidc->scope);
590 GNUNET_free (handle->oidc->state);
591 GNUNET_free (handle->oidc);
592 }
593 if (NULL!=handle->attr_idtoken_list)
594 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list);
595 if (NULL!=handle->attr_userinfo_list)
596 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
597 if (NULL!=handle->credentials)
598 GNUNET_RECLAIM_credential_list_destroy (handle->credentials);
599 if (NULL!=handle->presentations)
600 GNUNET_RECLAIM_presentation_list_destroy (handle->presentations);
601 GNUNET_CONTAINER_DLL_remove (requests_head,
602 requests_tail,
603 handle);
604 GNUNET_free (handle);
605}
606
607
608/**
609 * Task run on error, sends error message. Cleans up everything.
610 *
611 * @param cls the `struct RequestHandle`
612 */
613static void
614do_error (void *cls)
615{
616 struct RequestHandle *handle = cls;
617 struct MHD_Response *resp;
618 char *json_error;
619
620 GNUNET_asprintf (&json_error,
621 "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
622 handle->emsg,
623 (NULL != handle->edesc) ? handle->edesc : "",
624 (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
625 (NULL != handle->oidc->state) ? handle->oidc->state : "",
626 (NULL != handle->oidc->state) ? "\"" : "");
627 if (0 == handle->response_code)
628 handle->response_code = MHD_HTTP_BAD_REQUEST;
629 resp = GNUNET_REST_create_response (json_error);
630 if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
631 MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Basic");
632 MHD_add_response_header (resp,
633 MHD_HTTP_HEADER_CONTENT_TYPE,
634 "application/json");
635 handle->proc (handle->proc_cls, resp, handle->response_code);
636 cleanup_handle (handle);
637 GNUNET_free (json_error);
638}
639
640
641/**
642 * Task run on error in userinfo endpoint, sends error header. Cleans up
643 * everything
644 *
645 * @param cls the `struct RequestHandle`
646 */
647static void
648do_userinfo_error (void *cls)
649{
650 struct RequestHandle *handle = cls;
651 struct MHD_Response *resp;
652 char *error;
653
654 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
655 "Error: %s\n", handle->edesc);
656 GNUNET_asprintf (&error,
657 "error=\"%s\", error_description=\"%s\"",
658 handle->emsg,
659 (NULL != handle->edesc) ? handle->edesc : "");
660 resp = GNUNET_REST_create_response ("");
661 MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer");
662 handle->proc (handle->proc_cls, resp, handle->response_code);
663 cleanup_handle (handle);
664 GNUNET_free (error);
665}
666
667
668/**
669 * Task run on error, sends error message and redirects. Cleans up everything.
670 *
671 * @param cls the `struct RequestHandle`
672 */
673static void
674do_redirect_error (void *cls)
675{
676 struct RequestHandle *handle = cls;
677 struct MHD_Response *resp;
678 char *redirect;
679
680 GNUNET_asprintf (&redirect,
681 "%s?error=%s&error_description=%s%s%s",
682 handle->oidc->redirect_uri,
683 handle->emsg,
684 handle->edesc,
685 (NULL != handle->oidc->state) ? "&state=" : "",
686 (NULL != handle->oidc->state) ? handle->oidc->state : "");
687 resp = GNUNET_REST_create_response ("");
688 MHD_add_response_header (resp, "Location", redirect);
689 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
690 cleanup_handle (handle);
691 GNUNET_free (redirect);
692}
693
694
695/**
696 * Task run on timeout, sends error message. Cleans up everything.
697 *
698 * @param cls the `struct RequestHandle`
699 */
700static void
701do_timeout (void *cls)
702{
703 struct RequestHandle *handle = cls;
704
705 handle->timeout_task = NULL;
706 do_error (handle);
707}
708
709
710/**
711 * Respond to OPTIONS request
712 *
713 * @param con_handle the connection handle
714 * @param url the url
715 * @param cls the RequestHandle
716 */
717static void
718options_cont (struct GNUNET_REST_RequestHandle *con_handle,
719 const char *url,
720 void *cls)
721{
722 struct MHD_Response *resp;
723 struct RequestHandle *handle = cls;
724
725 // For now, independent of path return all options
726 resp = GNUNET_REST_create_response (NULL);
727 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
728 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
729 cleanup_handle (handle);
730 return;
731}
732
733
734/**
735 * Interprets cookie header and pass its identity keystring to handle
736 */
737static void
738cookie_identity_interpretation (struct RequestHandle *handle)
739{
740 struct GNUNET_HashCode cache_key;
741 char *cookies;
742 struct GNUNET_TIME_Absolute current_time, *relog_time;
743 char delimiter[] = "; ";
744 char *tmp_cookies;
745 char *token;
746 char *value;
747
748 // gets identity of login try with cookie
749 GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY,
750 strlen (OIDC_COOKIE_HEADER_KEY),
751 &cache_key);
752 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
753 ->header_param_map,
754 &cache_key))
755 {
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
757 return;
758 }
759 // splits cookies and find 'Identity' cookie
760 tmp_cookies =
761 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
762 &cache_key);
763 cookies = GNUNET_strdup (tmp_cookies);
764 token = strtok (cookies, delimiter);
765 handle->oidc->user_cancelled = GNUNET_NO;
766 handle->oidc->login_identity = NULL;
767 if (NULL == token)
768 {
769 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
770 "Unable to parse cookie: %s\n",
771 cookies);
772 GNUNET_free (cookies);
773 return;
774 }
775
776 while (NULL != token)
777 {
778 if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
779 {
780 handle->oidc->user_cancelled = GNUNET_YES;
781 GNUNET_free (cookies);
782 return;
783 }
784 if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
785 break;
786 token = strtok (NULL, delimiter);
787 }
788 if (NULL == token)
789 {
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
791 "No cookie value to process: %s\n",
792 cookies);
793 GNUNET_free (cookies);
794 return;
795 }
796 GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
797 if (GNUNET_NO ==
798 GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
799 {
800 GNUNET_log (
801 GNUNET_ERROR_TYPE_WARNING,
802 "Found cookie `%s', but no corresponding expiration entry present...\n",
803 token);
804 GNUNET_free (cookies);
805 return;
806 }
807 relog_time =
808 GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
809 current_time = GNUNET_TIME_absolute_get ();
810 // 30 min after old login -> redirect to login
811 if (current_time.abs_value_us > relog_time->abs_value_us)
812 {
813 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
814 "Found cookie `%s', but it is expired.\n",
815 token);
816 GNUNET_free (cookies);
817 return;
818 }
819 value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
820 GNUNET_assert (NULL != value);
821 handle->oidc->login_identity = GNUNET_strdup (value);
822 GNUNET_free (cookies);
823}
824
825
826/**
827 * Redirects to login page stored in configuration file
828 */
829static void
830login_redirect (void *cls)
831{
832 char *login_base_url;
833 char *new_redirect;
834 char *tmp;
835 struct MHD_Response *resp;
836 struct GNUNET_Buffer buf = { 0 };
837 struct RequestHandle *handle = cls;
838
839 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
840 "reclaim-rest-plugin",
841 "address",
842 &login_base_url))
843 {
844 GNUNET_buffer_write_str (&buf, login_base_url);
845 GNUNET_buffer_write_fstr (&buf,
846 "?%s=%s",
847 OIDC_RESPONSE_TYPE_KEY,
848 handle->oidc->response_type);
849 GNUNET_buffer_write_fstr (&buf,
850 "&%s=%s",
851 OIDC_CLIENT_ID_KEY,
852 handle->oidc->client_id);
853 GNUNET_STRINGS_urlencode (handle->oidc->redirect_uri,
854 strlen (handle->oidc->redirect_uri),
855 &tmp);
856 GNUNET_buffer_write_fstr (&buf,
857 "&%s=%s",
858 OIDC_REDIRECT_URI_KEY,
859 tmp);
860 GNUNET_free (tmp);
861 GNUNET_STRINGS_urlencode (handle->oidc->scope,
862 strlen (handle->oidc->scope),
863 &tmp);
864 GNUNET_buffer_write_fstr (&buf,
865 "&%s=%s",
866 OIDC_SCOPE_KEY,
867 tmp);
868 GNUNET_free (tmp);
869 if (NULL != handle->oidc->state)
870 {
871 GNUNET_STRINGS_urlencode (handle->oidc->state,
872 strlen (handle->oidc->state),
873 &tmp);
874 GNUNET_buffer_write_fstr (&buf,
875 "&%s=%s",
876 OIDC_STATE_KEY,
877 handle->oidc->state);
878 GNUNET_free (tmp);
879 }
880 if (NULL != handle->oidc->code_challenge)
881 {
882 GNUNET_buffer_write_fstr (&buf,
883 "&%s=%s",
884 OIDC_CODE_CHALLENGE_KEY,
885 handle->oidc->code_challenge);
886 }
887 if (NULL != handle->oidc->nonce)
888 {
889 GNUNET_buffer_write_fstr (&buf,
890 "&%s=%s",
891 OIDC_NONCE_KEY,
892 handle->oidc->nonce);
893 }
894 if (NULL != handle->oidc->claims)
895 {
896 GNUNET_STRINGS_urlencode (handle->oidc->claims,
897 strlen (handle->oidc->claims),
898 &tmp);
899 GNUNET_buffer_write_fstr (&buf,
900 "&%s=%s",
901 OIDC_CLAIMS_KEY,
902 tmp);
903 GNUNET_free (tmp);
904 }
905 new_redirect = GNUNET_buffer_reap_str (&buf);
906 resp = GNUNET_REST_create_response ("");
907 MHD_add_response_header (resp, "Location", new_redirect);
908 GNUNET_free (login_base_url);
909 }
910 else
911 {
912 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
913 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
914 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
915 GNUNET_SCHEDULER_add_now (&do_error, handle);
916 return;
917 }
918 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
919 GNUNET_free (new_redirect);
920 cleanup_handle (handle);
921}
922
923
924/**
925 * Does internal server error when iteration failed.
926 */
927static void
928oidc_iteration_error (void *cls)
929{
930 struct RequestHandle *handle = cls;
931
932 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
933 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
934 GNUNET_SCHEDULER_add_now (&do_error, handle);
935}
936
937
938/**
939 * Issues ticket and redirects to relying party with the authorization code as
940 * parameter. Otherwise redirects with error
941 */
942static void
943oidc_ticket_issue_cb (void *cls,
944 const struct GNUNET_RECLAIM_Ticket *ticket,
945 const struct GNUNET_RECLAIM_PresentationList *pres)
946{
947 struct RequestHandle *handle = cls;
948 struct MHD_Response *resp;
949 char *ticket_str;
950 char *redirect_uri;
951 char *code_string;
952
953 handle->idp_op = NULL;
954 if (NULL == ticket)
955 {
956 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
957 handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
958 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
959 return;
960 }
961 handle->ticket = *ticket;
962 ticket_str =
963 GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
964 sizeof(struct GNUNET_RECLAIM_Ticket));
965 code_string = OIDC_build_authz_code (&handle->priv_key,
966 &handle->ticket,
967 handle->attr_idtoken_list,
968 pres,
969 handle->oidc->nonce,
970 handle->oidc->code_challenge);
971 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
972 (NULL != handle->tld))
973 {
974 GNUNET_asprintf (&redirect_uri,
975 "%s.%s/%s%s%s=%s&state=%s",
976 handle->redirect_prefix,
977 handle->tld,
978 handle->redirect_suffix,
979 (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
980 "&"),
981 handle->oidc->response_type,
982 code_string,
983 handle->oidc->state);
984 }
985 else
986 {
987 GNUNET_asprintf (&redirect_uri,
988 "%s%s%s=%s&state=%s",
989 handle->oidc->redirect_uri,
990 (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
991 "&"),
992 handle->oidc->response_type,
993 code_string,
994 handle->oidc->state);
995 }
996 resp = GNUNET_REST_create_response ("");
997 MHD_add_response_header (resp, "Location", redirect_uri);
998 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
999 cleanup_handle (handle);
1000 GNUNET_free (redirect_uri);
1001 GNUNET_free (ticket_str);
1002 GNUNET_free (code_string);
1003}
1004
1005
1006static struct GNUNET_RECLAIM_AttributeList*
1007attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a,
1008 struct GNUNET_RECLAIM_AttributeList *list_b)
1009{
1010 struct GNUNET_RECLAIM_AttributeList *merged_list;
1011 struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1012 struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1013 struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1014
1015 merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1016 for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1017 {
1018 le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1019 le_m->attribute = GNUNET_RECLAIM_attribute_new (le_a->attribute->name,
1020 &le_a->attribute->
1021 credential,
1022 le_a->attribute->type,
1023 le_a->attribute->data,
1024 le_a->attribute->data_size);
1025 le_m->attribute->id = le_a->attribute->id;
1026 le_m->attribute->flag = le_a->attribute->flag;
1027 le_m->attribute->credential = le_a->attribute->credential;
1028 GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1029 merged_list->list_tail,
1030 le_m);
1031 }
1032 le_m = NULL;
1033 for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1034 {
1035 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1036 {
1037 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&le_m->attribute->id,
1038 &le_b->attribute->id))
1039 break; /** Attribute already in list **/
1040 }
1041 if (NULL != le_m)
1042 continue; /** Attribute already in list **/
1043 le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1044 le_m->attribute = GNUNET_RECLAIM_attribute_new (le_b->attribute->name,
1045 &le_b->attribute->
1046 credential,
1047 le_b->attribute->type,
1048 le_b->attribute->data,
1049 le_b->attribute->data_size);
1050 le_m->attribute->id = le_b->attribute->id;
1051 le_m->attribute->flag = le_b->attribute->flag;
1052 le_m->attribute->credential = le_b->attribute->credential;
1053 GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1054 merged_list->list_tail,
1055 le_m);
1056 }
1057 return merged_list;
1058}
1059
1060
1061static void
1062oidc_cred_collect_finished_cb (void *cls)
1063{
1064 struct RequestHandle *handle = cls;
1065 struct GNUNET_RECLAIM_AttributeList *merged_list;
1066 struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1067
1068 handle->cred_it = NULL;
1069 merged_list = attribute_list_merge (handle->attr_idtoken_list,
1070 handle->attr_userinfo_list);
1071 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1073 "List Attibute in ticket to issue: %s\n",
1074 le_m->attribute->name);
1075 handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
1076 &handle->priv_key,
1077 &handle->oidc->client_pkey,
1078 merged_list,
1079 &oidc_ticket_issue_cb,
1080 handle);
1081 GNUNET_RECLAIM_attribute_list_destroy (merged_list);
1082}
1083
1084
1085/**
1086 * Collects all attributes for an ego if in scope parameter
1087 */
1088static void
1089oidc_cred_collect (void *cls,
1090 const struct GNUNET_IDENTITY_PublicKey *identity,
1091 const struct GNUNET_RECLAIM_Credential *cred)
1092{
1093 struct RequestHandle *handle = cls;
1094 struct GNUNET_RECLAIM_AttributeListEntry *le;
1095 struct GNUNET_RECLAIM_CredentialListEntry *ale;
1096
1097 for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1098 {
1099 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&ale->credential->id,
1100 &cred->id))
1101 continue;
1102 /** Credential already in list **/
1103 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
1104 return;
1105 }
1106
1107 for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1108 {
1109 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
1110 &cred->id))
1111 continue;
1112 /** Credential matches for attribute, add **/
1113 ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
1114 ale->credential = GNUNET_RECLAIM_credential_new (cred->name,
1115 cred->type,
1116 cred->data,
1117 cred->data_size);
1118 GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1119 handle->credentials->list_tail,
1120 ale);
1121 }
1122 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
1123}
1124
1125
1126static void
1127oidc_attr_collect_finished_cb (void *cls)
1128{
1129 struct RequestHandle *handle = cls;
1130
1131 handle->attr_it = NULL;
1132 handle->ticket_it = NULL;
1133 if (NULL == handle->attr_idtoken_list->list_head)
1134 {
1135 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_SCOPE);
1136 handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1137 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1138 return;
1139 }
1140 handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1141 handle->cred_it =
1142 GNUNET_RECLAIM_get_credentials_start (idp,
1143 &handle->priv_key,
1144 &oidc_iteration_error,
1145 handle,
1146 &oidc_cred_collect,
1147 handle,
1148 &oidc_cred_collect_finished_cb,
1149 handle);
1150
1151}
1152
1153
1154static int
1155attr_in_claims_request (struct RequestHandle *handle,
1156 const char *attr_name,
1157 const char *claims_parameter)
1158{
1159 int ret = GNUNET_NO;
1160 json_t *root;
1161 json_error_t error;
1162 json_t *claims_j;
1163 const char *key;
1164 json_t *value;
1165
1166 /** Check if attribute is requested through a scope **/
1167 if (GNUNET_YES == OIDC_check_scopes_for_claim_request (handle->oidc->scope,
1168 attr_name))
1169 return GNUNET_YES;
1170
1171 /** Try claims parameter if not in scope */
1172 if ((NULL != handle->oidc->claims) &&
1173 (GNUNET_YES != ret))
1174 {
1175 root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1176 claims_j = json_object_get (root, claims_parameter);
1177 /* obj is a JSON object */
1178 if (NULL != claims_j)
1179 {
1180 json_object_foreach (claims_j, key, value) {
1181 if (0 != strcmp (attr_name, key))
1182 continue;
1183 ret = GNUNET_YES;
1184 break;
1185 }
1186 }
1187 json_decref (root);
1188 }
1189 return ret;
1190}
1191
1192
1193static int
1194attr_in_idtoken_request (struct RequestHandle *handle,
1195 const char *attr_name)
1196{
1197 return attr_in_claims_request (handle, attr_name, "id_token");
1198}
1199
1200
1201static int
1202attr_in_userinfo_request (struct RequestHandle *handle,
1203 const char *attr_name)
1204{
1205 return attr_in_claims_request (handle, attr_name, "userinfo");
1206}
1207
1208
1209/**
1210 * Collects all attributes for an ego if in scope parameter
1211 */
1212static void
1213oidc_attr_collect (void *cls,
1214 const struct GNUNET_IDENTITY_PublicKey *identity,
1215 const struct GNUNET_RECLAIM_Attribute *attr)
1216{
1217 struct RequestHandle *handle = cls;
1218 struct GNUNET_RECLAIM_AttributeListEntry *le;
1219 if (GNUNET_YES == attr_in_idtoken_request (handle, attr->name))
1220 {
1221 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1222 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
1223 &attr->credential,
1224 attr->type,
1225 attr->data,
1226 attr->data_size);
1227 le->attribute->id = attr->id;
1228 le->attribute->flag = attr->flag;
1229 le->attribute->credential = attr->credential;
1230 GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1231 handle->attr_idtoken_list->list_tail,
1232 le);
1233 }
1234 if (GNUNET_YES == attr_in_userinfo_request (handle, attr->name))
1235 {
1236 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1237 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
1238 &attr->credential,
1239 attr->type,
1240 attr->data,
1241 attr->data_size);
1242 le->attribute->id = attr->id;
1243 le->attribute->flag = attr->flag;
1244 le->attribute->credential = attr->credential;
1245 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1246 handle->attr_userinfo_list->list_tail,
1247 le);
1248 }
1249
1250 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1251}
1252
1253
1254/**
1255 * Checks time and cookie and redirects accordingly
1256 */
1257static void
1258code_redirect (void *cls)
1259{
1260 struct RequestHandle *handle = cls;
1261 struct GNUNET_TIME_Absolute current_time;
1262 struct GNUNET_TIME_Absolute *relog_time;
1263 struct GNUNET_IDENTITY_PublicKey pubkey;
1264 struct GNUNET_IDENTITY_PublicKey ego_pkey;
1265 struct GNUNET_HashCode cache_key;
1266 char *identity_cookie;
1267
1268 GNUNET_asprintf (&identity_cookie,
1269 "Identity=%s",
1270 handle->oidc->login_identity);
1271 GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1272 GNUNET_free (identity_cookie);
1273 // No login time for identity -> redirect to login
1274 if (GNUNET_YES ==
1275 GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
1276 {
1277 relog_time =
1278 GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1279 current_time = GNUNET_TIME_absolute_get ();
1280 // 30 min after old login -> redirect to login
1281 if (current_time.abs_value_us <= relog_time->abs_value_us)
1282 {
1283 if (GNUNET_OK !=
1284 GNUNET_IDENTITY_public_key_from_string (handle->oidc
1285 ->login_identity,
1286 &pubkey))
1287 {
1288 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_COOKIE);
1289 handle->edesc =
1290 GNUNET_strdup ("The cookie of a login identity is not valid");
1291 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1292 return;
1293 }
1294 // iterate over egos and compare their public key
1295 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1296 handle->ego_entry = handle->ego_entry->next)
1297 {
1298 GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1299 if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1300 {
1301 handle->priv_key =
1302 *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
1303 handle->attr_idtoken_list =
1304 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1305 handle->attr_userinfo_list =
1306 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1307 handle->attr_it =
1308 GNUNET_RECLAIM_get_attributes_start (idp,
1309 &handle->priv_key,
1310 &oidc_iteration_error,
1311 handle,
1312 &oidc_attr_collect,
1313 handle,
1314 &oidc_attr_collect_finished_cb,
1315 handle);
1316 return;
1317 }
1318 }
1319 GNUNET_SCHEDULER_add_now (&login_redirect, handle);
1320 return;
1321 }
1322 }
1323}
1324
1325
1326static void
1327build_redirect (void *cls)
1328{
1329 struct RequestHandle *handle = cls;
1330 struct MHD_Response *resp;
1331 char *redirect_uri;
1332
1333 if (GNUNET_YES == handle->oidc->user_cancelled)
1334 {
1335 if ((NULL != handle->redirect_prefix) &&
1336 (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1337 {
1338 GNUNET_asprintf (&redirect_uri,
1339 "%s.%s/%s?error=%s&error_description=%s&state=%s",
1340 handle->redirect_prefix,
1341 handle->tld,
1342 handle->redirect_suffix,
1343 "access_denied",
1344 "User denied access",
1345 handle->oidc->state);
1346 }
1347 else
1348 {
1349 GNUNET_asprintf (&redirect_uri,
1350 "%s?error=%s&error_description=%s&state=%s",
1351 handle->oidc->redirect_uri,
1352 "access_denied",
1353 "User denied access",
1354 handle->oidc->state);
1355 }
1356 resp = GNUNET_REST_create_response ("");
1357 MHD_add_response_header (resp, "Location", redirect_uri);
1358 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1359 cleanup_handle (handle);
1360 GNUNET_free (redirect_uri);
1361 return;
1362 }
1363 GNUNET_SCHEDULER_add_now (&code_redirect, handle);
1364}
1365
1366
1367static void
1368lookup_redirect_uri_result (void *cls,
1369 uint32_t rd_count,
1370 const struct GNUNET_GNSRECORD_Data *rd)
1371{
1372 struct RequestHandle *handle = cls;
1373 char *tmp;
1374 char *tmp_key_str;
1375 char *pos;
1376 struct GNUNET_IDENTITY_PublicKey redirect_zone;
1377
1378 handle->gns_op = NULL;
1379 if (0 == rd_count)
1380 {
1381 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1382 handle->edesc =
1383 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1384 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1385 return;
1386 }
1387 for (int i = 0; i < rd_count; i++)
1388 {
1389 if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1390 continue;
1391 if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1392 continue;
1393 tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1394 if (NULL == strstr (tmp, handle->oidc->client_id))
1395 {
1396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1397 "Redirect uri %s does not contain client_id %s\n",
1398 tmp,
1399 handle->oidc->client_id);
1400 }
1401 else
1402 {
1403 pos = strrchr (tmp, (unsigned char) '.');
1404 if (NULL == pos)
1405 {
1406 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1407 "Redirect uri %s contains client_id but is malformed\n",
1408 tmp);
1409 GNUNET_free (tmp);
1410 continue;
1411 }
1412 *pos = '\0';
1413 handle->redirect_prefix = GNUNET_strdup (tmp);
1414 tmp_key_str = pos + 1;
1415 pos = strchr (tmp_key_str, (unsigned char) '/');
1416 if (NULL == pos)
1417 {
1418 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1419 "Redirect uri %s contains client_id but is malformed\n",
1420 tmp);
1421 GNUNET_free (tmp);
1422 continue;
1423 }
1424 *pos = '\0';
1425 handle->redirect_suffix = GNUNET_strdup (pos + 1);
1426
1427 GNUNET_STRINGS_string_to_data (tmp_key_str,
1428 strlen (tmp_key_str),
1429 &redirect_zone,
1430 sizeof(redirect_zone));
1431 }
1432 GNUNET_SCHEDULER_add_now (&build_redirect, handle);
1433 GNUNET_free (tmp);
1434 return;
1435 }
1436 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1437 handle->edesc =
1438 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1439 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1440}
1441
1442
1443/**
1444 * Initiate redirect back to client.
1445 */
1446static void
1447client_redirect (void *cls)
1448{
1449 struct RequestHandle *handle = cls;
1450
1451 /* Lookup client redirect uri to verify request */
1452 handle->gns_op =
1453 GNUNET_GNS_lookup (gns_handle,
1454 GNUNET_GNS_EMPTY_LABEL_AT,
1455 &handle->oidc->client_pkey,
1456 GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT,
1457 GNUNET_GNS_LO_DEFAULT,
1458 &lookup_redirect_uri_result,
1459 handle);
1460}
1461
1462
1463static char *
1464get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1465{
1466 struct GNUNET_HashCode hc;
1467 char *value;
1468 char *res;
1469
1470 GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1471 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1472 ->url_param_map,
1473 &hc))
1474 return NULL;
1475 value =
1476 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1477 if (NULL == value)
1478 return NULL;
1479 GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1480 return res;
1481}
1482
1483
1484/**
1485 * Iteration over all results finished, build final
1486 * response.
1487 *
1488 * @param cls the `struct RequestHandle`
1489 */
1490static void
1491build_authz_response (void *cls)
1492{
1493 struct RequestHandle *handle = cls;
1494 struct GNUNET_HashCode cache_key;
1495
1496 char *expected_scope;
1497 char delimiter[] = " ";
1498 int number_of_ignored_parameter, iterator;
1499
1500
1501 // REQUIRED value: redirect_uri
1502 handle->oidc->redirect_uri =
1503 get_url_parameter_copy (handle, OIDC_REDIRECT_URI_KEY);
1504 if (NULL == handle->oidc->redirect_uri)
1505 {
1506 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
1507 handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1508 GNUNET_SCHEDULER_add_now (&do_error, handle);
1509 return;
1510 }
1511
1512 // REQUIRED value: response_type
1513 handle->oidc->response_type =
1514 get_url_parameter_copy (handle, OIDC_RESPONSE_TYPE_KEY);
1515 if (NULL == handle->oidc->response_type)
1516 {
1517 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
1518 handle->edesc = GNUNET_strdup ("missing parameter response_type");
1519 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1520 return;
1521 }
1522
1523 // REQUIRED value: scope
1524 handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1525 if (NULL == handle->oidc->scope)
1526 {
1527 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_SCOPE);
1528 handle->edesc = GNUNET_strdup ("missing parameter scope");
1529 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1530 return;
1531 }
1532
1533 // OPTIONAL value: nonce
1534 handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
1535
1536 // OPTIONAL value: claims
1537 handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY);
1538
1539 // TODO check other values if needed
1540 number_of_ignored_parameter =
1541 sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1542 for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1543 {
1544 GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator],
1545 strlen (OIDC_ignored_parameter_array[iterator]),
1546 &cache_key);
1547 if (GNUNET_YES ==
1548 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1549 ->url_param_map,
1550 &cache_key))
1551 {
1552 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_ACCESS_DENIED);
1553 GNUNET_asprintf (&handle->edesc,
1554 "Server will not handle parameter: %s",
1555 OIDC_ignored_parameter_array[iterator]);
1556 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1557 return;
1558 }
1559 }
1560
1561 // We only support authorization code flows.
1562 if (0 != strcmp (handle->oidc->response_type,
1563 OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE))
1564 {
1565 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE);
1566 handle->edesc = GNUNET_strdup ("The authorization server does not support "
1567 "obtaining this authorization code.");
1568 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1569 return;
1570 }
1571
1572 // Checks if scope contains 'openid'
1573 expected_scope = GNUNET_strdup (handle->oidc->scope);
1574 char *test;
1575 test = strtok (expected_scope, delimiter);
1576 while (NULL != test)
1577 {
1578 if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1579 break;
1580 test = strtok (NULL, delimiter);
1581 }
1582 if (NULL == test)
1583 {
1584 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_SCOPE);
1585 handle->edesc =
1586 GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1587 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1588 GNUNET_free (expected_scope);
1589 return;
1590 }
1591
1592 GNUNET_free (expected_scope);
1593 if ((NULL == handle->oidc->login_identity) &&
1594 (GNUNET_NO == handle->oidc->user_cancelled))
1595 GNUNET_SCHEDULER_add_now (&login_redirect, handle);
1596 else
1597 GNUNET_SCHEDULER_add_now (&client_redirect, handle);
1598}
1599
1600
1601/**
1602 * Iterate over tlds in config
1603 */
1604static void
1605tld_iter (void *cls, const char *section, const char *option, const char *value)
1606{
1607 struct RequestHandle *handle = cls;
1608 struct GNUNET_IDENTITY_PublicKey pkey;
1609
1610 if (GNUNET_OK !=
1611 GNUNET_IDENTITY_public_key_from_string (value, &pkey))
1612 {
1613 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1614 return;
1615 }
1616 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1617 handle->tld = GNUNET_strdup (option + 1);
1618}
1619
1620
1621/**
1622 * Responds to authorization GET and url-encoded POST request
1623 *
1624 * @param con_handle the connection handle
1625 * @param url the url
1626 * @param cls the RequestHandle
1627 */
1628static void
1629authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1630 const char *url,
1631 void *cls)
1632{
1633 struct RequestHandle *handle = cls;
1634 struct EgoEntry *tmp_ego;
1635 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1636 struct GNUNET_IDENTITY_PublicKey pkey;
1637
1638 cookie_identity_interpretation (handle);
1639
1640 // RECOMMENDED value: state - REQUIRED for answers
1641 handle->oidc->state = get_url_parameter_copy (handle, OIDC_STATE_KEY);
1642
1643 // REQUIRED value: client_id
1644 handle->oidc->client_id = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
1645 if (NULL == handle->oidc->client_id)
1646 {
1647 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
1648 handle->edesc = GNUNET_strdup ("missing parameter client_id");
1649 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1650 GNUNET_SCHEDULER_add_now (&do_error, handle);
1651 return;
1652 }
1653
1654 // OPTIONAL value: code_challenge
1655 handle->oidc->code_challenge = get_url_parameter_copy (handle,
1656 OIDC_CODE_CHALLENGE_KEY);
1657 if (NULL == handle->oidc->code_challenge)
1658 {
1659 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1660 "OAuth authorization request does not contain PKCE parameters!\n");
1661 }
1662
1663 if (GNUNET_OK !=
1664 GNUNET_IDENTITY_public_key_from_string (handle->oidc->client_id,
1665 &handle->oidc->client_pkey))
1666 {
1667 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT);
1668 handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1669 "authorization code using this method.");
1670 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1671 GNUNET_SCHEDULER_add_now (&do_error, handle);
1672 return;
1673 }
1674
1675 // If we know this identity, translated the corresponding TLD
1676 // TODO: We might want to have a reverse lookup functionality for TLDs?
1677 for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1678 {
1679 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1680 GNUNET_IDENTITY_key_get_public (priv_key, &pkey);
1681 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1682 {
1683 handle->tld = GNUNET_strdup (tmp_ego->identifier);
1684 handle->ego_entry = ego_tail;
1685 }
1686 }
1687 handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1688 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scope: %s\n", handle->oidc->scope);
1689 if (NULL == handle->tld)
1690 GNUNET_CONFIGURATION_iterate_section_values (cfg, "gns", tld_iter, handle);
1691 if (NULL == handle->tld)
1692 handle->tld = GNUNET_strdup (handle->oidc->client_id);
1693 GNUNET_SCHEDULER_add_now (&build_authz_response, handle);
1694}
1695
1696
1697/**
1698 * Combines an identity with a login time and responds OK to login request
1699 *
1700 * @param con_handle the connection handle
1701 * @param url the url
1702 * @param cls the RequestHandle
1703 */
1704static void
1705login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1706 const char *url,
1707 void *cls)
1708{
1709 struct MHD_Response *resp = GNUNET_REST_create_response ("");
1710 struct RequestHandle *handle = cls;
1711 struct GNUNET_HashCode cache_key;
1712 struct GNUNET_TIME_Absolute *current_time;
1713 struct GNUNET_TIME_Absolute *last_time;
1714 char *cookie;
1715 char *header_val;
1716 json_t *root;
1717 json_error_t error;
1718 json_t *identity;
1719 char term_data[handle->rest_handle->data_size + 1];
1720
1721 term_data[handle->rest_handle->data_size] = '\0';
1722 GNUNET_memcpy (term_data,
1723 handle->rest_handle->data,
1724 handle->rest_handle->data_size);
1725 root = json_loads (term_data, JSON_DECODE_ANY, &error);
1726 identity = json_object_get (root, "identity");
1727 if (! json_is_string (identity))
1728 {
1729 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1730 "Error parsing json string from %s\n",
1731 term_data);
1732 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1733 json_decref (root);
1734 cleanup_handle (handle);
1735 return;
1736 }
1737 GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1738 GNUNET_asprintf (&header_val,
1739 "%s;Max-Age=%d",
1740 cookie,
1741 OIDC_COOKIE_EXPIRATION);
1742 MHD_add_response_header (resp, "Set-Cookie", header_val);
1743 MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
1744 GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1745
1746 if (0 != strcmp (json_string_value (identity), "Denied"))
1747 {
1748 current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1749 *current_time = GNUNET_TIME_relative_to_absolute (
1750 GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
1751 OIDC_COOKIE_EXPIRATION));
1752 last_time =
1753 GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1754 GNUNET_free (last_time);
1755 GNUNET_CONTAINER_multihashmap_put (OIDC_cookie_jar_map,
1756 &cache_key,
1757 current_time,
1758 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1759 }
1760 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1761 GNUNET_free (cookie);
1762 GNUNET_free (header_val);
1763 json_decref (root);
1764 cleanup_handle (handle);
1765}
1766
1767
1768static int
1769parse_credentials_basic_auth (struct RequestHandle *handle,
1770 char **client_id,
1771 char **client_secret)
1772{
1773 struct GNUNET_HashCode cache_key;
1774 char *authorization;
1775 char *credentials;
1776 char *basic_authorization;
1777 char *client_id_tmp;
1778 char *pass;
1779
1780 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
1781 strlen (OIDC_AUTHORIZATION_HEADER_KEY),
1782 &cache_key);
1783 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1784 ->header_param_map,
1785 &cache_key))
1786 return GNUNET_SYSERR;
1787 authorization =
1788 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1789 &cache_key);
1790
1791 // split header in "Basic" and [content]
1792 credentials = strtok (authorization, " ");
1793 if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1794 return GNUNET_SYSERR;
1795 credentials = strtok (NULL, " ");
1796 if (NULL == credentials)
1797 return GNUNET_SYSERR;
1798 GNUNET_STRINGS_base64_decode (credentials,
1799 strlen (credentials),
1800 (void **) &basic_authorization);
1801
1802 if (NULL == basic_authorization)
1803 return GNUNET_SYSERR;
1804 client_id_tmp = strtok (basic_authorization, ":");
1805 if (NULL == client_id_tmp)
1806 {
1807 GNUNET_free (basic_authorization);
1808 return GNUNET_SYSERR;
1809 }
1810 pass = strtok (NULL, ":");
1811 if (NULL == pass)
1812 {
1813 GNUNET_free (basic_authorization);
1814 return GNUNET_SYSERR;
1815 }
1816 *client_id = strdup (client_id_tmp);
1817 *client_secret = strdup (pass);
1818 GNUNET_free (basic_authorization);
1819 return GNUNET_OK;
1820}
1821
1822
1823static int
1824parse_credentials_post_body (struct RequestHandle *handle,
1825 char **client_id,
1826 char **client_secret)
1827{
1828 struct GNUNET_HashCode cache_key;
1829 char *client_id_tmp;
1830 char *pass;
1831
1832 GNUNET_CRYPTO_hash ("client_id",
1833 strlen ("client_id"),
1834 &cache_key);
1835 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1836 ->url_param_map,
1837 &cache_key))
1838 return GNUNET_SYSERR;
1839 client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
1840 handle->rest_handle->url_param_map,
1841 &cache_key);
1842 if (NULL == client_id_tmp)
1843 return GNUNET_SYSERR;
1844 *client_id = strdup (client_id_tmp);
1845 GNUNET_CRYPTO_hash ("client_secret",
1846 strlen ("client_secret"),
1847 &cache_key);
1848 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1849 ->url_param_map,
1850 &cache_key))
1851 return GNUNET_SYSERR;
1852 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1853 &cache_key);
1854 if (NULL == pass)
1855 return GNUNET_SYSERR;
1856 *client_secret = strdup (pass);
1857 return GNUNET_OK;
1858}
1859
1860
1861static int
1862check_authorization (struct RequestHandle *handle,
1863 struct GNUNET_IDENTITY_PublicKey *cid)
1864{
1865 char *expected_pass;
1866 char *received_cid;
1867 char *received_cpw;
1868 char *pkce_cv;
1869
1870 if (GNUNET_OK == parse_credentials_basic_auth (handle,
1871 &received_cid,
1872 &received_cpw))
1873 {
1874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1875 "Received client credentials in HTTP AuthZ header\n");
1876 }
1877 else if (GNUNET_OK == parse_credentials_post_body (handle,
1878 &received_cid,
1879 &received_cpw))
1880 {
1881 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1882 "Received client credentials in POST body\n");
1883 }
1884 else
1885 {
1886 /** Allow public clients with PKCE **/
1887 pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
1888 if (NULL == pkce_cv)
1889 {
1890 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1891 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1892 return GNUNET_SYSERR;
1893 }
1894 handle->public_client = GNUNET_YES;
1895 GNUNET_free (pkce_cv);
1896 received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
1897 GNUNET_STRINGS_string_to_data (received_cid,
1898 strlen (received_cid),
1899 cid,
1900 sizeof(struct GNUNET_IDENTITY_PublicKey));
1901 GNUNET_free (received_cid);
1902 return GNUNET_OK;
1903
1904 }
1905
1906 // check client password
1907 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
1908 "reclaim-rest-plugin",
1909 "OIDC_CLIENT_SECRET",
1910 &expected_pass))
1911 {
1912 if (0 != strcmp (expected_pass, received_cpw))
1913 {
1914 GNUNET_free (expected_pass);
1915 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1916 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1917 return GNUNET_SYSERR;
1918 }
1919 GNUNET_free (expected_pass);
1920 }
1921 else
1922 {
1923 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1924 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1925 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1926 return GNUNET_SYSERR;
1927 }
1928 // check client_id
1929 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1930 handle->ego_entry = handle->ego_entry->next)
1931 {
1932 if (0 == strcmp (handle->ego_entry->keystring, received_cid))
1933 break;
1934 }
1935 if (NULL == handle->ego_entry)
1936 {
1937 GNUNET_free (received_cpw);
1938 GNUNET_free (received_cid);
1939 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1940 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1941 return GNUNET_SYSERR;
1942 }
1943 GNUNET_STRINGS_string_to_data (received_cid,
1944 strlen (received_cid),
1945 cid,
1946 sizeof(struct GNUNET_IDENTITY_PublicKey));
1947
1948 GNUNET_free (received_cpw);
1949 GNUNET_free (received_cid);
1950 return GNUNET_OK;
1951}
1952
1953
1954const struct EgoEntry *
1955find_ego (struct RequestHandle *handle,
1956 struct GNUNET_IDENTITY_PublicKey *test_key)
1957{
1958 struct EgoEntry *ego_entry;
1959 struct GNUNET_IDENTITY_PublicKey pub_key;
1960
1961 for (ego_entry = ego_head; NULL != ego_entry;
1962 ego_entry = ego_entry->next)
1963 {
1964 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
1965 if (0 == GNUNET_memcmp (&pub_key, test_key))
1966 return ego_entry;
1967 }
1968 return NULL;
1969}
1970
1971
1972/**
1973 * Responds to token url-encoded POST request
1974 *
1975 * @param con_handle the connection handle
1976 * @param url the url
1977 * @param cls the RequestHandle
1978 */
1979static void
1980token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1981 const char *url,
1982 void *cls)
1983{
1984 struct RequestHandle *handle = cls;
1985 const struct EgoEntry *ego_entry;
1986 struct GNUNET_TIME_Relative expiration_time;
1987 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
1988 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
1989 struct GNUNET_RECLAIM_Ticket ticket;
1990 struct GNUNET_IDENTITY_PublicKey cid;
1991 struct GNUNET_HashCode cache_key;
1992 struct MHD_Response *resp;
1993 char *grant_type;
1994 char *code;
1995 char *json_response;
1996 char *id_token;
1997 char *access_token;
1998 char *jwt_secret;
1999 char *nonce;
2000 char *code_verifier;
2001
2002 /*
2003 * Check Authorization
2004 */
2005 if (GNUNET_SYSERR == check_authorization (handle, &cid))
2006 {
2007 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2008 "OIDC authorization for token endpoint failed\n");
2009 GNUNET_SCHEDULER_add_now (&do_error, handle);
2010 return;
2011 }
2012
2013 /*
2014 * Check parameter
2015 */
2016
2017 // TODO Do not allow multiple equal parameter names
2018 // REQUIRED grant_type
2019 GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY,
2020 strlen (OIDC_GRANT_TYPE_KEY),
2021 &cache_key);
2022 grant_type = get_url_parameter_copy (handle, OIDC_GRANT_TYPE_KEY);
2023 if (NULL == grant_type)
2024 {
2025 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2026 handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2027 handle->response_code = MHD_HTTP_BAD_REQUEST;
2028 GNUNET_SCHEDULER_add_now (&do_error, handle);
2029 return;
2030 }
2031
2032 // Check parameter grant_type == "authorization_code"
2033 if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2034 {
2035 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE);
2036 handle->response_code = MHD_HTTP_BAD_REQUEST;
2037 GNUNET_free (grant_type);
2038 GNUNET_SCHEDULER_add_now (&do_error, handle);
2039 return;
2040 }
2041 GNUNET_free (grant_type);
2042 // REQUIRED code
2043 code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
2044 if (NULL == code)
2045 {
2046 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2047 handle->edesc = GNUNET_strdup ("missing parameter code");
2048 handle->response_code = MHD_HTTP_BAD_REQUEST;
2049 GNUNET_SCHEDULER_add_now (&do_error, handle);
2050 return;
2051 }
2052 ego_entry = find_ego (handle, &cid);
2053 if (NULL == ego_entry)
2054 {
2055 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2056 handle->edesc = GNUNET_strdup ("Unknown client");
2057 handle->response_code = MHD_HTTP_BAD_REQUEST;
2058 GNUNET_free (code);
2059 GNUNET_SCHEDULER_add_now (&do_error, handle);
2060 return;
2061 }
2062
2063 // REQUIRED code verifier
2064 code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
2065 if (NULL == code_verifier)
2066 {
2067 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2068 "OAuth authorization request does not contain PKCE parameters!\n");
2069
2070 }
2071
2072 // decode code
2073 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2074 &cl, &pl, &nonce))
2075 {
2076 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2077 handle->edesc = GNUNET_strdup ("invalid code");
2078 handle->response_code = MHD_HTTP_BAD_REQUEST;
2079 GNUNET_free (code);
2080 GNUNET_SCHEDULER_add_now (&do_error, handle);
2081 return;
2082 }
2083 GNUNET_free (code);
2084
2085 // create jwt
2086 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
2087 "reclaim-rest-plugin",
2088 "expiration_time",
2089 &expiration_time))
2090 {
2091 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
2092 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2093 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2094 GNUNET_SCHEDULER_add_now (&do_error, handle);
2095 return;
2096 }
2097
2098
2099 // TODO OPTIONAL acr,amr,azp
2100 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2101 "reclaim-rest-plugin",
2102 "jwt_secret",
2103 &jwt_secret))
2104 {
2105 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2106 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2107 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2108 GNUNET_SCHEDULER_add_now (&do_error, handle);
2109 return;
2110 }
2111 id_token = OIDC_generate_id_token (&ticket.audience,
2112 &ticket.identity,
2113 cl,
2114 pl,
2115 &expiration_time,
2116 (NULL != nonce) ? nonce : NULL,
2117 jwt_secret);
2118 access_token = OIDC_access_token_new (&ticket);
2119 OIDC_build_token_response (access_token,
2120 id_token,
2121 &expiration_time,
2122 &json_response);
2123
2124 resp = GNUNET_REST_create_response (json_response);
2125 MHD_add_response_header (resp, "Cache-Control", "no-store");
2126 MHD_add_response_header (resp, "Pragma", "no-cache");
2127 MHD_add_response_header (resp, "Content-Type", "application/json");
2128 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2129 GNUNET_RECLAIM_attribute_list_destroy (cl);
2130 GNUNET_RECLAIM_presentation_list_destroy (pl);
2131 GNUNET_free (access_token);
2132 GNUNET_free (json_response);
2133 GNUNET_free (id_token);
2134 cleanup_handle (handle);
2135}
2136
2137
2138/**
2139 * Collects claims and stores them in handle
2140 */
2141static void
2142consume_ticket (void *cls,
2143 const struct GNUNET_IDENTITY_PublicKey *identity,
2144 const struct GNUNET_RECLAIM_Attribute *attr,
2145 const struct GNUNET_RECLAIM_Presentation *pres)
2146{
2147 struct RequestHandle *handle = cls;
2148 struct GNUNET_RECLAIM_AttributeListEntry *ale;
2149 struct GNUNET_RECLAIM_PresentationListEntry *atle;
2150 struct MHD_Response *resp;
2151 char *result_str;
2152 handle->idp_op = NULL;
2153
2154 if (NULL == identity)
2155 {
2156 result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2157 handle->attr_userinfo_list,
2158 handle->presentations);
2159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2160 resp = GNUNET_REST_create_response (result_str);
2161 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2162 GNUNET_free (result_str);
2163 cleanup_handle (handle);
2164 return;
2165 }
2166 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
2167 ale->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
2168 &attr->credential,
2169 attr->type,
2170 attr->data,
2171 attr->data_size);
2172 ale->attribute->id = attr->id;
2173 ale->attribute->flag = attr->flag;
2174 ale->attribute->credential = attr->credential;
2175 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2176 handle->attr_userinfo_list->list_tail,
2177 ale);
2178 if (NULL == pres)
2179 return;
2180 for (atle = handle->presentations->list_head;
2181 NULL != atle; atle = atle->next)
2182 {
2183 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->presentation->credential_id,
2184 &pres->credential_id))
2185 continue;
2186 break; /** already in list **/
2187 }
2188 if (NULL == atle)
2189 {
2190 /** Credential matches for attribute, add **/
2191 atle = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
2192 atle->presentation = GNUNET_RECLAIM_presentation_new (pres->type,
2193 pres->data,
2194 pres->data_size);
2195 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2196 handle->presentations->list_tail,
2197 atle);
2198 }
2199}
2200
2201
2202/**
2203 * Responds to userinfo GET and url-encoded POST request
2204 *
2205 * @param con_handle the connection handle
2206 * @param url the url
2207 * @param cls the RequestHandle
2208 */
2209static void
2210userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2211 const char *url,
2212 void *cls)
2213{
2214 // TODO expiration time
2215 struct RequestHandle *handle = cls;
2216 struct GNUNET_RECLAIM_Ticket *ticket;
2217 char delimiter[] = " ";
2218 struct GNUNET_HashCode cache_key;
2219 char *authorization;
2220 char *authorization_type;
2221 char *authorization_access_token;
2222 const struct EgoEntry *aud_ego;
2223 const struct GNUNET_IDENTITY_PrivateKey *privkey;
2224
2225 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Getting userinfo\n");
2226 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
2227 strlen (OIDC_AUTHORIZATION_HEADER_KEY),
2228 &cache_key);
2229 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
2230 ->header_param_map,
2231 &cache_key))
2232 {
2233 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2234 handle->edesc = GNUNET_strdup ("No Access Token");
2235 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2236 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2237 return;
2238 }
2239 authorization =
2240 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2241 &cache_key);
2242
2243 // split header in "Bearer" and access_token
2244 authorization = GNUNET_strdup (authorization);
2245 authorization_type = strtok (authorization, delimiter);
2246 if ((NULL == authorization_type) ||
2247 (0 != strcmp ("Bearer", authorization_type)))
2248 {
2249 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2250 handle->edesc = GNUNET_strdup ("No Access Token");
2251 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2252 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2253 GNUNET_free (authorization);
2254 return;
2255 }
2256 authorization_access_token = strtok (NULL, delimiter);
2257 if (NULL == authorization_access_token)
2258 {
2259 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2260 handle->edesc = GNUNET_strdup ("Access token missing");
2261 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2262 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2263 GNUNET_free (authorization);
2264 return;
2265 }
2266
2267 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2268 &ticket))
2269 {
2270 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2271 handle->edesc = GNUNET_strdup ("The access token is invalid");
2272 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2273 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2274 GNUNET_free (authorization);
2275 return;
2276
2277 }
2278 GNUNET_assert (NULL != ticket);
2279 handle->ticket = *ticket;
2280 GNUNET_free (ticket);
2281 aud_ego = find_ego (handle, &handle->ticket.audience);
2282 if (NULL == aud_ego)
2283 {
2284 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2285 handle->edesc = GNUNET_strdup ("The access token expired");
2286 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2287 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2288 GNUNET_free (authorization);
2289 return;
2290 }
2291 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Consuming ticket\n");
2292 privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2293 handle->attr_userinfo_list =
2294 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
2295 handle->presentations =
2296 GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
2297
2298 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2299 privkey,
2300 &handle->ticket,
2301 &consume_ticket,
2302 handle);
2303 GNUNET_free (authorization);
2304}
2305
2306
2307/**
2308 * If listing is enabled, prints information about the egos.
2309 *
2310 * This function is initially called for all egos and then again
2311 * whenever a ego's identifier changes or if it is deleted. At the
2312 * end of the initial pass over all egos, the function is once called
2313 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
2314 * be invoked in the future or that there was an error.
2315 *
2316 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
2317 * this function is only called ONCE, and 'NULL' being passed in
2318 * 'ego' does indicate an error (i.e. name is taken or no default
2319 * value is known). If 'ego' is non-NULL and if '*ctx'
2320 * is set in those callbacks, the value WILL be passed to a subsequent
2321 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
2322 * that one was not NULL).
2323 *
2324 * When an identity is renamed, this function is called with the
2325 * (known) ego but the NEW identifier.
2326 *
2327 * When an identity is deleted, this function is called with the
2328 * (known) ego and "NULL" for the 'identifier'. In this case,
2329 * the 'ego' is henceforth invalid (and the 'ctx' should also be
2330 * cleaned up).
2331 *
2332 * @param cls closure
2333 * @param ego ego handle
2334 * @param ctx context for application to store data for this ego
2335 * (during the lifetime of this process, initially NULL)
2336 * @param identifier identifier assigned by the user for this ego,
2337 * NULL if the user just deleted the ego and it
2338 * must thus no longer be used
2339 */
2340static void
2341list_ego (void *cls,
2342 struct GNUNET_IDENTITY_Ego *ego,
2343 void **ctx,
2344 const char *identifier)
2345{
2346 struct EgoEntry *ego_entry;
2347 struct GNUNET_IDENTITY_PublicKey pk;
2348
2349 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
2350 {
2351 state = ID_REST_STATE_POST_INIT;
2352 return;
2353 }
2354 GNUNET_assert (NULL != ego);
2355 if (ID_REST_STATE_INIT == state)
2356
2357 {
2358 ego_entry = GNUNET_new (struct EgoEntry);
2359 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
2360 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
2361 ego_entry->ego = ego;
2362 ego_entry->identifier = GNUNET_strdup (identifier);
2363 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
2364 ego_tail,
2365 ego_entry);
2366 return;
2367 }
2368 /* Ego renamed or added */
2369 if (identifier != NULL)
2370 {
2371 for (ego_entry = ego_head; NULL != ego_entry;
2372 ego_entry = ego_entry->next)
2373 {
2374 if (ego_entry->ego == ego)
2375 {
2376 /* Rename */
2377 GNUNET_free (ego_entry->identifier);
2378 ego_entry->identifier = GNUNET_strdup (identifier);
2379 break;
2380 }
2381 }
2382 if (NULL == ego_entry)
2383 {
2384 /* Add */
2385 ego_entry = GNUNET_new (struct EgoEntry);
2386 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
2387 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
2388 ego_entry->ego = ego;
2389 ego_entry->identifier = GNUNET_strdup (identifier);
2390 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
2391 ego_tail,
2392 ego_entry);
2393 }
2394 }
2395 else
2396 {
2397 /* Delete */
2398 for (ego_entry = ego_head; NULL != ego_entry;
2399 ego_entry = ego_entry->next)
2400 {
2401 if (ego_entry->ego == ego)
2402 break;
2403 }
2404 if (NULL == ego_entry)
2405 return; /* Not found */
2406
2407 GNUNET_CONTAINER_DLL_remove (ego_head,
2408 ego_tail,
2409 ego_entry);
2410 GNUNET_free (ego_entry->identifier);
2411 GNUNET_free (ego_entry->keystring);
2412 GNUNET_free (ego_entry);
2413 return;
2414 }
2415}
2416
2417
2418static void
2419oidc_config_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2420 const char *url,
2421 void *cls)
2422{
2423 json_t *oidc_config;
2424 json_t *auth_methods;
2425 json_t *sig_algs;
2426 json_t *scopes;
2427 json_t *response_types;
2428 json_t *sub_types;
2429 json_t *claim_types;
2430 char *oidc_config_str;
2431 struct MHD_Response *resp;
2432 struct RequestHandle *handle = cls;
2433
2434 oidc_config = json_object ();
2435 // FIXME get from config?
2436 json_object_set_new (oidc_config,
2437 "issuer", json_string ("http://localhost:7776"));
2438 json_object_set_new (oidc_config,
2439 "authorization_endpoint",
2440 json_string ("https://api.reclaim/openid/authorize"));
2441 json_object_set_new (oidc_config,
2442 "token_endpoint",
2443 json_string ("http://localhost:7776/openid/token"));
2444 auth_methods = json_array ();
2445 json_array_append_new (auth_methods,
2446 json_string ("client_secret_basic"));
2447 json_array_append_new (auth_methods,
2448 json_string ("client_secret_post"));
2449 json_object_set_new (oidc_config,
2450 "token_endpoint_auth_methods_supported",
2451 auth_methods);
2452 sig_algs = json_array ();
2453 json_array_append_new (sig_algs,
2454 json_string ("HS512"));
2455 json_object_set_new (oidc_config,
2456 "id_token_signing_alg_values_supported",
2457 sig_algs);
2458 json_object_set_new (oidc_config,
2459 "userinfo_endpoint",
2460 json_string ("http://localhost:7776/openid/userinfo"));
2461 scopes = json_array ();
2462 json_array_append_new (scopes,
2463 json_string ("openid"));
2464 json_array_append_new (scopes,
2465 json_string ("profile"));
2466 json_array_append_new (scopes,
2467 json_string ("email"));
2468 json_array_append_new (scopes,
2469 json_string ("address"));
2470 json_array_append_new (scopes,
2471 json_string ("phone"));
2472 json_object_set_new (oidc_config,
2473 "scopes_supported",
2474 scopes);
2475 response_types = json_array ();
2476 json_array_append_new (response_types,
2477 json_string ("code"));
2478 json_object_set_new (oidc_config,
2479 "response_types_supported",
2480 response_types);
2481 sub_types = json_array ();
2482 json_array_append_new (sub_types,
2483 json_string ("public")); /* no pairwise suppport */
2484 json_object_set_new (oidc_config,
2485 "subject_types_supported",
2486 sub_types);
2487 claim_types = json_array ();
2488 json_array_append_new (claim_types,
2489 json_string ("normal"));
2490 json_array_append_new (claim_types,
2491 json_string ("aggregated"));
2492 json_object_set_new (oidc_config,
2493 "claim_types_supported",
2494 claim_types);
2495 json_object_set_new (oidc_config,
2496 "claims_parameter_supported",
2497 json_boolean (1));
2498 oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2499 resp = GNUNET_REST_create_response (oidc_config_str);
2500 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2501 GNUNET_free (oidc_config_str);
2502 cleanup_handle (handle);
2503}
2504
2505
2506/**
2507 * Respond to OPTIONS request
2508 *
2509 * @param con_handle the connection handle
2510 * @param url the url
2511 * @param cls the RequestHandle
2512 */
2513static void
2514oidc_config_cors (struct GNUNET_REST_RequestHandle *con_handle,
2515 const char *url,
2516 void *cls)
2517{
2518 struct MHD_Response *resp;
2519 struct RequestHandle *handle = cls;
2520
2521 // For now, independent of path return all options
2522 resp = GNUNET_REST_create_response (NULL);
2523 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
2524 MHD_add_response_header (resp, "Access-Control-Allow-Origin", "*");
2525 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2526 cleanup_handle (handle);
2527 return;
2528}
2529
2530
2531static enum GNUNET_GenericReturnValue
2532rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
2533 GNUNET_REST_ResultProcessor proc,
2534 void *proc_cls)
2535{
2536 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
2537 struct GNUNET_REST_RequestHandlerError err;
2538 static const struct GNUNET_REST_RequestHandler handlers[] =
2539 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
2540 { MHD_HTTP_METHOD_POST,
2541 GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, // url-encoded
2542 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
2543 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2544 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2545 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2546 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
2547 &oidc_config_endpoint },
2548 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
2549 &oidc_config_cors },
2550 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
2551 GNUNET_REST_HANDLER_END };
2552
2553 handle->oidc = GNUNET_new (struct OIDC_Variables);
2554 if (NULL == OIDC_cookie_jar_map)
2555 OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
2556 GNUNET_NO);
2557 handle->response_code = 0;
2558 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
2559 handle->proc_cls = proc_cls;
2560 handle->proc = proc;
2561 handle->rest_handle = rest_handle;
2562 handle->url = GNUNET_strdup (rest_handle->url);
2563 handle->timeout_task =
2564 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2565 GNUNET_CONTAINER_DLL_insert (requests_head,
2566 requests_tail,
2567 handle);
2568 if (handle->url[strlen (handle->url) - 1] == '/')
2569 handle->url[strlen (handle->url) - 1] = '\0';
2570 if (GNUNET_NO ==
2571 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2572 return GNUNET_NO;
2573
2574 return GNUNET_YES;
2575}
2576
2577
2578/**
2579 * Entry point for the plugin.
2580 *
2581 * @param cls Config info
2582 * @return NULL on error, otherwise the plugin context
2583 */
2584void *
2585libgnunet_plugin_rest_openid_connect_init (void *cls)
2586{
2587 static struct Plugin plugin;
2588 struct GNUNET_REST_Plugin *api;
2589
2590 cfg = cls;
2591 if (NULL != plugin.cfg)
2592 return NULL; /* can only initialize once! */
2593 memset (&plugin, 0, sizeof(struct Plugin));
2594 plugin.cfg = cfg;
2595 api = GNUNET_new (struct GNUNET_REST_Plugin);
2596 api->cls = &plugin;
2597 api->name = GNUNET_REST_API_NS_OIDC;
2598 api->process_request = &rest_identity_process_request;
2599 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
2600 gns_handle = GNUNET_GNS_connect (cfg);
2601 idp = GNUNET_RECLAIM_connect (cfg);
2602
2603 state = ID_REST_STATE_INIT;
2604 GNUNET_asprintf (&allow_methods,
2605 "%s, %s, %s, %s, %s",
2606 MHD_HTTP_METHOD_GET,
2607 MHD_HTTP_METHOD_POST,
2608 MHD_HTTP_METHOD_PUT,
2609 MHD_HTTP_METHOD_DELETE,
2610 MHD_HTTP_METHOD_OPTIONS);
2611
2612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2613 _ ("OpenID Connect REST API initialized\n"));
2614 return api;
2615}
2616
2617
2618static int
2619cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
2620{
2621 GNUNET_free (value);
2622 return GNUNET_YES;
2623}
2624
2625
2626/**
2627 * Exit point from the plugin.
2628 *
2629 * @param cls the plugin context (as returned by "init")
2630 * @return always NULL
2631 */
2632void *
2633libgnunet_plugin_rest_openid_connect_done (void *cls)
2634{
2635 struct GNUNET_REST_Plugin *api = cls;
2636 struct Plugin *plugin = api->cls;
2637 struct EgoEntry *ego_entry;
2638
2639 plugin->cfg = NULL;
2640 while (NULL != requests_head)
2641 cleanup_handle (requests_head);
2642 if (NULL != OIDC_cookie_jar_map)
2643 {
2644 GNUNET_CONTAINER_multihashmap_iterate (OIDC_cookie_jar_map,
2645 &cleanup_hashmap,
2646 NULL);
2647 GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2648 }
2649 GNUNET_free (allow_methods);
2650 if (NULL != gns_handle)
2651 GNUNET_GNS_disconnect (gns_handle);
2652 if (NULL != identity_handle)
2653 GNUNET_IDENTITY_disconnect (identity_handle);
2654 if (NULL != idp)
2655 GNUNET_RECLAIM_disconnect (idp);
2656 while (NULL != (ego_entry = ego_head))
2657 {
2658 GNUNET_CONTAINER_DLL_remove (ego_head,
2659 ego_tail,
2660 ego_entry);
2661 GNUNET_free (ego_entry->identifier);
2662 GNUNET_free (ego_entry->keystring);
2663 GNUNET_free (ego_entry);
2664 }
2665 GNUNET_free (api);
2666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2667 "OpenID Connect REST plugin is finished\n");
2668 return NULL;
2669}
2670
2671
2672/* end of plugin_rest_openid_connect.c */
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
deleted file mode 100644
index 022744c82..000000000
--- a/src/reclaim/plugin_rest_reclaim.c
+++ /dev/null
@@ -1,1546 +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 * Reponse 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 resp = GNUNET_REST_create_response (emsg);
357 MHD_add_response_header (resp, "Content-Type", "application/json");
358 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
359 if (GNUNET_OK != success)
360 {
361 GNUNET_SCHEDULER_add_now (&do_error, handle);
362 return;
363 }
364 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
365 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
366}
367
368
369static void
370delete_finished_cb (void *cls, int32_t success, const char *emsg)
371{
372 struct RequestHandle *handle = cls;
373 struct MHD_Response *resp;
374
375 resp = GNUNET_REST_create_response (emsg);
376 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
377 if (GNUNET_OK != success)
378 {
379 GNUNET_SCHEDULER_add_now (&do_error, handle);
380 return;
381 }
382 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
383 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
384}
385
386
387/**
388 * Return attributes for identity
389 *
390 * @param cls the request handle
391 */
392static void
393return_response (void *cls)
394{
395 char *result_str;
396 struct RequestHandle *handle = cls;
397 struct MHD_Response *resp;
398
399 result_str = json_dumps (handle->resp_object, 0);
400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
401 resp = GNUNET_REST_create_response (result_str);
402 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
403 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
404 GNUNET_free (result_str);
405 cleanup_handle (handle);
406}
407
408
409static void
410collect_finished_cb (void *cls)
411{
412 struct RequestHandle *handle = cls;
413
414 // Done
415 handle->attr_it = NULL;
416 handle->cred_it = NULL;
417 handle->ticket_it = NULL;
418 GNUNET_SCHEDULER_add_now (&return_response, handle);
419}
420
421
422/**
423 * Collect all attributes for an ego
424 *
425 */
426static void
427ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
428{
429 json_t *json_resource;
430 struct RequestHandle *handle = cls;
431 json_t *value;
432 char *tmp;
433
434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
435 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
436 json_resource = json_object ();
437 GNUNET_free (tmp);
438 json_array_append (handle->resp_object, json_resource);
439
440 tmp =
441 GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
442 sizeof(struct
443 GNUNET_IDENTITY_PublicKey));
444 value = json_string (tmp);
445 json_object_set_new (json_resource, "issuer", value);
446 GNUNET_free (tmp);
447 tmp =
448 GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
449 sizeof(struct
450 GNUNET_IDENTITY_PublicKey));
451 value = json_string (tmp);
452 json_object_set_new (json_resource, "audience", value);
453 GNUNET_free (tmp);
454 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
455 value = json_string (tmp);
456 json_object_set_new (json_resource, "rnd", value);
457 GNUNET_free (tmp);
458 GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
459}
460
461
462static void
463add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
464 const char *url,
465 void *cls)
466{
467 struct RequestHandle *handle = cls;
468 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
469 const char *identity;
470 struct EgoEntry *ego_entry;
471 struct GNUNET_RECLAIM_Credential *attribute;
472 struct GNUNET_TIME_Relative exp;
473 char term_data[handle->rest_handle->data_size + 1];
474 json_t *data_json;
475 json_error_t err;
476 struct GNUNET_JSON_Specification attrspec[] =
477 { GNUNET_RECLAIM_JSON_spec_credential (&attribute),
478 GNUNET_JSON_spec_end () };
479
480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
481 "Adding an credential for %s.\n",
482 handle->url);
483 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
484 handle->url))
485 {
486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
487 GNUNET_SCHEDULER_add_now (&do_error, handle);
488 return;
489 }
490 identity = handle->url + strlen (
491 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
492
493 for (ego_entry = ego_head; NULL != ego_entry;
494 ego_entry = ego_entry->next)
495 if (0 == strcmp (identity, ego_entry->identifier))
496 break;
497
498 if (NULL == ego_entry)
499 {
500 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
501 return;
502 }
503 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
504
505 if (0 >= handle->rest_handle->data_size)
506 {
507 GNUNET_SCHEDULER_add_now (&do_error, handle);
508 return;
509 }
510
511 term_data[handle->rest_handle->data_size] = '\0';
512 GNUNET_memcpy (term_data,
513 handle->rest_handle->data,
514 handle->rest_handle->data_size);
515 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
516 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL);
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_IDENTITY_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 GNUNET_RECLAIM_attribute_list_destroy (attrs);
617 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
618}
619
620
621/**
622 * Lists credential for identity request
623 *
624 * @param con_handle the connection handle
625 * @param url the url
626 * @param cls the RequestHandle
627 */
628static void
629list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
630 const char *url,
631 void *cls)
632{
633 struct RequestHandle *handle = cls;
634 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
635 struct EgoEntry *ego_entry;
636 char *identity;
637
638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
639 "Getting credentials for %s.\n",
640 handle->url);
641 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
642 handle->url))
643 {
644 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
645 GNUNET_SCHEDULER_add_now (&do_error, handle);
646 return;
647 }
648 identity = handle->url + strlen (
649 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
650
651 for (ego_entry = ego_head; NULL != ego_entry;
652 ego_entry = ego_entry->next)
653 if (0 == strcmp (identity, ego_entry->identifier))
654 break;
655 handle->resp_object = json_array ();
656
657
658 if (NULL == ego_entry)
659 {
660 // Done
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
662 GNUNET_SCHEDULER_add_now (&return_response, handle);
663 return;
664 }
665 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
666 handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
667 priv_key,
668 &collect_error_cb,
669 handle,
670 &cred_collect,
671 handle,
672 &
673 collect_finished_cb,
674 handle);
675}
676
677
678/**
679 * Deletes credential from an identity
680 *
681 * @param con_handle the connection handle
682 * @param url the url
683 * @param cls the RequestHandle
684 */
685static void
686delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
687 const char *url,
688 void *cls)
689{
690 struct RequestHandle *handle = cls;
691 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
692 struct GNUNET_RECLAIM_Credential attr;
693 struct EgoEntry *ego_entry;
694 char *identity_id_str;
695 char *identity;
696 char *id;
697
698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting credential.\n");
699 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
700 handle->url))
701 {
702 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
703 GNUNET_SCHEDULER_add_now (&do_error, handle);
704 return;
705 }
706 identity_id_str =
707 strdup (handle->url + strlen (
708 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1);
709 identity = strtok (identity_id_str, "/");
710 id = strtok (NULL, "/");
711 if ((NULL == identity) || (NULL == id))
712 {
713 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
714 GNUNET_free (identity_id_str);
715 GNUNET_SCHEDULER_add_now (&do_error, handle);
716 return;
717 }
718
719 for (ego_entry = ego_head; NULL != ego_entry;
720 ego_entry = ego_entry->next)
721 if (0 == strcmp (identity, ego_entry->identifier))
722 break;
723 handle->resp_object = json_array ();
724 if (NULL == ego_entry)
725 {
726 // Done
727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
728 GNUNET_free (identity_id_str);
729 GNUNET_SCHEDULER_add_now (&return_response, handle);
730 return;
731 }
732 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
733 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Credential));
734 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
735 attr.name = "";
736 handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
737 priv_key,
738 &attr,
739 &delete_finished_cb,
740 handle);
741 GNUNET_free (identity_id_str);
742}
743
744
745/**
746 * List tickets for identity request
747 *
748 * @param con_handle the connection handle
749 * @param url the url
750 * @param cls the RequestHandle
751 */
752static void
753list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
754 const char *url,
755 void *cls)
756{
757 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
758 struct RequestHandle *handle = cls;
759 struct EgoEntry *ego_entry;
760 char *identity;
761
762 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
763 "Getting tickets for %s.\n",
764 handle->url);
765 if (strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= strlen (handle->url))
766 {
767 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
768 GNUNET_SCHEDULER_add_now (&do_error, handle);
769 return;
770 }
771 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
772
773 for (ego_entry = ego_head; NULL != ego_entry;
774 ego_entry = ego_entry->next)
775 if (0 == strcmp (identity, ego_entry->identifier))
776 break;
777 handle->resp_object = json_array ();
778
779 if (NULL == ego_entry)
780 {
781 // Done
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
783 GNUNET_SCHEDULER_add_now (&return_response, handle);
784 return;
785 }
786 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
787 handle->ticket_it =
788 GNUNET_RECLAIM_ticket_iteration_start (idp,
789 priv_key,
790 &collect_error_cb,
791 handle,
792 &ticket_collect,
793 handle,
794 &collect_finished_cb,
795 handle);
796}
797
798
799static void
800add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
801 const char *url,
802 void *cls)
803{
804 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
805 const char *identity;
806 struct RequestHandle *handle = cls;
807 struct EgoEntry *ego_entry;
808 struct GNUNET_RECLAIM_Attribute *attribute;
809 struct GNUNET_TIME_Relative exp;
810 char term_data[handle->rest_handle->data_size + 1];
811 json_t *data_json;
812 json_error_t err;
813 struct GNUNET_JSON_Specification attrspec[] =
814 { GNUNET_RECLAIM_JSON_spec_attribute (&attribute), GNUNET_JSON_spec_end () };
815
816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
817 "Adding an attribute for %s.\n",
818 handle->url);
819 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
820 {
821 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
822 GNUNET_SCHEDULER_add_now (&do_error, handle);
823 return;
824 }
825 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
826
827 for (ego_entry = ego_head; NULL != ego_entry;
828 ego_entry = ego_entry->next)
829 if (0 == strcmp (identity, ego_entry->identifier))
830 break;
831
832 if (NULL == ego_entry)
833 {
834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
835 return;
836 }
837 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
838
839 if (0 >= handle->rest_handle->data_size)
840 {
841 GNUNET_SCHEDULER_add_now (&do_error, handle);
842 return;
843 }
844
845 term_data[handle->rest_handle->data_size] = '\0';
846 GNUNET_memcpy (term_data,
847 handle->rest_handle->data,
848 handle->rest_handle->data_size);
849 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
850 GNUNET_assert (GNUNET_OK ==
851 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
852 json_decref (data_json);
853 if (NULL == attribute)
854 {
855 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
856 "Unable to parse attribute from %s\n",
857 term_data);
858 GNUNET_SCHEDULER_add_now (&do_error, handle);
859 return;
860 }
861 /**
862 * New ID for attribute
863 */
864 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
865 GNUNET_RECLAIM_id_generate (&attribute->id);
866 exp = GNUNET_TIME_UNIT_HOURS;
867 handle->idp_op = GNUNET_RECLAIM_attribute_store (idp,
868 identity_priv,
869 attribute,
870 &exp,
871 &finished_cont,
872 handle);
873 GNUNET_JSON_parse_free (attrspec);
874}
875
876
877/**
878 * Parse a JWT and return the respective claim value as Attribute
879 *
880 * @param cred the jwt credential
881 * @param claim the name of the claim in the JWT
882 *
883 * @return a GNUNET_RECLAIM_Attribute, containing the new value
884 */
885struct GNUNET_RECLAIM_Attribute *
886parse_jwt (const struct GNUNET_RECLAIM_Credential *cred,
887 const char *claim)
888{
889 char *jwt_string;
890 struct GNUNET_RECLAIM_Attribute *attr;
891 char delim[] = ".";
892 const char *type_str = NULL;
893 const char *val_str = NULL;
894 char *data;
895 size_t data_size;
896 uint32_t type;
897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
898 char *decoded_jwt;
899 json_t *json_val;
900 json_error_t *json_err = NULL;
901
902 jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type,
903 cred->data,
904 cred->data_size);
905 char *jwt_body = strtok (jwt_string, delim);
906 jwt_body = strtok (NULL, delim);
907 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
908 (void **) &decoded_jwt);
909 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
910 const char *key;
911 json_t *value;
912 json_object_foreach (json_val, key, value) {
913 if (0 == strcasecmp (key,claim))
914 {
915 val_str = json_dumps (value, JSON_ENCODE_ANY);
916 }
917 }
918 type_str = "String";
919 type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
920 if (GNUNET_SYSERR == GNUNET_RECLAIM_attribute_string_to_value (type,val_str,
921 (void **) &data,
922 &data_size))
923 {
924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
925 "Attribute value from JWT Parser invalid!\n");
926 GNUNET_RECLAIM_attribute_string_to_value (type,
927 "Error: Referenced Claim Name not Found",
928 (void **) &data,
929 &data_size);
930 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
931 type, data, data_size);
932 attr->id = cred->id;
933 attr->flag = 1;
934 }
935 else
936 {
937 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
938 type, data, data_size);
939 attr->id = cred->id;
940 attr->flag = 1;
941 }
942 return attr;
943}
944
945
946/**
947 * Collect all attributes for an ego
948 *
949 */
950static void
951attr_collect (void *cls,
952 const struct GNUNET_IDENTITY_PublicKey *identity,
953 const struct GNUNET_RECLAIM_Attribute *attr)
954{
955 struct RequestHandle *handle = cls;
956 json_t *attr_obj;
957 const char *type;
958 char *id_str;
959
960 char *tmp_value;
961 tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
962 attr->data,
963 attr->data_size);
964 attr_obj = json_object ();
965 json_object_set_new (attr_obj, "value", json_string (tmp_value));
966 json_object_set_new (attr_obj, "name", json_string (attr->name));
967
968 if (GNUNET_RECLAIM_id_is_zero (&attr->credential))
969 json_object_set_new (attr_obj, "flag", json_string ("0"));
970 else
971 json_object_set_new (attr_obj, "flag", json_string ("1"));
972 type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
973 json_object_set_new (attr_obj, "type", json_string (type));
974 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
975 sizeof(attr->id));
976 json_object_set_new (attr_obj, "id", json_string (id_str));
977 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
978 sizeof(attr->credential));
979 json_object_set_new (attr_obj, "credential", json_string (id_str));
980 json_array_append (handle->resp_object, attr_obj);
981 json_decref (attr_obj);
982 GNUNET_free (tmp_value);
983 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
984}
985
986
987/**
988 * List attributes for identity request
989 *
990 * @param con_handle the connection handle
991 * @param url the url
992 * @param cls the RequestHandle
993 */
994static void
995list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
996 const char *url,
997 void *cls)
998{
999 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1000 struct RequestHandle *handle = cls;
1001 struct EgoEntry *ego_entry;
1002 char *identity;
1003
1004 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1005 "Getting attributes for %s.\n",
1006 handle->url);
1007 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1008 {
1009 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1010 GNUNET_SCHEDULER_add_now (&do_error, handle);
1011 return;
1012 }
1013 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
1014
1015 for (ego_entry = ego_head; NULL != ego_entry;
1016 ego_entry = ego_entry->next)
1017 if (0 == strcmp (identity, ego_entry->identifier))
1018 break;
1019 handle->resp_object = json_array ();
1020
1021
1022 if (NULL == ego_entry)
1023 {
1024 // Done
1025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1026 GNUNET_SCHEDULER_add_now (&return_response, handle);
1027 return;
1028 }
1029 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1030 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (idp,
1031 priv_key,
1032 &collect_error_cb,
1033 handle,
1034 &attr_collect,
1035 handle,
1036 &collect_finished_cb,
1037 handle);
1038}
1039
1040
1041/**
1042 * List attributes for identity request
1043 *
1044 * @param con_handle the connection handle
1045 * @param url the url
1046 * @param cls the RequestHandle
1047 */
1048static void
1049delete_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1050 const char *url,
1051 void *cls)
1052{
1053 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1054 struct RequestHandle *handle = cls;
1055 struct GNUNET_RECLAIM_Attribute attr;
1056 struct EgoEntry *ego_entry;
1057 char *identity_id_str;
1058 char *identity;
1059 char *id;
1060
1061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attributes.\n");
1062 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1063 {
1064 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1065 GNUNET_SCHEDULER_add_now (&do_error, handle);
1066 return;
1067 }
1068 identity_id_str =
1069 strdup (handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1);
1070 identity = strtok (identity_id_str, "/");
1071 id = strtok (NULL, "/");
1072 if ((NULL == identity) || (NULL == id))
1073 {
1074 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
1075 GNUNET_free (identity_id_str);
1076 GNUNET_SCHEDULER_add_now (&do_error, handle);
1077 return;
1078 }
1079
1080 for (ego_entry = ego_head; NULL != ego_entry;
1081 ego_entry = ego_entry->next)
1082 if (0 == strcmp (identity, ego_entry->identifier))
1083 break;
1084 handle->resp_object = json_array ();
1085 if (NULL == ego_entry)
1086 {
1087 // Done
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1089 GNUNET_free (identity_id_str);
1090 GNUNET_SCHEDULER_add_now (&return_response, handle);
1091 return;
1092 }
1093 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1094 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Attribute));
1095 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
1096 attr.name = "";
1097 handle->idp_op = GNUNET_RECLAIM_attribute_delete (idp,
1098 priv_key,
1099 &attr,
1100 &delete_finished_cb,
1101 handle);
1102 GNUNET_free (identity_id_str);
1103}
1104
1105
1106static void
1107revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1108 const char *url,
1109 void *cls)
1110{
1111 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
1112 struct RequestHandle *handle = cls;
1113 struct EgoEntry *ego_entry;
1114 struct GNUNET_RECLAIM_Ticket *ticket = NULL;
1115 struct GNUNET_IDENTITY_PublicKey tmp_pk;
1116 char term_data[handle->rest_handle->data_size + 1];
1117 json_t *data_json;
1118 json_error_t err;
1119 struct GNUNET_JSON_Specification tktspec[] =
1120 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1121
1122 if (0 >= handle->rest_handle->data_size)
1123 {
1124 GNUNET_SCHEDULER_add_now (&do_error, handle);
1125 return;
1126 }
1127
1128 term_data[handle->rest_handle->data_size] = '\0';
1129 GNUNET_memcpy (term_data,
1130 handle->rest_handle->data,
1131 handle->rest_handle->data_size);
1132 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1133 if ((NULL == data_json) ||
1134 (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL)))
1135 {
1136 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1137 GNUNET_SCHEDULER_add_now (&do_error, handle);
1138 GNUNET_JSON_parse_free (tktspec);
1139 if (NULL != data_json)
1140 json_decref (data_json);
1141 return;
1142 }
1143 json_decref (data_json);
1144 if (NULL == ticket)
1145 {
1146 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1147 "Unable to parse ticket from %s\n",
1148 term_data);
1149 GNUNET_SCHEDULER_add_now (&do_error, handle);
1150 return;
1151 }
1152
1153 for (ego_entry = ego_head; NULL != ego_entry;
1154 ego_entry = ego_entry->next)
1155 {
1156 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1157 if (0 == memcmp (&ticket->identity,
1158 &tmp_pk,
1159 sizeof(struct GNUNET_IDENTITY_PublicKey)))
1160 break;
1161 }
1162 if (NULL == ego_entry)
1163 {
1164 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1165 GNUNET_JSON_parse_free (tktspec);
1166 return;
1167 }
1168 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1169
1170 handle->idp_op = GNUNET_RECLAIM_ticket_revoke (idp,
1171 identity_priv,
1172 ticket,
1173 &finished_cont,
1174 handle);
1175 GNUNET_JSON_parse_free (tktspec);
1176}
1177
1178
1179static void
1180consume_cont (void *cls,
1181 const struct GNUNET_IDENTITY_PublicKey *identity,
1182 const struct GNUNET_RECLAIM_Attribute *attr,
1183 const struct GNUNET_RECLAIM_Presentation *pres)
1184{
1185 struct RequestHandle *handle = cls;
1186 char *val_str;
1187 json_t *value;
1188
1189 if (NULL == identity)
1190 {
1191 GNUNET_SCHEDULER_add_now (&return_response, handle);
1192 return;
1193 }
1194
1195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
1196 val_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
1197 attr->data,
1198 attr->data_size);
1199 if (NULL == val_str)
1200 {
1201 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1202 "Failed to parse value for: %s\n",
1203 attr->name);
1204 return;
1205 }
1206 value = json_string (val_str);
1207 json_object_set_new (handle->resp_object, attr->name, value);
1208 json_decref (value);
1209 GNUNET_free (val_str);
1210}
1211
1212
1213static void
1214consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1215 const char *url,
1216 void *cls)
1217{
1218 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
1219 struct RequestHandle *handle = cls;
1220 struct EgoEntry *ego_entry;
1221 struct GNUNET_RECLAIM_Ticket *ticket;
1222 struct GNUNET_IDENTITY_PublicKey tmp_pk;
1223 char term_data[handle->rest_handle->data_size + 1];
1224 json_t *data_json;
1225 json_error_t err;
1226 struct GNUNET_JSON_Specification tktspec[] =
1227 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1228
1229 if (0 >= handle->rest_handle->data_size)
1230 {
1231 GNUNET_SCHEDULER_add_now (&do_error, handle);
1232 return;
1233 }
1234
1235 term_data[handle->rest_handle->data_size] = '\0';
1236 GNUNET_memcpy (term_data,
1237 handle->rest_handle->data,
1238 handle->rest_handle->data_size);
1239 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1240 if (NULL == data_json)
1241 {
1242 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1243 "Unable to parse JSON Object from %s\n",
1244 term_data);
1245 GNUNET_SCHEDULER_add_now (&do_error, handle);
1246 return;
1247 }
1248 if (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL))
1249 {
1250 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1251 GNUNET_SCHEDULER_add_now (&do_error, handle);
1252 GNUNET_JSON_parse_free (tktspec);
1253 json_decref (data_json);
1254 return;
1255 }
1256 for (ego_entry = ego_head; NULL != ego_entry;
1257 ego_entry = ego_entry->next)
1258 {
1259 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1260 if (0 == memcmp (&ticket->audience,
1261 &tmp_pk,
1262 sizeof(struct GNUNET_IDENTITY_PublicKey)))
1263 break;
1264 }
1265 if (NULL == ego_entry)
1266 {
1267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1268 GNUNET_JSON_parse_free (tktspec);
1269 return;
1270 }
1271 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1272 handle->resp_object = json_object ();
1273 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
1274 identity_priv,
1275 ticket,
1276 &consume_cont,
1277 handle);
1278 GNUNET_JSON_parse_free (tktspec);
1279}
1280
1281
1282/**
1283 * Respond to OPTIONS request
1284 *
1285 * @param con_handle the connection handle
1286 * @param url the url
1287 * @param cls the RequestHandle
1288 */
1289static void
1290options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1291 const char *url,
1292 void *cls)
1293{
1294 struct MHD_Response *resp;
1295 struct RequestHandle *handle = cls;
1296
1297 // For now, independent of path return all options
1298 resp = GNUNET_REST_create_response (NULL);
1299 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1300 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1301 cleanup_handle (handle);
1302 return;
1303}
1304
1305
1306/**
1307 * If listing is enabled, prints information about the egos.
1308 *
1309 * This function is initially called for all egos and then again
1310 * whenever a ego's identifier changes or if it is deleted. At the
1311 * end of the initial pass over all egos, the function is once called
1312 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
1313 * be invoked in the future or that there was an error.
1314 *
1315 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
1316 * this function is only called ONCE, and 'NULL' being passed in
1317 * 'ego' does indicate an error (i.e. name is taken or no default
1318 * value is known). If 'ego' is non-NULL and if '*ctx'
1319 * is set in those callbacks, the value WILL be passed to a subsequent
1320 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
1321 * that one was not NULL).
1322 *
1323 * When an identity is renamed, this function is called with the
1324 * (known) ego but the NEW identifier.
1325 *
1326 * When an identity is deleted, this function is called with the
1327 * (known) ego and "NULL" for the 'identifier'. In this case,
1328 * the 'ego' is henceforth invalid (and the 'ctx' should also be
1329 * cleaned up).
1330 *
1331 * @param cls closure
1332 * @param ego ego handle
1333 * @param ctx context for application to store data for this ego
1334 * (during the lifetime of this process, initially NULL)
1335 * @param identifier identifier assigned by the user for this ego,
1336 * NULL if the user just deleted the ego and it
1337 * must thus no longer be used
1338 */
1339static void
1340list_ego (void *cls,
1341 struct GNUNET_IDENTITY_Ego *ego,
1342 void **ctx,
1343 const char *identifier)
1344{
1345 struct EgoEntry *ego_entry;
1346 struct GNUNET_IDENTITY_PublicKey pk;
1347
1348 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1349 {
1350 state = ID_REST_STATE_POST_INIT;
1351 return;
1352 }
1353 if (ID_REST_STATE_INIT == state)
1354 {
1355 ego_entry = GNUNET_new (struct EgoEntry);
1356 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1357 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
1358 ego_entry->ego = ego;
1359 ego_entry->identifier = GNUNET_strdup (identifier);
1360 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1361 ego_tail,
1362 ego_entry);
1363 }
1364 /* Ego renamed or added */
1365 if (identifier != NULL)
1366 {
1367 for (ego_entry = ego_head; NULL != ego_entry;
1368 ego_entry = ego_entry->next)
1369 {
1370 if (ego_entry->ego == ego)
1371 {
1372 /* Rename */
1373 GNUNET_free (ego_entry->identifier);
1374 ego_entry->identifier = GNUNET_strdup (identifier);
1375 break;
1376 }
1377 }
1378 if (NULL == ego_entry)
1379 {
1380 /* Add */
1381 ego_entry = GNUNET_new (struct EgoEntry);
1382 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1383 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
1384 ego_entry->ego = ego;
1385 ego_entry->identifier = GNUNET_strdup (identifier);
1386 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1387 ego_tail,
1388 ego_entry);
1389 }
1390 }
1391 else
1392 {
1393 /* Delete */
1394 for (ego_entry = ego_head; NULL != ego_entry;
1395 ego_entry = ego_entry->next)
1396 {
1397 if (ego_entry->ego == ego)
1398 break;
1399 }
1400 if (NULL == ego_entry)
1401 return; /* Not found */
1402
1403 GNUNET_CONTAINER_DLL_remove (ego_head,
1404 ego_tail,
1405 ego_entry);
1406 GNUNET_free (ego_entry->identifier);
1407 GNUNET_free (ego_entry->keystring);
1408 GNUNET_free (ego_entry);
1409 return;
1410 }
1411
1412}
1413
1414
1415static enum GNUNET_GenericReturnValue
1416rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1417 GNUNET_REST_ResultProcessor proc,
1418 void *proc_cls)
1419{
1420 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1421 struct GNUNET_REST_RequestHandlerError err;
1422 static const struct GNUNET_REST_RequestHandler handlers[] =
1423 { { MHD_HTTP_METHOD_GET,
1424 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont },
1425 { MHD_HTTP_METHOD_POST,
1426 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont },
1427 { MHD_HTTP_METHOD_DELETE,
1428 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont },
1429 { MHD_HTTP_METHOD_GET,
1430 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
1431 { MHD_HTTP_METHOD_POST,
1432 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
1433 { MHD_HTTP_METHOD_DELETE,
1434 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont },
1435 { MHD_HTTP_METHOD_GET,
1436 GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont },
1437 { MHD_HTTP_METHOD_POST,
1438 GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont },
1439 { MHD_HTTP_METHOD_POST,
1440 GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont },
1441 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
1442 GNUNET_REST_HANDLER_END
1443 };
1444
1445 handle->response_code = 0;
1446 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1447 handle->proc_cls = proc_cls;
1448 handle->proc = proc;
1449 handle->rest_handle = rest_handle;
1450
1451 handle->url = GNUNET_strdup (rest_handle->url);
1452 if (handle->url[strlen (handle->url) - 1] == '/')
1453 handle->url[strlen (handle->url) - 1] = '\0';
1454 handle->timeout_task =
1455 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
1456 GNUNET_CONTAINER_DLL_insert (requests_head,
1457 requests_tail,
1458 handle);
1459 if (GNUNET_NO ==
1460 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1461 {
1462 cleanup_handle (handle);
1463 return GNUNET_NO;
1464 }
1465
1466 return GNUNET_YES;
1467}
1468
1469
1470/**
1471 * Entry point for the plugin.
1472 *
1473 * @param cls Config info
1474 * @return NULL on error, otherwise the plugin context
1475 */
1476void *
1477libgnunet_plugin_rest_reclaim_init (void *cls)
1478{
1479 static struct Plugin plugin;
1480 struct GNUNET_REST_Plugin *api;
1481
1482 cfg = cls;
1483 if (NULL != plugin.cfg)
1484 return NULL; /* can only initialize once! */
1485 memset (&plugin, 0, sizeof(struct Plugin));
1486 plugin.cfg = cfg;
1487 api = GNUNET_new (struct GNUNET_REST_Plugin);
1488 api->cls = &plugin;
1489 api->name = GNUNET_REST_API_NS_RECLAIM;
1490 api->process_request = &rest_identity_process_request;
1491 GNUNET_asprintf (&allow_methods,
1492 "%s, %s, %s, %s, %s",
1493 MHD_HTTP_METHOD_GET,
1494 MHD_HTTP_METHOD_POST,
1495 MHD_HTTP_METHOD_PUT,
1496 MHD_HTTP_METHOD_DELETE,
1497 MHD_HTTP_METHOD_OPTIONS);
1498 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1499 state = ID_REST_STATE_INIT;
1500 idp = GNUNET_RECLAIM_connect (cfg);
1501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1502 _ ("Identity Provider REST API initialized\n"));
1503 return api;
1504}
1505
1506
1507/**
1508 * Exit point from the plugin.
1509 *
1510 * @param cls the plugin context (as returned by "init")
1511 * @return always NULL
1512 */
1513void *
1514libgnunet_plugin_rest_reclaim_done (void *cls)
1515{
1516 struct GNUNET_REST_Plugin *api = cls;
1517 struct Plugin *plugin = api->cls;
1518 struct RequestHandle *request;
1519 struct EgoEntry *ego_entry;
1520 struct EgoEntry *ego_tmp;
1521
1522 plugin->cfg = NULL;
1523 while (NULL != (request = requests_head))
1524 do_error (request);
1525 if (NULL != idp)
1526 GNUNET_RECLAIM_disconnect (idp);
1527 if (NULL != identity_handle)
1528 GNUNET_IDENTITY_disconnect (identity_handle);
1529 for (ego_entry = ego_head; NULL != ego_entry;)
1530 {
1531 ego_tmp = ego_entry;
1532 ego_entry = ego_entry->next;
1533 GNUNET_free (ego_tmp->identifier);
1534 GNUNET_free (ego_tmp->keystring);
1535 GNUNET_free (ego_tmp);
1536 }
1537
1538 GNUNET_free (allow_methods);
1539 GNUNET_free (api);
1540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1541 "Identity Provider REST plugin is finished\n");
1542 return NULL;
1543}
1544
1545
1546/* end of plugin_rest_reclaim.c */
diff --git a/src/reclaim/reclaim.conf b/src/reclaim/reclaim.conf
deleted file mode 100644
index 8655f2e0b..000000000
--- a/src/reclaim/reclaim.conf
+++ /dev/null
@@ -1,19 +0,0 @@
1[reclaim]
2START_ON_DEMAND = YES
3RUN_PER_USER = YES
4#PORT = 2108
5HOSTNAME = localhost
6BINARY = gnunet-service-reclaim
7ACCEPT_FROM = 127.0.0.1;
8ACCEPT_FROM6 = ::1;
9UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-reclaim.sock
10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES
12TICKET_REFRESH_INTERVAL = 6h
13
14[reclaim-rest-plugin]
15#ADDRESS = https://identity.gnu:8000#/login
16ADDRESS = https://ui.reclaim/#/login
17OIDC_CLIENT_SECRET = secret
18JWT_SECRET = secret
19EXPIRATION_TIME = 1d
diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h
deleted file mode 100644
index aae8ee89a..000000000
--- a/src/reclaim/reclaim.h
+++ /dev/null
@@ -1,552 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @author Martin Schanzenbach
23 * @file reclaim/reclaim.h
24 *
25 * @brief Common type definitions for the identity provider
26 * service and API.
27 */
28#ifndef RECLAIM_H
29#define RECLAIM_H
30
31#include "gnunet_common.h"
32#include "gnunet_identity_service.h"
33
34GNUNET_NETWORK_STRUCT_BEGIN
35
36
37/**
38 * Use to store an identity attribute
39 */
40struct AttributeStoreMessage
41{
42 /**
43 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
44 */
45 struct GNUNET_MessageHeader header;
46
47 /**
48 * Unique identifier for this request (for key collisions).
49 */
50 uint32_t id GNUNET_PACKED;
51
52 /**
53 * The length of the attribute
54 */
55 uint32_t attr_len GNUNET_PACKED;
56
57 /**
58 * The expiration interval of the attribute
59 */
60 uint64_t exp GNUNET_PACKED;
61
62 /**
63 * Identity
64 */
65 struct GNUNET_IDENTITY_PrivateKey identity;
66
67 /* followed by the serialized attribute */
68};
69
70
71/**
72 * Use to delete an identity attribute
73 */
74struct AttributeDeleteMessage
75{
76 /**
77 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
78 */
79 struct GNUNET_MessageHeader header;
80
81 /**
82 * Unique identifier for this request (for key collisions).
83 */
84 uint32_t id GNUNET_PACKED;
85
86 /**
87 * The length of the attribute
88 */
89 uint32_t attr_len GNUNET_PACKED;
90
91 /**
92 * Identity
93 */
94 struct GNUNET_IDENTITY_PrivateKey identity;
95
96 /* followed by the serialized attribute */
97};
98
99
100/**
101 * Attribute store/delete response message
102 */
103struct SuccessResultMessage
104{
105 /**
106 * Message header
107 */
108 struct GNUNET_MessageHeader header;
109
110 /**
111 * Unique identifier for this request (for key collisions).
112 */
113 uint32_t id GNUNET_PACKED;
114
115 /**
116 * #GNUNET_SYSERR on failure, #GNUNET_OK on success
117 */
118 int32_t op_result GNUNET_PACKED;
119};
120
121/**
122 * Attribute is returned from the idp.
123 */
124struct AttributeResultMessage
125{
126 /**
127 * Message header
128 */
129 struct GNUNET_MessageHeader header;
130
131 /**
132 * Unique identifier for this request (for key collisions).
133 */
134 uint32_t id GNUNET_PACKED;
135
136 /**
137 * Length of serialized attribute data
138 */
139 uint16_t attr_len GNUNET_PACKED;
140
141 /**
142 * Length of serialized credential data
143 */
144 uint16_t credential_len GNUNET_PACKED;
145
146 /**
147 * always zero (for alignment)
148 */
149 uint16_t reserved GNUNET_PACKED;
150
151 /**
152 * The public key of the identity.
153 */
154 struct GNUNET_IDENTITY_PublicKey identity;
155
156 /* followed by:
157 * serialized attribute data
158 */
159};
160
161/**
162 * Credential is returned from the idp.
163 */
164struct CredentialResultMessage
165{
166 /**
167 * Message header
168 */
169 struct GNUNET_MessageHeader header;
170
171 /**
172 * Unique identifier for this request (for key collisions).
173 */
174 uint32_t id GNUNET_PACKED;
175
176 /**
177 * Length of serialized attribute data
178 */
179 uint16_t credential_len GNUNET_PACKED;
180
181 /**
182 * always zero (for alignment)
183 */
184 uint16_t reserved GNUNET_PACKED;
185
186 /**
187 * The public key of the identity.
188 */
189 struct GNUNET_IDENTITY_PublicKey identity;
190
191 /* followed by:
192 * serialized credential data
193 */
194};
195
196
197/**
198 * Start a attribute iteration for the given identity
199 */
200struct AttributeIterationStartMessage
201{
202 /**
203 * Message
204 */
205 struct GNUNET_MessageHeader header;
206
207 /**
208 * Unique identifier for this request (for key collisions).
209 */
210 uint32_t id GNUNET_PACKED;
211
212 /**
213 * Identity.
214 */
215 struct GNUNET_IDENTITY_PrivateKey identity;
216};
217
218
219/**
220 * Ask for next result of attribute iteration for the given operation
221 */
222struct AttributeIterationNextMessage
223{
224 /**
225 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
226 */
227 struct GNUNET_MessageHeader header;
228
229 /**
230 * Unique identifier for this request (for key collisions).
231 */
232 uint32_t id GNUNET_PACKED;
233};
234
235
236/**
237 * Start a credential iteration for the given identity
238 */
239struct CredentialIterationStartMessage
240{
241 /**
242 * Message
243 */
244 struct GNUNET_MessageHeader header;
245
246 /**
247 * Unique identifier for this request (for key collisions).
248 */
249 uint32_t id GNUNET_PACKED;
250
251 /**
252 * Identity.
253 */
254 struct GNUNET_IDENTITY_PrivateKey identity;
255};
256
257
258/**
259 * Ask for next result of credential iteration for the given operation
260 */
261struct CredentialIterationNextMessage
262{
263 /**
264 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
265 */
266 struct GNUNET_MessageHeader header;
267
268 /**
269 * Unique identifier for this request (for key collisions).
270 */
271 uint32_t id GNUNET_PACKED;
272};
273
274
275/**
276 * Stop credential iteration for the given operation
277 */
278struct CredentialIterationStopMessage
279{
280 /**
281 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP
282 */
283 struct GNUNET_MessageHeader header;
284
285 /**
286 * Unique identifier for this request (for key collisions).
287 */
288 uint32_t id GNUNET_PACKED;
289};
290
291
292/**
293 * Stop attribute iteration for the given operation
294 */
295struct AttributeIterationStopMessage
296{
297 /**
298 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP
299 */
300 struct GNUNET_MessageHeader header;
301
302 /**
303 * Unique identifier for this request (for key collisions).
304 */
305 uint32_t id GNUNET_PACKED;
306};
307
308/**
309 * Start a ticket iteration for the given identity
310 */
311struct TicketIterationStartMessage
312{
313 /**
314 * Message
315 */
316 struct GNUNET_MessageHeader header;
317
318 /**
319 * Unique identifier for this request (for key collisions).
320 */
321 uint32_t id GNUNET_PACKED;
322
323 /**
324 * Identity.
325 */
326 struct GNUNET_IDENTITY_PrivateKey identity;
327};
328
329
330/**
331 * Ask for next result of ticket iteration for the given operation
332 */
333struct TicketIterationNextMessage
334{
335 /**
336 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT
337 */
338 struct GNUNET_MessageHeader header;
339
340 /**
341 * Unique identifier for this request (for key collisions).
342 */
343 uint32_t id GNUNET_PACKED;
344};
345
346
347/**
348 * Stop ticket iteration for the given operation
349 */
350struct TicketIterationStopMessage
351{
352 /**
353 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP
354 */
355 struct GNUNET_MessageHeader header;
356
357 /**
358 * Unique identifier for this request (for key collisions).
359 */
360 uint32_t id GNUNET_PACKED;
361};
362
363
364/**
365 * Ticket issue message
366 */
367struct IssueTicketMessage
368{
369 /**
370 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET
371 */
372 struct GNUNET_MessageHeader header;
373
374 /**
375 * Unique identifier for this request (for key collisions).
376 */
377 uint32_t id GNUNET_PACKED;
378
379 /**
380 * Identity.
381 */
382 struct GNUNET_IDENTITY_PrivateKey identity;
383
384 /**
385 * Requesting party.
386 */
387 struct GNUNET_IDENTITY_PublicKey rp;
388
389 /**
390 * length of serialized attribute list
391 */
392 uint32_t attr_len GNUNET_PACKED;
393
394 // Followed by a serialized attribute list
395};
396
397/**
398 * Ticket revoke message
399 */
400struct RevokeTicketMessage
401{
402 /**
403 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET
404 */
405 struct GNUNET_MessageHeader header;
406
407 /**
408 * Unique identifier for this request (for key collisions).
409 */
410 uint32_t id GNUNET_PACKED;
411
412 /**
413 * Identity.
414 */
415 struct GNUNET_IDENTITY_PrivateKey identity;
416
417 /**
418 * length of serialized attribute list
419 */
420 uint32_t attrs_len GNUNET_PACKED;
421
422 /**
423 * The ticket to revoke
424 */
425 struct GNUNET_RECLAIM_Ticket ticket;
426};
427
428/**
429 * Ticket revoke message
430 */
431struct RevokeTicketResultMessage
432{
433 /**
434 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
435 */
436 struct GNUNET_MessageHeader header;
437
438 /**
439 * Unique identifier for this request (for key collisions).
440 */
441 uint32_t id GNUNET_PACKED;
442
443 /**
444 * Revocation result
445 */
446 uint32_t success GNUNET_PACKED;
447};
448
449
450/**
451 * Ticket result message
452 */
453struct TicketResultMessage
454{
455 /**
456 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
457 */
458 struct GNUNET_MessageHeader header;
459
460 /**
461 * Unique identifier for this request (for key collisions).
462 */
463 uint32_t id GNUNET_PACKED;
464
465 /**
466 * Length of new presentations created
467 */
468 uint32_t presentations_len GNUNET_PACKED;
469
470 /**
471 * The new ticket
472 */
473 struct GNUNET_RECLAIM_Ticket ticket;
474
475 /* Followed by the serialized GNUNET_RECLAIM_PresentationList */
476};
477
478/**
479 * Ticket consume message
480 */
481struct ConsumeTicketMessage
482{
483 /**
484 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET
485 */
486 struct GNUNET_MessageHeader header;
487
488 /**
489 * Unique identifier for this request (for key collisions).
490 */
491 uint32_t id GNUNET_PACKED;
492
493 /**
494 * Identity.
495 */
496 struct GNUNET_IDENTITY_PrivateKey identity;
497
498 /**
499 * The ticket to consume
500 */
501 struct GNUNET_RECLAIM_Ticket ticket;
502};
503
504/**
505 * Attribute list is returned from the idp.
506 */
507struct ConsumeTicketResultMessage
508{
509 /**
510 * Message header
511 */
512 struct GNUNET_MessageHeader header;
513
514 /**
515 * Unique identifier for this request (for key collisions).
516 */
517 uint32_t id GNUNET_PACKED;
518
519 /**
520 * Result
521 */
522 uint32_t result GNUNET_PACKED;
523
524 /**
525 * Length of serialized attribute data
526 */
527 uint16_t attrs_len GNUNET_PACKED;
528
529 /**
530 * Length of presentation data
531 */
532 uint16_t presentations_len;
533
534 /**
535 * always zero (for alignment)
536 */
537 uint16_t reserved GNUNET_PACKED;
538
539 /**
540 * The public key of the identity.
541 */
542 struct GNUNET_IDENTITY_PublicKey identity;
543
544 /* followed by:
545 * serialized attributes data
546 */
547};
548
549
550GNUNET_NETWORK_STRUCT_END
551
552#endif
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
deleted file mode 100644
index f4f2b946a..000000000
--- a/src/reclaim/reclaim_api.c
+++ /dev/null
@@ -1,1763 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/reclaim_api.c
23 * @brief api to interact with the reclaim service
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_mq_lib.h"
30#include "gnunet_protocols.h"
31#include "gnunet_reclaim_lib.h"
32#include "gnunet_reclaim_service.h"
33#include "reclaim.h"
34
35#define LOG(kind, ...) GNUNET_log_from (kind, "reclaim-api", __VA_ARGS__)
36
37
38/**
39 * Handle for an operation with the service.
40 */
41struct GNUNET_RECLAIM_Operation
42{
43 /**
44 * Main handle.
45 */
46 struct GNUNET_RECLAIM_Handle *h;
47
48 /**
49 * We keep operations in a DLL.
50 */
51 struct GNUNET_RECLAIM_Operation *next;
52
53 /**
54 * We keep operations in a DLL.
55 */
56 struct GNUNET_RECLAIM_Operation *prev;
57
58 /**
59 * Message to send to the service.
60 * Allocated at the end of this struct.
61 */
62 const struct GNUNET_MessageHeader *msg;
63
64 /**
65 * Continuation to invoke after attribute store call
66 */
67 GNUNET_RECLAIM_ContinuationWithStatus as_cb;
68
69 /**
70 * Attribute result callback
71 */
72 GNUNET_RECLAIM_AttributeResult ar_cb;
73
74 /**
75 * Attribute result callback
76 */
77 GNUNET_RECLAIM_AttributeTicketResult atr_cb;
78
79 /**
80 * Credential result callback
81 */
82 GNUNET_RECLAIM_CredentialResult at_cb;
83
84 /**
85 * Revocation result callback
86 */
87 GNUNET_RECLAIM_ContinuationWithStatus rvk_cb;
88
89 /**
90 * Ticket result callback
91 */
92 GNUNET_RECLAIM_TicketCallback tr_cb;
93
94 /**
95 * Ticket issue result callback
96 */
97 GNUNET_RECLAIM_IssueTicketCallback ti_cb;
98
99 /**
100 * Envelope with the message for this queue entry.
101 */
102 struct GNUNET_MQ_Envelope *env;
103
104 /**
105 * request id
106 */
107 uint32_t r_id;
108
109 /**
110 * Closure for @e cont or @e cb.
111 */
112 void *cls;
113};
114
115
116/**
117 * Handle for a ticket iterator operation
118 */
119struct GNUNET_RECLAIM_TicketIterator
120{
121 /**
122 * Kept in a DLL.
123 */
124 struct GNUNET_RECLAIM_TicketIterator *next;
125
126 /**
127 * Kept in a DLL.
128 */
129 struct GNUNET_RECLAIM_TicketIterator *prev;
130
131 /**
132 * Main handle to access the idp.
133 */
134 struct GNUNET_RECLAIM_Handle *h;
135
136 /**
137 * Function to call on completion.
138 */
139 GNUNET_SCHEDULER_TaskCallback finish_cb;
140
141 /**
142 * Closure for @e finish_cb.
143 */
144 void *finish_cb_cls;
145
146 /**
147 * The continuation to call with the results
148 */
149 GNUNET_RECLAIM_TicketCallback tr_cb;
150
151 /**
152 * Closure for @e tr_cb.
153 */
154 void *cls;
155
156 /**
157 * Function to call on errors.
158 */
159 GNUNET_SCHEDULER_TaskCallback error_cb;
160
161 /**
162 * Closure for @e error_cb.
163 */
164 void *error_cb_cls;
165
166 /**
167 * Envelope of the message to send to the service, if not yet
168 * sent.
169 */
170 struct GNUNET_MQ_Envelope *env;
171
172 /**
173 * The operation id this zone iteration operation has
174 */
175 uint32_t r_id;
176};
177
178
179/**
180 * Handle for a attribute iterator operation
181 */
182struct GNUNET_RECLAIM_AttributeIterator
183{
184 /**
185 * Kept in a DLL.
186 */
187 struct GNUNET_RECLAIM_AttributeIterator *next;
188
189 /**
190 * Kept in a DLL.
191 */
192 struct GNUNET_RECLAIM_AttributeIterator *prev;
193
194 /**
195 * Main handle to access the service.
196 */
197 struct GNUNET_RECLAIM_Handle *h;
198
199 /**
200 * Function to call on completion.
201 */
202 GNUNET_SCHEDULER_TaskCallback finish_cb;
203
204 /**
205 * Closure for @e finish_cb.
206 */
207 void *finish_cb_cls;
208
209 /**
210 * The continuation to call with the results
211 */
212 GNUNET_RECLAIM_AttributeResult proc;
213
214 /**
215 * Closure for @e proc.
216 */
217 void *proc_cls;
218
219 /**
220 * Function to call on errors.
221 */
222 GNUNET_SCHEDULER_TaskCallback error_cb;
223
224 /**
225 * Closure for @e error_cb.
226 */
227 void *error_cb_cls;
228
229 /**
230 * Envelope of the message to send to the service, if not yet
231 * sent.
232 */
233 struct GNUNET_MQ_Envelope *env;
234
235 /**
236 * Private key of the zone.
237 */
238 struct GNUNET_IDENTITY_PrivateKey identity;
239
240 /**
241 * The operation id this zone iteration operation has
242 */
243 uint32_t r_id;
244};
245
246/**
247 * Handle for a credential iterator operation
248 */
249struct GNUNET_RECLAIM_CredentialIterator
250{
251 /**
252 * Kept in a DLL.
253 */
254 struct GNUNET_RECLAIM_CredentialIterator *next;
255
256 /**
257 * Kept in a DLL.
258 */
259 struct GNUNET_RECLAIM_CredentialIterator *prev;
260
261 /**
262 * Main handle to access the service.
263 */
264 struct GNUNET_RECLAIM_Handle *h;
265
266 /**
267 * Function to call on completion.
268 */
269 GNUNET_SCHEDULER_TaskCallback finish_cb;
270
271 /**
272 * Closure for @e finish_cb.
273 */
274 void *finish_cb_cls;
275
276 /**
277 * The continuation to call with the results
278 */
279 GNUNET_RECLAIM_CredentialResult proc;
280
281 /**
282 * Closure for @e proc.
283 */
284 void *proc_cls;
285
286 /**
287 * Function to call on errors.
288 */
289 GNUNET_SCHEDULER_TaskCallback error_cb;
290
291 /**
292 * Closure for @e error_cb.
293 */
294 void *error_cb_cls;
295
296 /**
297 * Envelope of the message to send to the service, if not yet
298 * sent.
299 */
300 struct GNUNET_MQ_Envelope *env;
301
302 /**
303 * Private key of the zone.
304 */
305 struct GNUNET_IDENTITY_PrivateKey identity;
306
307 /**
308 * The operation id this zone iteration operation has
309 */
310 uint32_t r_id;
311};
312
313
314/**
315 * Handle to the service.
316 */
317struct GNUNET_RECLAIM_Handle
318{
319 /**
320 * Configuration to use.
321 */
322 const struct GNUNET_CONFIGURATION_Handle *cfg;
323
324 /**
325 * Socket (if available).
326 */
327 struct GNUNET_CLIENT_Connection *client;
328
329 /**
330 * Closure for 'cb'.
331 */
332 void *cb_cls;
333
334 /**
335 * Head of active operations.
336 */
337 struct GNUNET_RECLAIM_Operation *op_head;
338
339 /**
340 * Tail of active operations.
341 */
342 struct GNUNET_RECLAIM_Operation *op_tail;
343
344 /**
345 * Head of active iterations
346 */
347 struct GNUNET_RECLAIM_AttributeIterator *it_head;
348
349 /**
350 * Tail of active iterations
351 */
352 struct GNUNET_RECLAIM_AttributeIterator *it_tail;
353
354 /**
355 * Head of active iterations
356 */
357 struct GNUNET_RECLAIM_CredentialIterator *ait_head;
358
359 /**
360 * Tail of active iterations
361 */
362 struct GNUNET_RECLAIM_CredentialIterator *ait_tail;
363
364 /**
365 * Head of active iterations
366 */
367 struct GNUNET_RECLAIM_TicketIterator *ticket_it_head;
368
369 /**
370 * Tail of active iterations
371 */
372 struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail;
373
374 /**
375 * Currently pending transmission request, or NULL for none.
376 */
377 struct GNUNET_CLIENT_TransmitHandle *th;
378
379 /**
380 * Task doing exponential back-off trying to reconnect.
381 */
382 struct GNUNET_SCHEDULER_Task *reconnect_task;
383
384 /**
385 * Time for next connect retry.
386 */
387 struct GNUNET_TIME_Relative reconnect_backoff;
388
389 /**
390 * Connection to service (if available).
391 */
392 struct GNUNET_MQ_Handle *mq;
393
394 /**
395 * Request Id generator. Incremented by one for each request.
396 */
397 uint32_t r_id_gen;
398
399 /**
400 * Are we polling for incoming messages right now?
401 */
402 int in_receive;
403};
404
405
406/**
407 * Try again to connect to the service.
408 *
409 * @param h handle to the reclaim service.
410 */
411static void
412reconnect (struct GNUNET_RECLAIM_Handle *h);
413
414
415/**
416 * Reconnect
417 *
418 * @param cls the handle
419 */
420static void
421reconnect_task (void *cls)
422{
423 struct GNUNET_RECLAIM_Handle *handle = cls;
424
425 handle->reconnect_task = NULL;
426 reconnect (handle);
427}
428
429
430/**
431 * Disconnect from service and then reconnect.
432 *
433 * @param handle our service
434 */
435static void
436force_reconnect (struct GNUNET_RECLAIM_Handle *handle)
437{
438 GNUNET_MQ_destroy (handle->mq);
439 handle->mq = NULL;
440 handle->reconnect_backoff =
441 GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
442 handle->reconnect_task =
443 GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
444 &reconnect_task,
445 handle);
446}
447
448
449/**
450 * Free @a it.
451 *
452 * @param it entry to free
453 */
454static void
455free_it (struct GNUNET_RECLAIM_AttributeIterator *it)
456{
457 struct GNUNET_RECLAIM_Handle *h = it->h;
458
459 GNUNET_CONTAINER_DLL_remove (h->it_head, h->it_tail, it);
460 if (NULL != it->env)
461 GNUNET_MQ_discard (it->env);
462 GNUNET_free (it);
463}
464
465
466/**
467 * Free @a it.
468 *
469 * @param ait entry to free
470 */
471static void
472free_ait (struct GNUNET_RECLAIM_CredentialIterator *ait)
473{
474 struct GNUNET_RECLAIM_Handle *h = ait->h;
475
476 GNUNET_CONTAINER_DLL_remove (h->ait_head, h->ait_tail, ait);
477 if (NULL != ait->env)
478 GNUNET_MQ_discard (ait->env);
479 GNUNET_free (ait);
480}
481
482
483/**
484 * Free @a op
485 *
486 * @param op the operation to free
487 */
488static void
489free_op (struct GNUNET_RECLAIM_Operation *op)
490{
491 if (NULL == op)
492 return;
493 if (NULL != op->env)
494 GNUNET_MQ_discard (op->env);
495 GNUNET_free (op);
496}
497
498
499/**
500 * Generic error handler, called with the appropriate error code and
501 * the same closure specified at the creation of the message queue.
502 * Not every message queue implementation supports an error handler.
503 *
504 * @param cls closure with the `struct GNUNET_GNS_Handle *`
505 * @param error error code
506 */
507static void
508mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
509{
510 struct GNUNET_RECLAIM_Handle *handle = cls;
511
512 force_reconnect (handle);
513}
514
515
516/**
517 * Handle an incoming message of type
518 * #GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE
519 *
520 * @param cls
521 * @param msg the message we received
522 */
523static void
524handle_success_response (void *cls, const struct SuccessResultMessage *msg)
525{
526 struct GNUNET_RECLAIM_Handle *h = cls;
527 struct GNUNET_RECLAIM_Operation *op;
528 uint32_t r_id = ntohl (msg->id);
529 int res;
530 const char *emsg;
531
532 for (op = h->op_head; NULL != op; op = op->next)
533 if (op->r_id == r_id)
534 break;
535 if (NULL == op)
536 return;
537
538 res = ntohl (msg->op_result);
539 LOG (GNUNET_ERROR_TYPE_DEBUG,
540 "Received SUCCESS_RESPONSE with result %d\n",
541 res);
542
543 /* TODO: add actual error message to response... */
544 if (GNUNET_SYSERR == res)
545 emsg = _ ("failed to store record\n");
546 else
547 emsg = NULL;
548 if (NULL != op->as_cb)
549 op->as_cb (op->cls, res, emsg);
550 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
551 free_op (op);
552}
553
554
555/**
556 * Handle an incoming message of type
557 * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
558 *
559 * @param cls
560 * @param msg the message we received
561 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
562 */
563static int
564check_consume_ticket_result (void *cls,
565 const struct ConsumeTicketResultMessage *msg)
566{
567 size_t msg_len;
568 size_t attrs_len;
569 size_t pl_len;
570
571 msg_len = ntohs (msg->header.size);
572 attrs_len = ntohs (msg->attrs_len);
573 pl_len = ntohs (msg->presentations_len);
574 if (msg_len !=
575 sizeof(struct ConsumeTicketResultMessage) + attrs_len + pl_len)
576 {
577 GNUNET_break (0);
578 return GNUNET_SYSERR;
579 }
580 return GNUNET_OK;
581}
582
583
584/**
585 * Handle an incoming message of type
586 * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
587 *
588 * @param cls
589 * @param msg the message we received
590 */
591static void
592handle_consume_ticket_result (void *cls,
593 const struct ConsumeTicketResultMessage *msg)
594{
595 struct GNUNET_RECLAIM_Handle *h = cls;
596 struct GNUNET_RECLAIM_Operation *op;
597 size_t attrs_len;
598 size_t pl_len;
599 uint32_t r_id = ntohl (msg->id);
600 char *read_ptr;
601
602 attrs_len = ntohs (msg->attrs_len);
603 pl_len = ntohs (msg->presentations_len);
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n");
605
606
607 for (op = h->op_head; NULL != op; op = op->next)
608 if (op->r_id == r_id)
609 break;
610 if (NULL == op)
611 return;
612
613 {
614 struct GNUNET_RECLAIM_AttributeList *attrs;
615 struct GNUNET_RECLAIM_AttributeListEntry *le;
616 struct GNUNET_RECLAIM_PresentationList *pl;
617 struct GNUNET_RECLAIM_PresentationListEntry *ple;
618 attrs =
619 GNUNET_RECLAIM_attribute_list_deserialize ((char *) &msg[1], attrs_len);
620 read_ptr = ((char *) &msg[1]) + attrs_len;
621 pl = GNUNET_RECLAIM_presentation_list_deserialize (read_ptr, pl_len);
622 if (NULL != op->atr_cb)
623 {
624 if (NULL == attrs)
625 {
626 op->atr_cb (op->cls, &msg->identity, NULL, NULL);
627 }
628 else
629 {
630 for (le = attrs->list_head; NULL != le; le = le->next)
631 {
632 if (GNUNET_NO ==
633 GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
634 {
635 for (ple = pl->list_head; NULL != ple; ple = ple->next)
636 {
637 if (GNUNET_YES ==
638 GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
639 &ple->presentation->credential_id))
640 {
641 op->atr_cb (op->cls, &msg->identity,
642 le->attribute, ple->presentation);
643 break;
644 }
645
646 }
647 }
648 else // No credentials
649 {
650 op->atr_cb (op->cls, &msg->identity,
651 le->attribute, NULL);
652 }
653 }
654 if (NULL != attrs)
655 GNUNET_RECLAIM_attribute_list_destroy (attrs);
656 if (NULL != pl)
657 GNUNET_RECLAIM_presentation_list_destroy (pl);
658 attrs = NULL;
659 pl = NULL;
660 }
661 op->atr_cb (op->cls, NULL, NULL, NULL);
662 }
663 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
664 free_op (op);
665 GNUNET_free (attrs);
666 return;
667 }
668 GNUNET_assert (0);
669}
670
671
672/**
673 * Handle an incoming message of type
674 * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
675 *
676 * @param cls
677 * @param msg the message we received
678 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
679 */
680static int
681check_attribute_result (void *cls, const struct AttributeResultMessage *msg)
682{
683 size_t msg_len;
684 size_t attr_len;
685
686 msg_len = ntohs (msg->header.size);
687 attr_len = ntohs (msg->attr_len);
688 if (msg_len != sizeof(struct AttributeResultMessage) + attr_len)
689 {
690 GNUNET_break (0);
691 return GNUNET_SYSERR;
692 }
693 return GNUNET_OK;
694}
695
696
697/**
698 * Handle an incoming message of type
699 * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
700 *
701 * @param cls
702 * @param msg the message we received
703 */
704static void
705handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
706{
707 static struct GNUNET_IDENTITY_PrivateKey identity_dummy;
708 struct GNUNET_RECLAIM_Handle *h = cls;
709 struct GNUNET_RECLAIM_AttributeIterator *it;
710 struct GNUNET_RECLAIM_Operation *op;
711 size_t attr_len;
712 uint32_t r_id = ntohl (msg->id);
713
714 attr_len = ntohs (msg->attr_len);
715 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attribute result.\n");
716
717
718 for (it = h->it_head; NULL != it; it = it->next)
719 if (it->r_id == r_id)
720 break;
721 for (op = h->op_head; NULL != op; op = op->next)
722 if (op->r_id == r_id)
723 break;
724 if ((NULL == it) && (NULL == op))
725 return;
726
727 if ((0 ==
728 (memcmp (&msg->identity, &identity_dummy, sizeof(identity_dummy)))))
729 {
730 if ((NULL == it) && (NULL == op))
731 {
732 GNUNET_break (0);
733 force_reconnect (h);
734 return;
735 }
736 if (NULL != it)
737 {
738 if (NULL != it->finish_cb)
739 it->finish_cb (it->finish_cb_cls);
740 free_it (it);
741 }
742 if (NULL != op)
743 {
744 if (NULL != op->ar_cb)
745 op->ar_cb (op->cls, NULL, NULL);
746 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
747 free_op (op);
748 }
749 return;
750 }
751
752 {
753 struct GNUNET_RECLAIM_Attribute *attr;
754 GNUNET_RECLAIM_attribute_deserialize ((char *) &msg[1], attr_len,
755 &attr);
756 if (NULL != it)
757 {
758 if (NULL != it->proc)
759 it->proc (it->proc_cls, &msg->identity, attr);
760 }
761 else if (NULL != op)
762 {
763 if (NULL != op->ar_cb)
764 op->ar_cb (op->cls, &msg->identity, attr);
765 }
766 GNUNET_free (attr);
767 return;
768 }
769 GNUNET_assert (0);
770}
771
772
773/**
774 * Handle an incoming message of type
775 * #GNUNET_MESSAGE_TYPE_RECLAIM_credential_RESULT
776 *
777 * @param cls
778 * @param msg the message we received
779 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
780 */
781static int
782check_credential_result (void *cls, const struct CredentialResultMessage *msg)
783{
784 size_t msg_len;
785 size_t cred_len;
786
787 msg_len = ntohs (msg->header.size);
788 cred_len = ntohs (msg->credential_len);
789 if (msg_len != sizeof(struct CredentialResultMessage) + cred_len)
790 {
791 GNUNET_break (0);
792 return GNUNET_SYSERR;
793 }
794 return GNUNET_OK;
795}
796
797
798/**
799 * Handle an incoming message of type
800 * #GNUNET_MESSAGE_TYPE_RECLAIM_credential_RESULT
801 *
802 * @param cls
803 * @param msg the message we received
804 */
805static void
806handle_credential_result (void *cls, const struct
807 CredentialResultMessage *msg)
808{
809 static struct GNUNET_IDENTITY_PrivateKey identity_dummy;
810 struct GNUNET_RECLAIM_Handle *h = cls;
811 struct GNUNET_RECLAIM_CredentialIterator *it;
812 struct GNUNET_RECLAIM_Operation *op;
813 size_t att_len;
814 uint32_t r_id = ntohl (msg->id);
815
816 att_len = ntohs (msg->credential_len);
817 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing credential result.\n");
818
819
820 for (it = h->ait_head; NULL != it; it = it->next)
821 if (it->r_id == r_id)
822 break;
823 for (op = h->op_head; NULL != op; op = op->next)
824 if (op->r_id == r_id)
825 break;
826 if ((NULL == it) && (NULL == op))
827 return;
828
829 if ((0 ==
830 (memcmp (&msg->identity, &identity_dummy, sizeof(identity_dummy)))))
831 {
832 if ((NULL == it) && (NULL == op))
833 {
834 GNUNET_break (0);
835 force_reconnect (h);
836 return;
837 }
838 if (NULL != it)
839 {
840 if (NULL != it->finish_cb)
841 it->finish_cb (it->finish_cb_cls);
842 free_ait (it);
843 }
844 if (NULL != op)
845 {
846 if (NULL != op->at_cb)
847 op->at_cb (op->cls, NULL, NULL);
848 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
849 free_op (op);
850 }
851 return;
852 }
853
854 {
855 struct GNUNET_RECLAIM_Credential *att;
856 att = GNUNET_RECLAIM_credential_deserialize ((char *) &msg[1], att_len);
857
858 if (NULL != it)
859 {
860 if (NULL != it->proc)
861 it->proc (it->proc_cls, &msg->identity, att);
862 }
863 else if (NULL != op)
864 {
865 if (NULL != op->at_cb)
866 op->at_cb (op->cls, &msg->identity, att);
867 }
868 GNUNET_free (att);
869 return;
870 }
871 GNUNET_assert (0);
872}
873
874/**
875 * Handle an incoming message of type
876 * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
877 *
878 * @param cls
879 * @param msg the message we received
880 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
881 */
882static int
883check_ticket_result (void *cls, const struct TicketResultMessage *msg)
884{
885 size_t msg_len;
886 size_t pres_len;
887
888 msg_len = ntohs (msg->header.size);
889 pres_len = ntohs (msg->presentations_len);
890 if (msg_len != sizeof(struct TicketResultMessage) + pres_len)
891 {
892 GNUNET_break (0);
893 return GNUNET_SYSERR;
894 }
895 return GNUNET_OK;
896}
897
898
899/**
900 * Handle an incoming message of type
901 * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
902 *
903 * @param cls
904 * @param msg the message we received
905 */
906static void
907handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
908{
909 struct GNUNET_RECLAIM_Handle *handle = cls;
910 struct GNUNET_RECLAIM_Operation *op;
911 struct GNUNET_RECLAIM_TicketIterator *it;
912 struct GNUNET_RECLAIM_PresentationList *pres;
913 uint32_t r_id = ntohl (msg->id);
914 static const struct GNUNET_RECLAIM_Ticket ticket;
915 uint32_t pres_len = ntohs (msg->presentations_len);
916
917 for (op = handle->op_head; NULL != op; op = op->next)
918 if (op->r_id == r_id)
919 break;
920 for (it = handle->ticket_it_head; NULL != it; it = it->next)
921 if (it->r_id == r_id)
922 break;
923 if ((NULL == op) && (NULL == it))
924 return;
925 if (NULL != op)
926 {
927 if (0 < pres_len)
928 pres = GNUNET_RECLAIM_presentation_list_deserialize ((char*)&msg[1],
929 pres_len);
930 GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
931 if (0 ==
932 memcmp (&msg->ticket, &ticket, sizeof(struct GNUNET_RECLAIM_Ticket)))
933 {
934 if (NULL != op->ti_cb)
935 op->ti_cb (op->cls, NULL, NULL);
936 }
937 else
938 {
939 if (NULL != op->ti_cb)
940 op->ti_cb (op->cls,
941 &msg->ticket,
942 (0 < pres_len) ? pres : NULL);
943 }
944 if (0 < pres_len)
945 GNUNET_RECLAIM_presentation_list_destroy (pres);
946 free_op (op);
947 return;
948 }
949 else if (NULL != it)
950 {
951 if (0 ==
952 memcmp (&msg->ticket, &ticket, sizeof(struct GNUNET_RECLAIM_Ticket)))
953 {
954 GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
955 handle->ticket_it_tail,
956 it);
957 it->finish_cb (it->finish_cb_cls);
958 GNUNET_free (it);
959 }
960 else
961 {
962 if (NULL != it->tr_cb)
963 it->tr_cb (it->cls, &msg->ticket);
964 }
965 return;
966 }
967 GNUNET_break (0);
968}
969
970
971/**
972 * Handle an incoming message of type
973 * #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
974 *
975 * @param cls
976 * @param msg the message we received
977 */
978static void
979handle_revoke_ticket_result (void *cls,
980 const struct RevokeTicketResultMessage *msg)
981{
982 struct GNUNET_RECLAIM_Handle *h = cls;
983 struct GNUNET_RECLAIM_Operation *op;
984 uint32_t r_id = ntohl (msg->id);
985 int32_t success;
986
987 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing revocation result.\n");
988
989
990 for (op = h->op_head; NULL != op; op = op->next)
991 if (op->r_id == r_id)
992 break;
993 if (NULL == op)
994 return;
995 success = ntohl (msg->success);
996 {
997 if (NULL != op->rvk_cb)
998 {
999 op->rvk_cb (op->cls, success, NULL);
1000 }
1001 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
1002 free_op (op);
1003 return;
1004 }
1005 GNUNET_assert (0);
1006}
1007
1008
1009/**
1010 * Try again to connect to the service.
1011 *
1012 * @param h handle to the reclaim service.
1013 */
1014static void
1015reconnect (struct GNUNET_RECLAIM_Handle *h)
1016{
1017 struct GNUNET_MQ_MessageHandler handlers[] =
1018 { GNUNET_MQ_hd_fixed_size (success_response,
1019 GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE,
1020 struct SuccessResultMessage,
1021 h),
1022 GNUNET_MQ_hd_var_size (attribute_result,
1023 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
1024 struct AttributeResultMessage,
1025 h),
1026 GNUNET_MQ_hd_var_size (credential_result,
1027 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT,
1028 struct CredentialResultMessage,
1029 h),
1030 GNUNET_MQ_hd_var_size (ticket_result,
1031 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
1032 struct TicketResultMessage,
1033 h),
1034 GNUNET_MQ_hd_var_size (consume_ticket_result,
1035 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
1036 struct ConsumeTicketResultMessage,
1037 h),
1038 GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
1039 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT,
1040 struct RevokeTicketResultMessage,
1041 h),
1042 GNUNET_MQ_handler_end () };
1043 struct GNUNET_RECLAIM_Operation *op;
1044
1045 GNUNET_assert (NULL == h->mq);
1046 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to reclaim service.\n");
1047
1048 h->mq =
1049 GNUNET_CLIENT_connect (h->cfg, "reclaim", handlers, &mq_error_handler, h);
1050 if (NULL == h->mq)
1051 return;
1052 for (op = h->op_head; NULL != op; op = op->next)
1053 GNUNET_MQ_send_copy (h->mq, op->env);
1054}
1055
1056
1057/**
1058 * Connect to the reclaim service.
1059 *
1060 * @param cfg the configuration to use
1061 * @return handle to use
1062 */
1063struct GNUNET_RECLAIM_Handle *
1064GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
1065{
1066 struct GNUNET_RECLAIM_Handle *h;
1067
1068 h = GNUNET_new (struct GNUNET_RECLAIM_Handle);
1069 h->cfg = cfg;
1070 reconnect (h);
1071 if (NULL == h->mq)
1072 {
1073 GNUNET_free (h);
1074 return NULL;
1075 }
1076 return h;
1077}
1078
1079
1080/**
1081 * Cancel an operation. Note that the operation MAY still
1082 * be executed; this merely cancels the continuation; if the request
1083 * was already transmitted, the service may still choose to complete
1084 * the operation.
1085 *
1086 * @param op operation to cancel
1087 */
1088void
1089GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op)
1090{
1091 struct GNUNET_RECLAIM_Handle *h = op->h;
1092
1093 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
1094 free_op (op);
1095}
1096
1097
1098/**
1099 * Disconnect from service
1100 *
1101 * @param h handle to destroy
1102 */
1103void
1104GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h)
1105{
1106 GNUNET_assert (NULL != h);
1107 if (NULL != h->mq)
1108 {
1109 GNUNET_MQ_destroy (h->mq);
1110 h->mq = NULL;
1111 }
1112 if (NULL != h->reconnect_task)
1113 {
1114 GNUNET_SCHEDULER_cancel (h->reconnect_task);
1115 h->reconnect_task = NULL;
1116 }
1117 GNUNET_assert (NULL == h->op_head);
1118 GNUNET_free (h);
1119}
1120
1121
1122/**
1123 * Store an attribute. If the attribute is already present,
1124 * it is replaced with the new attribute.
1125 *
1126 * @param h handle to the re:claimID service
1127 * @param pkey private key of the identity
1128 * @param attr the attribute value
1129 * @param exp_interval the relative expiration interval for the attribute
1130 * @param cont continuation to call when done
1131 * @param cont_cls closure for @a cont
1132 * @return handle to abort the request
1133 */
1134struct GNUNET_RECLAIM_Operation *
1135GNUNET_RECLAIM_attribute_store (
1136 struct GNUNET_RECLAIM_Handle *h,
1137 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1138 const struct GNUNET_RECLAIM_Attribute *attr,
1139 const struct GNUNET_TIME_Relative *exp_interval,
1140 GNUNET_RECLAIM_ContinuationWithStatus cont,
1141 void *cont_cls)
1142{
1143 struct GNUNET_RECLAIM_Operation *op;
1144 struct AttributeStoreMessage *sam;
1145 size_t attr_len;
1146
1147 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1148 op->h = h;
1149 op->as_cb = cont;
1150 op->cls = cont_cls;
1151 op->r_id = h->r_id_gen++;
1152 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1153 attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (attr);
1154 op->env = GNUNET_MQ_msg_extra (sam,
1155 attr_len,
1156 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE);
1157 sam->identity = *pkey;
1158 sam->id = htonl (op->r_id);
1159 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1160
1161 GNUNET_RECLAIM_attribute_serialize (attr, (char *) &sam[1]);
1162
1163 sam->attr_len = htons (attr_len);
1164 if (NULL != h->mq)
1165 GNUNET_MQ_send_copy (h->mq, op->env);
1166 return op;
1167}
1168
1169
1170/**
1171 * Delete an attribute. Tickets used to share this attribute are updated
1172 * accordingly.
1173 *
1174 * @param h handle to the re:claimID service
1175 * @param pkey Private key of the identity to add an attribute to
1176 * @param attr The attribute
1177 * @param cont Continuation to call when done
1178 * @param cont_cls Closure for @a cont
1179 * @return handle Used to to abort the request
1180 */
1181struct GNUNET_RECLAIM_Operation *
1182GNUNET_RECLAIM_attribute_delete (
1183 struct GNUNET_RECLAIM_Handle *h,
1184 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1185 const struct GNUNET_RECLAIM_Attribute *attr,
1186 GNUNET_RECLAIM_ContinuationWithStatus cont,
1187 void *cont_cls)
1188{
1189 struct GNUNET_RECLAIM_Operation *op;
1190 struct AttributeDeleteMessage *dam;
1191 size_t attr_len;
1192
1193 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1194 op->h = h;
1195 op->as_cb = cont;
1196 op->cls = cont_cls;
1197 op->r_id = h->r_id_gen++;
1198 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1199 attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (attr);
1200 op->env = GNUNET_MQ_msg_extra (dam,
1201 attr_len,
1202 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE);
1203 dam->identity = *pkey;
1204 dam->id = htonl (op->r_id);
1205 GNUNET_RECLAIM_attribute_serialize (attr, (char *) &dam[1]);
1206
1207 dam->attr_len = htons (attr_len);
1208 if (NULL != h->mq)
1209 GNUNET_MQ_send_copy (h->mq, op->env);
1210 return op;
1211}
1212
1213
1214/**
1215 * Store an credential. If the credential is already present,
1216 * it is replaced with the new credential.
1217 *
1218 * @param h handle to the re:claimID service
1219 * @param pkey private key of the identity
1220 * @param attr the credential value
1221 * @param exp_interval the relative expiration interval for the credential
1222 * @param cont continuation to call when done
1223 * @param cont_cls closure for @a cont
1224 * @return handle to abort the request
1225 */
1226struct GNUNET_RECLAIM_Operation *
1227GNUNET_RECLAIM_credential_store (
1228 struct GNUNET_RECLAIM_Handle *h,
1229 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1230 const struct GNUNET_RECLAIM_Credential *attr,
1231 const struct GNUNET_TIME_Relative *exp_interval,
1232 GNUNET_RECLAIM_ContinuationWithStatus cont,
1233 void *cont_cls)
1234{
1235 struct GNUNET_RECLAIM_Operation *op;
1236 struct AttributeStoreMessage *sam;
1237 size_t attr_len;
1238
1239 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1240 op->h = h;
1241 op->as_cb = cont;
1242 op->cls = cont_cls;
1243 op->r_id = h->r_id_gen++;
1244 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1245 attr_len = GNUNET_RECLAIM_credential_serialize_get_size (attr);
1246 op->env = GNUNET_MQ_msg_extra (sam,
1247 attr_len,
1248 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE);
1249 sam->identity = *pkey;
1250 sam->id = htonl (op->r_id);
1251 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1252
1253 GNUNET_RECLAIM_credential_serialize (attr, (char *) &sam[1]);
1254
1255 sam->attr_len = htons (attr_len);
1256 if (NULL != h->mq)
1257 GNUNET_MQ_send_copy (h->mq, op->env);
1258 return op;
1259}
1260
1261
1262/**
1263 * Delete an credential. Tickets used to share this credential are updated
1264 * accordingly.
1265 *
1266 * @param h handle to the re:claimID service
1267 * @param pkey Private key of the identity to add an attribute to
1268 * @param attr The credential
1269 * @param cont Continuation to call when done
1270 * @param cont_cls Closure for @a cont
1271 * @return handle Used to to abort the request
1272 */
1273struct GNUNET_RECLAIM_Operation *
1274GNUNET_RECLAIM_credential_delete (
1275 struct GNUNET_RECLAIM_Handle *h,
1276 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1277 const struct GNUNET_RECLAIM_Credential *attr,
1278 GNUNET_RECLAIM_ContinuationWithStatus cont,
1279 void *cont_cls)
1280{
1281 struct GNUNET_RECLAIM_Operation *op;
1282 struct AttributeDeleteMessage *dam;
1283 size_t attr_len;
1284
1285 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1286 op->h = h;
1287 op->as_cb = cont;
1288 op->cls = cont_cls;
1289 op->r_id = h->r_id_gen++;
1290 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1291 attr_len = GNUNET_RECLAIM_credential_serialize_get_size (attr);
1292 op->env = GNUNET_MQ_msg_extra (dam,
1293 attr_len,
1294 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE);
1295 dam->identity = *pkey;
1296 dam->id = htonl (op->r_id);
1297 GNUNET_RECLAIM_credential_serialize (attr, (char *) &dam[1]);
1298
1299 dam->attr_len = htons (attr_len);
1300 if (NULL != h->mq)
1301 GNUNET_MQ_send_copy (h->mq, op->env);
1302 return op;
1303}
1304
1305
1306/**
1307 * List all attributes for a local identity.
1308 * This MUST lock the `struct GNUNET_RECLAIM_Handle`
1309 * for any other calls than #GNUNET_RECLAIM_get_attributes_next() and
1310 * #GNUNET_RECLAIM_get_attributes_stop. @a proc will be called once
1311 * immediately, and then again after
1312 * #GNUNET_RECLAIM_get_attributes_next() is invoked.
1313 *
1314 * On error (disconnect), @a error_cb will be invoked.
1315 * On normal completion, @a finish_cb proc will be
1316 * invoked.
1317 *
1318 * @param h Handle to the re:claimID service
1319 * @param identity Identity to iterate over
1320 * @param error_cb Function to call on error (i.e. disconnect),
1321 * the handle is afterwards invalid
1322 * @param error_cb_cls Closure for @a error_cb
1323 * @param proc Function to call on each attribute
1324 * @param proc_cls Closure for @a proc
1325 * @param finish_cb Function to call on completion
1326 * the handle is afterwards invalid
1327 * @param finish_cb_cls Closure for @a finish_cb
1328 * @return an iterator Handle to use for iteration
1329 */
1330struct GNUNET_RECLAIM_AttributeIterator *
1331GNUNET_RECLAIM_get_attributes_start (
1332 struct GNUNET_RECLAIM_Handle *h,
1333 const struct GNUNET_IDENTITY_PrivateKey *identity,
1334 GNUNET_SCHEDULER_TaskCallback error_cb,
1335 void *error_cb_cls,
1336 GNUNET_RECLAIM_AttributeResult proc,
1337 void *proc_cls,
1338 GNUNET_SCHEDULER_TaskCallback finish_cb,
1339 void *finish_cb_cls)
1340{
1341 struct GNUNET_RECLAIM_AttributeIterator *it;
1342 struct GNUNET_MQ_Envelope *env;
1343 struct AttributeIterationStartMessage *msg;
1344 uint32_t rid;
1345
1346 rid = h->r_id_gen++;
1347 it = GNUNET_new (struct GNUNET_RECLAIM_AttributeIterator);
1348 it->h = h;
1349 it->error_cb = error_cb;
1350 it->error_cb_cls = error_cb_cls;
1351 it->finish_cb = finish_cb;
1352 it->finish_cb_cls = finish_cb_cls;
1353 it->proc = proc;
1354 it->proc_cls = proc_cls;
1355 it->r_id = rid;
1356 it->identity = *identity;
1357 GNUNET_CONTAINER_DLL_insert_tail (h->it_head, h->it_tail, it);
1358 env =
1359 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START);
1360 msg->id = htonl (rid);
1361 msg->identity = *identity;
1362 if (NULL == h->mq)
1363 it->env = env;
1364 else
1365 GNUNET_MQ_send (h->mq, env);
1366 return it;
1367}
1368
1369
1370/**
1371 * Calls the record processor specified in #GNUNET_RECLAIM_get_attributes_start
1372 * for the next record.
1373 *
1374 * @param it the iterator
1375 */
1376void
1377GNUNET_RECLAIM_get_attributes_next (struct GNUNET_RECLAIM_AttributeIterator *it)
1378{
1379 struct GNUNET_RECLAIM_Handle *h = it->h;
1380 struct AttributeIterationNextMessage *msg;
1381 struct GNUNET_MQ_Envelope *env;
1382
1383 env =
1384 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT);
1385 msg->id = htonl (it->r_id);
1386 GNUNET_MQ_send (h->mq, env);
1387}
1388
1389
1390/**
1391 * Stops iteration and releases the handle for further calls. Must
1392 * be called on any iteration that has not yet completed prior to calling
1393 * #GNUNET_RECLAIM_disconnect.
1394 *
1395 * @param it the iterator
1396 */
1397void
1398GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
1399{
1400 struct GNUNET_RECLAIM_Handle *h = it->h;
1401 struct GNUNET_MQ_Envelope *env;
1402 struct AttributeIterationStopMessage *msg;
1403
1404 if (NULL != h->mq)
1405 {
1406 env =
1407 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP);
1408 msg->id = htonl (it->r_id);
1409 GNUNET_MQ_send (h->mq, env);
1410 }
1411 free_it (it);
1412}
1413
1414
1415/**
1416 * List all credentials for a local identity.
1417 * This MUST lock the `struct GNUNET_RECLAIM_Handle`
1418 * for any other calls than #GNUNET_RECLAIM_get_credentials_next() and
1419 * #GNUNET_RECLAIM_get_credentials_stop. @a proc will be called once
1420 * immediately, and then again after
1421 * #GNUNET_RECLAIM_get_credentials_next() is invoked.
1422 *
1423 * On error (disconnect), @a error_cb will be invoked.
1424 * On normal completion, @a finish_cb proc will be
1425 * invoked.
1426 *
1427 * @param h Handle to the re:claimID service
1428 * @param identity Identity to iterate over
1429 * @param error_cb Function to call on error (i.e. disconnect),
1430 * the handle is afterwards invalid
1431 * @param error_cb_cls Closure for @a error_cb
1432 * @param proc Function to call on each credential
1433 * @param proc_cls Closure for @a proc
1434 * @param finish_cb Function to call on completion
1435 * the handle is afterwards invalid
1436 * @param finish_cb_cls Closure for @a finish_cb
1437 * @return an iterator Handle to use for iteration
1438 */
1439struct GNUNET_RECLAIM_CredentialIterator *
1440GNUNET_RECLAIM_get_credentials_start (
1441 struct GNUNET_RECLAIM_Handle *h,
1442 const struct GNUNET_IDENTITY_PrivateKey *identity,
1443 GNUNET_SCHEDULER_TaskCallback error_cb,
1444 void *error_cb_cls,
1445 GNUNET_RECLAIM_CredentialResult proc,
1446 void *proc_cls,
1447 GNUNET_SCHEDULER_TaskCallback finish_cb,
1448 void *finish_cb_cls)
1449{
1450 struct GNUNET_RECLAIM_CredentialIterator *ait;
1451 struct GNUNET_MQ_Envelope *env;
1452 struct CredentialIterationStartMessage *msg;
1453 uint32_t rid;
1454
1455 rid = h->r_id_gen++;
1456 ait = GNUNET_new (struct GNUNET_RECLAIM_CredentialIterator);
1457 ait->h = h;
1458 ait->error_cb = error_cb;
1459 ait->error_cb_cls = error_cb_cls;
1460 ait->finish_cb = finish_cb;
1461 ait->finish_cb_cls = finish_cb_cls;
1462 ait->proc = proc;
1463 ait->proc_cls = proc_cls;
1464 ait->r_id = rid;
1465 ait->identity = *identity;
1466 GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait);
1467 env =
1468 GNUNET_MQ_msg (msg,
1469 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START);
1470 msg->id = htonl (rid);
1471 msg->identity = *identity;
1472 if (NULL == h->mq)
1473 ait->env = env;
1474 else
1475 GNUNET_MQ_send (h->mq, env);
1476 return ait;
1477}
1478
1479
1480/**
1481 * Calls the record processor specified in #GNUNET_RECLAIM_get_credential_start
1482 * for the next record.
1483 *
1484 * @param it the iterator
1485 */
1486void
1487GNUNET_RECLAIM_get_credentials_next (struct
1488 GNUNET_RECLAIM_CredentialIterator *ait)
1489{
1490 struct GNUNET_RECLAIM_Handle *h = ait->h;
1491 struct CredentialIterationNextMessage *msg;
1492 struct GNUNET_MQ_Envelope *env;
1493
1494 env =
1495 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT);
1496 msg->id = htonl (ait->r_id);
1497 GNUNET_MQ_send (h->mq, env);
1498}
1499
1500
1501/**
1502 * Stops iteration and releases the handle for further calls. Must
1503 * be called on any iteration that has not yet completed prior to calling
1504 * #GNUNET_RECLAIM_disconnect.
1505 *
1506 * @param it the iterator
1507 */
1508void
1509GNUNET_RECLAIM_get_credentials_stop (struct
1510 GNUNET_RECLAIM_CredentialIterator *ait)
1511{
1512 struct GNUNET_RECLAIM_Handle *h = ait->h;
1513 struct GNUNET_MQ_Envelope *env;
1514 struct CredentialIterationStopMessage *msg;
1515
1516 if (NULL != h->mq)
1517 {
1518 env =
1519 GNUNET_MQ_msg (msg,
1520 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP);
1521 msg->id = htonl (ait->r_id);
1522 GNUNET_MQ_send (h->mq, env);
1523 }
1524 free_ait (ait);
1525}
1526
1527
1528/**
1529 * Issues a ticket to another relying party. The identity may use
1530 * @GNUNET_RECLAIM_ticket_consume to consume the ticket
1531 * and retrieve the attributes specified in the attribute list.
1532 *
1533 * @param h the reclaim to use
1534 * @param iss the issuing identity (= the user)
1535 * @param rp the subject of the ticket (= the relying party)
1536 * @param attrs the attributes that the relying party is given access to
1537 * @param cb the callback
1538 * @param cb_cls the callback closure
1539 * @return handle to abort the operation
1540 */
1541struct GNUNET_RECLAIM_Operation *
1542GNUNET_RECLAIM_ticket_issue (
1543 struct GNUNET_RECLAIM_Handle *h,
1544 const struct GNUNET_IDENTITY_PrivateKey *iss,
1545 const struct GNUNET_IDENTITY_PublicKey *rp,
1546 const struct GNUNET_RECLAIM_AttributeList *attrs,
1547 GNUNET_RECLAIM_IssueTicketCallback cb,
1548 void *cb_cls)
1549{
1550 struct GNUNET_RECLAIM_Operation *op;
1551 struct IssueTicketMessage *tim;
1552 size_t attr_len;
1553
1554 fprintf (stderr, "Issuing ticket\n");
1555 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1556 op->h = h;
1557 op->ti_cb = cb;
1558 op->cls = cb_cls;
1559 op->r_id = h->r_id_gen++;
1560 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1561 attr_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
1562 op->env = GNUNET_MQ_msg_extra (tim,
1563 attr_len,
1564 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET);
1565 tim->identity = *iss;
1566 tim->rp = *rp;
1567 tim->id = htonl (op->r_id);
1568
1569 GNUNET_RECLAIM_attribute_list_serialize (attrs, (char *) &tim[1]);
1570
1571 tim->attr_len = htons (attr_len);
1572 if (NULL != h->mq)
1573 GNUNET_MQ_send_copy (h->mq, op->env);
1574 return op;
1575}
1576
1577
1578/**
1579 * Consumes an issued ticket. The ticket is persisted
1580 * and used to retrieve identity information from the issuer
1581 *
1582 * @param h the reclaim to use
1583 * @param identity the identity that is the subject of the issued ticket (the
1584 * relying party)
1585 * @param ticket the issued ticket to consume
1586 * @param cb the callback to call
1587 * @param cb_cls the callback closure
1588 * @return handle to abort the operation
1589 */
1590struct GNUNET_RECLAIM_Operation *
1591GNUNET_RECLAIM_ticket_consume (
1592 struct GNUNET_RECLAIM_Handle *h,
1593 const struct GNUNET_IDENTITY_PrivateKey *identity,
1594 const struct GNUNET_RECLAIM_Ticket *ticket,
1595 GNUNET_RECLAIM_AttributeTicketResult cb,
1596 void *cb_cls)
1597{
1598 struct GNUNET_RECLAIM_Operation *op;
1599 struct ConsumeTicketMessage *ctm;
1600
1601 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1602 op->h = h;
1603 op->atr_cb = cb;
1604 op->cls = cb_cls;
1605 op->r_id = h->r_id_gen++;
1606 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1607 op->env = GNUNET_MQ_msg (ctm, GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET);
1608 ctm->identity = *identity;
1609 ctm->id = htonl (op->r_id);
1610 ctm->ticket = *ticket;
1611 if (NULL != h->mq)
1612 GNUNET_MQ_send_copy (h->mq, op->env);
1613 else
1614 reconnect (h);
1615 return op;
1616}
1617
1618
1619/**
1620 * Lists all tickets that have been issued to remote
1621 * identites (relying parties)
1622 *
1623 * @param h the reclaim to use
1624 * @param identity the issuing identity
1625 * @param error_cb function to call on error (i.e. disconnect),
1626 * the handle is afterwards invalid
1627 * @param error_cb_cls closure for @a error_cb
1628 * @param proc function to call on each ticket; it
1629 * will be called repeatedly with a value (if available)
1630 * @param proc_cls closure for @a proc
1631 * @param finish_cb function to call on completion
1632 * the handle is afterwards invalid
1633 * @param finish_cb_cls closure for @a finish_cb
1634 * @return an iterator handle to use for iteration
1635 */
1636struct GNUNET_RECLAIM_TicketIterator *
1637GNUNET_RECLAIM_ticket_iteration_start (
1638 struct GNUNET_RECLAIM_Handle *h,
1639 const struct GNUNET_IDENTITY_PrivateKey *identity,
1640 GNUNET_SCHEDULER_TaskCallback error_cb,
1641 void *error_cb_cls,
1642 GNUNET_RECLAIM_TicketCallback proc,
1643 void *proc_cls,
1644 GNUNET_SCHEDULER_TaskCallback finish_cb,
1645 void *finish_cb_cls)
1646{
1647 struct GNUNET_RECLAIM_TicketIterator *it;
1648 struct GNUNET_MQ_Envelope *env;
1649 struct TicketIterationStartMessage *msg;
1650 uint32_t rid;
1651
1652 rid = h->r_id_gen++;
1653 it = GNUNET_new (struct GNUNET_RECLAIM_TicketIterator);
1654 it->h = h;
1655 it->error_cb = error_cb;
1656 it->error_cb_cls = error_cb_cls;
1657 it->finish_cb = finish_cb;
1658 it->finish_cb_cls = finish_cb_cls;
1659 it->tr_cb = proc;
1660 it->cls = proc_cls;
1661 it->r_id = rid;
1662 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, h->ticket_it_tail, it);
1663 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START);
1664 msg->id = htonl (rid);
1665 msg->identity = *identity;
1666 if (NULL == h->mq)
1667 it->env = env;
1668 else
1669 GNUNET_MQ_send (h->mq, env);
1670 return it;
1671}
1672
1673
1674/**
1675 * Calls the ticket processor specified in
1676 * #GNUNET_RECLAIM_ticket_iteration_start for the next record.
1677 *
1678 * @param it the iterator
1679 */
1680void
1681GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it)
1682{
1683 struct GNUNET_RECLAIM_Handle *h = it->h;
1684 struct TicketIterationNextMessage *msg;
1685 struct GNUNET_MQ_Envelope *env;
1686
1687 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT);
1688 msg->id = htonl (it->r_id);
1689 GNUNET_MQ_send (h->mq, env);
1690}
1691
1692
1693/**
1694 * Stops iteration and releases the handle for further calls. Must
1695 * be called on any iteration that has not yet completed prior to calling
1696 * #GNUNET_RECLAIM_disconnect.
1697 *
1698 * @param it the iterator
1699 */
1700void
1701GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it)
1702{
1703 struct GNUNET_RECLAIM_Handle *h = it->h;
1704 struct GNUNET_MQ_Envelope *env;
1705 struct TicketIterationStopMessage *msg;
1706
1707 if (NULL != h->mq)
1708 {
1709 env =
1710 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP);
1711 msg->id = htonl (it->r_id);
1712 GNUNET_MQ_send (h->mq, env);
1713 }
1714 GNUNET_free (it);
1715}
1716
1717
1718/**
1719 * Revoked an issued ticket. The relying party will be unable to retrieve
1720 * attributes. Other issued tickets remain unaffected.
1721 * This includes tickets issued to other relying parties as well as to
1722 * other tickets issued to the audience specified in this ticket.
1723 *
1724 * @param h the identity provider to use
1725 * @param identity the issuing identity
1726 * @param ticket the ticket to revoke
1727 * @param cb the callback
1728 * @param cb_cls the callback closure
1729 * @return handle to abort the operation
1730 */
1731struct GNUNET_RECLAIM_Operation *
1732GNUNET_RECLAIM_ticket_revoke (
1733 struct GNUNET_RECLAIM_Handle *h,
1734 const struct GNUNET_IDENTITY_PrivateKey *identity,
1735 const struct GNUNET_RECLAIM_Ticket *ticket,
1736 GNUNET_RECLAIM_ContinuationWithStatus cb,
1737 void *cb_cls)
1738{
1739 struct GNUNET_RECLAIM_Operation *op;
1740 struct RevokeTicketMessage *msg;
1741 uint32_t rid;
1742
1743 rid = h->r_id_gen++;
1744 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1745 op->h = h;
1746 op->rvk_cb = cb;
1747 op->cls = cb_cls;
1748 op->r_id = rid;
1749 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1750 op->env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET);
1751 msg->id = htonl (rid);
1752 msg->identity = *identity;
1753 msg->ticket = *ticket;
1754 if (NULL != h->mq)
1755 {
1756 GNUNET_MQ_send (h->mq, op->env);
1757 op->env = NULL;
1758 }
1759 return op;
1760}
1761
1762
1763/* end of reclaim_api.c */
diff --git a/src/reclaim/reclaim_attribute.c b/src/reclaim/reclaim_attribute.c
deleted file mode 100644
index 2217987ac..000000000
--- a/src/reclaim/reclaim_attribute.c
+++ /dev/null
@@ -1,550 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-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/**
22 * @file reclaim-attribute/reclaim_attribute.c
23 * @brief helper library to manage identity attributes
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_reclaim_plugin.h"
29#include "reclaim_attribute.h"
30
31
32/**
33 * Handle for a plugin
34 */
35struct Plugin
36{
37 /**
38 * Name of the plugin
39 */
40 char *library_name;
41
42 /**
43 * Plugin API
44 */
45 struct GNUNET_RECLAIM_AttributePluginFunctions *api;
46};
47
48
49/**
50 * Plugins
51 */
52static struct Plugin **attr_plugins;
53
54
55/**
56 * Number of plugins
57 */
58static unsigned int num_plugins;
59
60
61/**
62 * Init canary
63 */
64static int initialized;
65
66
67/**
68 * Add a plugin
69 *
70 * @param cls closure
71 * @param library_name name of the API library
72 * @param lib_ret the plugin API pointer
73 */
74static void
75add_plugin (void *cls, const char *library_name, void *lib_ret)
76{
77 struct GNUNET_RECLAIM_AttributePluginFunctions *api = lib_ret;
78 struct Plugin *plugin;
79
80 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81 "Loading attribute plugin `%s'\n",
82 library_name);
83 plugin = GNUNET_new (struct Plugin);
84 plugin->api = api;
85 plugin->library_name = GNUNET_strdup (library_name);
86 GNUNET_array_append (attr_plugins, num_plugins, plugin);
87}
88
89
90/**
91 * Load plugins
92 */
93static void
94init ()
95{
96 if (GNUNET_YES == initialized)
97 return;
98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_",
100 NULL,
101 &add_plugin,
102 NULL);
103}
104
105
106/**
107 * Convert a type name to the corresponding number
108 *
109 * @param typename name to convert
110 * @return corresponding number, UINT32_MAX on error
111 */
112uint32_t
113GNUNET_RECLAIM_attribute_typename_to_number (const char *typename)
114{
115 unsigned int i;
116 struct Plugin *plugin;
117 uint32_t ret;
118
119 init ();
120 for (i = 0; i < num_plugins; i++)
121 {
122 plugin = attr_plugins[i];
123 if (UINT32_MAX !=
124 (ret = plugin->api->typename_to_number (plugin->api->cls, typename)))
125 return ret;
126 }
127 return UINT32_MAX;
128}
129
130
131/**
132 * Convert a type number to the corresponding type string
133 *
134 * @param type number of a type
135 * @return corresponding typestring, NULL on error
136 */
137const char *
138GNUNET_RECLAIM_attribute_number_to_typename (uint32_t type)
139{
140 unsigned int i;
141 struct Plugin *plugin;
142 const char *ret;
143
144 init ();
145 for (i = 0; i < num_plugins; i++)
146 {
147 plugin = attr_plugins[i];
148 if (NULL !=
149 (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
150 return ret;
151 }
152 return NULL;
153}
154
155
156/**
157 * Convert human-readable version of a 'claim' of an attribute to the binary
158 * representation
159 *
160 * @param type type of the claim
161 * @param s human-readable string
162 * @param data set to value in binary encoding (will be allocated)
163 * @param data_size set to number of bytes in @a data
164 * @return #GNUNET_OK on success
165 */
166int
167GNUNET_RECLAIM_attribute_string_to_value (uint32_t type,
168 const char *s,
169 void **data,
170 size_t *data_size)
171{
172 unsigned int i;
173 struct Plugin *plugin;
174
175 init ();
176 for (i = 0; i < num_plugins; i++)
177 {
178 plugin = attr_plugins[i];
179 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
180 type,
181 s,
182 data,
183 data_size))
184 return GNUNET_OK;
185 }
186 return GNUNET_SYSERR;
187}
188
189
190/**
191 * Convert the 'claim' of an attribute to a string
192 *
193 * @param type the type of attribute
194 * @param data claim in binary encoding
195 * @param data_size number of bytes in @a data
196 * @return NULL on error, otherwise human-readable representation of the claim
197 */
198char *
199GNUNET_RECLAIM_attribute_value_to_string (uint32_t type,
200 const void *data,
201 size_t data_size)
202{
203 unsigned int i;
204 struct Plugin *plugin;
205 char *ret;
206
207 init ();
208 for (i = 0; i < num_plugins; i++)
209 {
210 plugin = attr_plugins[i];
211 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
212 type,
213 data,
214 data_size)))
215 return ret;
216 }
217 return NULL;
218}
219
220
221/**
222 * Create a new attribute.
223 *
224 * @param attr_name the attribute name
225 * @param credential credential ID of the attribute (maybe NULL)
226 * @param type the attribute type
227 * @param data the attribute value
228 * @param data_size the attribute value size
229 * @return the new attribute
230 */
231struct GNUNET_RECLAIM_Attribute *
232GNUNET_RECLAIM_attribute_new (const char *attr_name,
233 const struct
234 GNUNET_RECLAIM_Identifier *credential,
235 uint32_t type,
236 const void *data,
237 size_t data_size)
238{
239 struct GNUNET_RECLAIM_Attribute *attr;
240 char *write_ptr;
241 char *attr_name_tmp = GNUNET_strdup (attr_name);
242
243 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
244
245 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
246 + strlen (attr_name_tmp) + 1 + data_size);
247 if (NULL != credential)
248 attr->credential = *credential;
249 attr->type = type;
250 attr->data_size = data_size;
251 attr->flag = 0;
252 write_ptr = (char *) &attr[1];
253 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
254 attr->name = write_ptr;
255 write_ptr += strlen (attr->name) + 1;
256 GNUNET_memcpy (write_ptr, data, data_size);
257 attr->data = write_ptr;
258 GNUNET_free (attr_name_tmp);
259 return attr;
260}
261
262
263/**
264 * Add a new attribute to a claim list
265 *
266 * @param attr_name the name of the new attribute claim
267 * @param type the type of the claim
268 * @param data claim payload
269 * @param data_size claim payload size
270 */
271void
272GNUNET_RECLAIM_attribute_list_add (
273 struct GNUNET_RECLAIM_AttributeList *al,
274 const char *attr_name,
275 const struct GNUNET_RECLAIM_Identifier *credential,
276 uint32_t type,
277 const void *data,
278 size_t data_size)
279{
280 struct GNUNET_RECLAIM_AttributeListEntry *ale;
281
282 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
283 ale->attribute =
284 GNUNET_RECLAIM_attribute_new (attr_name, credential,
285 type, data, data_size);
286 GNUNET_CONTAINER_DLL_insert (al->list_head,
287 al->list_tail,
288 ale);
289}
290
291
292/**
293 * Get required size for serialization buffer
294 *
295 * @param attrs the attribute list to serialize
296 * @return the required buffer size
297 */
298size_t
299GNUNET_RECLAIM_attribute_list_serialize_get_size (
300 const struct GNUNET_RECLAIM_AttributeList *al)
301{
302 struct GNUNET_RECLAIM_AttributeListEntry *ale;
303 size_t len = 0;
304
305 for (ale = al->list_head; NULL != ale; ale = ale->next)
306 {
307 GNUNET_assert (NULL != ale->attribute);
308 len += GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
309 }
310 return len;
311}
312
313
314/**
315 * Serialize an attribute list
316 *
317 * @param attrs the attribute list to serialize
318 * @param result the serialized attribute
319 * @return length of serialized data
320 */
321size_t
322GNUNET_RECLAIM_attribute_list_serialize (
323 const struct GNUNET_RECLAIM_AttributeList *al,
324 char *result)
325{
326 struct GNUNET_RECLAIM_AttributeListEntry *ale;
327 size_t len;
328 size_t total_len;
329 char *write_ptr;
330 write_ptr = result;
331 total_len = 0;
332 for (ale = al->list_head; NULL != ale; ale = ale->next)
333 {
334 GNUNET_assert (NULL != ale->attribute);
335 len = GNUNET_RECLAIM_attribute_serialize (ale->attribute, write_ptr);
336 total_len += len;
337 write_ptr += len;
338 }
339 return total_len;
340}
341
342
343/**
344 * Deserialize an attribute list
345 *
346 * @param data the serialized attribute list
347 * @param data_size the length of the serialized data
348 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
349 */
350struct GNUNET_RECLAIM_AttributeList *
351GNUNET_RECLAIM_attribute_list_deserialize (const char *data, size_t data_size)
352{
353 struct GNUNET_RECLAIM_AttributeList *al;
354 struct GNUNET_RECLAIM_AttributeListEntry *ale;
355 size_t attr_len;
356 const char *read_ptr;
357 size_t left = data_size;
358
359 al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
360 if (data_size < sizeof(struct Attribute))
361 return al;
362 read_ptr = data;
363 while (left >= sizeof(struct Attribute))
364 {
365 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
366 attr_len =
367 GNUNET_RECLAIM_attribute_deserialize (read_ptr,
368 left,
369 &ale->attribute);
370 if (-1 == attr_len)
371 {
372 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
373 "Failed to deserialize malformed attribute.\n");
374 GNUNET_free (ale);
375 return al;
376 }
377 left -= attr_len;
378 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
379 read_ptr += attr_len;
380 }
381 return al;
382}
383
384
385/**
386 * Make a (deep) copy of a claim list
387 * @param attrs claim list to copy
388 * @return copied claim list
389 */
390struct GNUNET_RECLAIM_AttributeList *
391GNUNET_RECLAIM_attribute_list_dup (
392 const struct GNUNET_RECLAIM_AttributeList *al)
393{
394 struct GNUNET_RECLAIM_AttributeListEntry *ale;
395 struct GNUNET_RECLAIM_AttributeListEntry *result_ale;
396 struct GNUNET_RECLAIM_AttributeList *result;
397
398 result = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
399 for (ale = al->list_head; NULL != ale; ale = ale->next)
400 {
401 result_ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
402 GNUNET_assert (NULL != ale->attribute);
403 {
404 result_ale->attribute =
405 GNUNET_RECLAIM_attribute_new (ale->attribute->name,
406 &ale->attribute->credential,
407 ale->attribute->type,
408 ale->attribute->data,
409 ale->attribute->data_size);
410
411 result_ale->attribute->id = ale->attribute->id;
412 result_ale->attribute->flag = ale->attribute->flag;
413 }
414 GNUNET_CONTAINER_DLL_insert (result->list_head,
415 result->list_tail,
416 result_ale);
417 }
418 return result;
419}
420
421
422/**
423 * Destroy claim list
424 *
425 * @param attrs list to destroy
426 */
427void
428GNUNET_RECLAIM_attribute_list_destroy (
429 struct GNUNET_RECLAIM_AttributeList *al)
430{
431 struct GNUNET_RECLAIM_AttributeListEntry *ale;
432 struct GNUNET_RECLAIM_AttributeListEntry *tmp_ale;
433
434 for (ale = al->list_head; NULL != ale;)
435 {
436 if (NULL != ale->attribute)
437 GNUNET_free (ale->attribute);
438 tmp_ale = ale;
439 ale = ale->next;
440 GNUNET_free (tmp_ale);
441 }
442 GNUNET_free (al);
443}
444
445
446/**
447 * Get required size for serialization buffer
448 *
449 * @param attr the attribute to serialize
450 * @return the required buffer size
451 */
452size_t
453GNUNET_RECLAIM_attribute_serialize_get_size (
454 const struct GNUNET_RECLAIM_Attribute *attr)
455{
456 return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
457}
458
459
460/**
461 * Serialize an attribute
462 *
463 * @param attr the attribute to serialize
464 * @param result the serialized attribute
465 * @return length of serialized data
466 */
467size_t
468GNUNET_RECLAIM_attribute_serialize (
469 const struct GNUNET_RECLAIM_Attribute *attr,
470 char *result)
471{
472 size_t data_len_ser;
473 size_t name_len;
474 struct Attribute *attr_ser;
475 char *write_ptr;
476
477 attr_ser = (struct Attribute *) result;
478 attr_ser->attribute_type = htons (attr->type);
479 attr_ser->attribute_flag = htonl (attr->flag);
480 attr_ser->attribute_id = attr->id;
481 attr_ser->credential_id = attr->credential;
482 name_len = strlen (attr->name);
483 attr_ser->name_len = htons (name_len);
484 write_ptr = (char *) &attr_ser[1];
485 GNUNET_memcpy (write_ptr, attr->name, name_len);
486 write_ptr += name_len;
487 // TODO plugin-ize
488 // data_len_ser = plugin->serialize_attribute_value (attr,
489 // &attr_ser[1]);
490 data_len_ser = attr->data_size;
491 GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
492 attr_ser->data_size = htons (data_len_ser);
493
494 return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
495}
496
497
498/**
499 * Deserialize an attribute
500 *
501 * @param data the serialized attribute
502 * @param data_size the length of the serialized data
503 *
504 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
505 */
506ssize_t
507GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size,
508 struct GNUNET_RECLAIM_Attribute **attr)
509{
510 struct Attribute *attr_ser;
511 struct GNUNET_RECLAIM_Attribute *attribute;
512 size_t data_len;
513 size_t name_len;
514 char *write_ptr;
515
516 if (data_size < sizeof(struct Attribute))
517 return -1;
518
519 attr_ser = (struct Attribute *) data;
520 data_len = ntohs (attr_ser->data_size);
521 name_len = ntohs (attr_ser->name_len);
522 if (data_size < sizeof(struct Attribute) + data_len + name_len)
523 {
524 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
525 "Buffer too small to deserialize\n");
526 return -1;
527 }
528 attribute = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
529 + data_len + name_len + 1);
530 attribute->type = ntohs (attr_ser->attribute_type);
531 attribute->flag = ntohl (attr_ser->attribute_flag);
532 attribute->id = attr_ser->attribute_id;
533 attribute->credential = attr_ser->credential_id;
534 attribute->data_size = data_len;
535
536 write_ptr = (char *) &attribute[1];
537 GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
538 write_ptr[name_len] = '\0';
539 attribute->name = write_ptr;
540
541 write_ptr += name_len + 1;
542 GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len,
543 attribute->data_size);
544 *attr = attribute;
545 attribute->data = write_ptr;
546 return sizeof(struct Attribute) + data_len + name_len;
547}
548
549
550/* end of reclaim_attribute.c */
diff --git a/src/reclaim/reclaim_attribute.h b/src/reclaim/reclaim_attribute.h
deleted file mode 100644
index 285d75d83..000000000
--- a/src/reclaim/reclaim_attribute.h
+++ /dev/null
@@ -1,73 +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 * @file reclaim-attribute/reclaim_attribute.h
23 * @brief GNUnet reclaim identity attributes
24 *
25 */
26#ifndef RECLAIM_ATTRIBUTE_H
27#define RECLAIM_ATTRIBUTE_H
28
29#include "gnunet_reclaim_service.h"
30
31GNUNET_NETWORK_STRUCT_BEGIN
32
33/**
34 * Serialized claim
35 */
36struct Attribute
37{
38 /**
39 * Attribute type
40 */
41 uint32_t attribute_type GNUNET_PACKED;
42
43 /**
44 * Attribute flag
45 */
46 uint32_t attribute_flag GNUNET_PACKED;
47
48 /**
49 * Attribute ID
50 */
51 struct GNUNET_RECLAIM_Identifier attribute_id;
52
53 /**
54 * Credential ID
55 */
56 struct GNUNET_RECLAIM_Identifier credential_id;
57
58 /**
59 * Name length
60 */
61 uint32_t name_len GNUNET_PACKED;
62
63 /**
64 * Data size
65 */
66 uint32_t data_size GNUNET_PACKED;
67
68 // followed by data_size Attribute value data
69};
70
71GNUNET_NETWORK_STRUCT_BEGIN
72
73#endif
diff --git a/src/reclaim/reclaim_credential.c b/src/reclaim/reclaim_credential.c
deleted file mode 100644
index 5c8974400..000000000
--- a/src/reclaim/reclaim_credential.c
+++ /dev/null
@@ -1,1037 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-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/**
22 * @file reclaim/reclaim_credential.c
23 * @brief helper library to manage identity attribute credentials
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_reclaim_plugin.h"
29#include "reclaim_credential.h"
30
31
32/**
33 * Handle for a plugin
34 */
35struct Plugin
36{
37 /**
38 * Name of the plugin
39 */
40 char *library_name;
41
42 /**
43 * Plugin API
44 */
45 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
46};
47
48
49/**
50 * Plugins
51 */
52static struct Plugin **credential_plugins;
53
54
55/**
56 * Number of plugins
57 */
58static unsigned int num_plugins;
59
60
61/**
62 * Init canary
63 */
64static int initialized;
65
66
67/**
68 * Add a plugin
69 *
70 * @param cls closure
71 * @param library_name name of the API library
72 * @param lib_ret the plugin API pointer
73 */
74static void
75add_plugin (void *cls, const char *library_name, void *lib_ret)
76{
77 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = lib_ret;
78 struct Plugin *plugin;
79
80 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81 "Loading credential plugin `%s'\n",
82 library_name);
83 plugin = GNUNET_new (struct Plugin);
84 plugin->api = api;
85 plugin->library_name = GNUNET_strdup (library_name);
86 GNUNET_array_append (credential_plugins, num_plugins, plugin);
87}
88
89
90/**
91 * Load plugins
92 */
93static void
94init ()
95{
96 if (GNUNET_YES == initialized)
97 return;
98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_credential_",
100 NULL,
101 &add_plugin,
102 NULL);
103}
104
105
106/**
107 * Convert an credential type name to the corresponding number
108 *
109 * @param typename name to convert
110 * @return corresponding number, UINT32_MAX on error
111 */
112uint32_t
113GNUNET_RECLAIM_credential_typename_to_number (const char *typename)
114{
115 unsigned int i;
116 struct Plugin *plugin;
117 uint32_t ret;
118 init ();
119 for (i = 0; i < num_plugins; i++)
120 {
121 plugin = credential_plugins[i];
122 if (UINT32_MAX !=
123 (ret = plugin->api->typename_to_number (plugin->api->cls,
124 typename)))
125 return ret;
126 }
127 return UINT32_MAX;
128}
129
130
131/**
132 * Convert an credential type number to the corresponding credential type string
133 *
134 * @param type number of a type
135 * @return corresponding typestring, NULL on error
136 */
137const char *
138GNUNET_RECLAIM_credential_number_to_typename (uint32_t type)
139{
140 unsigned int i;
141 struct Plugin *plugin;
142 const char *ret;
143
144 init ();
145 for (i = 0; i < num_plugins; i++)
146 {
147 plugin = credential_plugins[i];
148 if (NULL !=
149 (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
150 return ret;
151 }
152 return NULL;
153}
154
155
156/**
157 * Convert human-readable version of a 'claim' of an credential to the binary
158 * representation
159 *
160 * @param type type of the claim
161 * @param s human-readable string
162 * @param data set to value in binary encoding (will be allocated)
163 * @param data_size set to number of bytes in @a data
164 * @return #GNUNET_OK on success
165 */
166int
167GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
168 const char *s,
169 void **data,
170 size_t *data_size)
171{
172 unsigned int i;
173 struct Plugin *plugin;
174
175 init ();
176 for (i = 0; i < num_plugins; i++)
177 {
178 plugin = credential_plugins[i];
179 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
180 type,
181 s,
182 data,
183 data_size))
184 return GNUNET_OK;
185 }
186 return GNUNET_SYSERR;
187}
188
189
190/**
191 * Convert the 'claim' of an credential to a string
192 *
193 * @param type the type of credential
194 * @param data claim in binary encoding
195 * @param data_size number of bytes in @a data
196 * @return NULL on error, otherwise human-readable representation of the claim
197 */
198char *
199GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
200 const void *data,
201 size_t data_size)
202{
203 unsigned int i;
204 struct Plugin *plugin;
205 char *ret;
206
207 init ();
208 for (i = 0; i < num_plugins; i++)
209 {
210 plugin = credential_plugins[i];
211 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
212 type,
213 data,
214 data_size)))
215 return ret;
216 }
217 return NULL;
218}
219
220
221/**
222 * Create a new credential.
223 *
224 * @param attr_name the credential name
225 * @param type the credential type
226 * @param data the credential value
227 * @param data_size the credential value size
228 * @return the new credential
229 */
230struct GNUNET_RECLAIM_Credential *
231GNUNET_RECLAIM_credential_new (const char *attr_name,
232 uint32_t type,
233 const void *data,
234 size_t data_size)
235{
236 struct GNUNET_RECLAIM_Credential *attr;
237 char *write_ptr;
238 char *attr_name_tmp = GNUNET_strdup (attr_name);
239
240 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
241
242 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
243 + strlen (attr_name_tmp) + 1 + data_size);
244 attr->type = type;
245 attr->data_size = data_size;
246 attr->flag = 0;
247 write_ptr = (char *) &attr[1];
248 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
249 attr->name = write_ptr;
250 write_ptr += strlen (attr->name) + 1;
251 GNUNET_memcpy (write_ptr, data, data_size);
252 attr->data = write_ptr;
253 GNUNET_free (attr_name_tmp);
254 return attr;
255}
256
257
258/**
259 * Get required size for serialization buffer
260 *
261 * @param attrs the attribute list to serialize
262 * @return the required buffer size
263 */
264size_t
265GNUNET_RECLAIM_credential_list_serialize_get_size (
266 const struct GNUNET_RECLAIM_CredentialList *credentials)
267{
268 struct GNUNET_RECLAIM_CredentialListEntry *le;
269 size_t len = 0;
270
271 for (le = credentials->list_head; NULL != le; le = le->next)
272 {
273 GNUNET_assert (NULL != le->credential);
274 len += GNUNET_RECLAIM_credential_serialize_get_size (le->credential);
275 len += sizeof(struct GNUNET_RECLAIM_CredentialListEntry);
276 }
277 return len;
278}
279
280
281/**
282 * Serialize an attribute list
283 *
284 * @param attrs the attribute list to serialize
285 * @param result the serialized attribute
286 * @return length of serialized data
287 */
288size_t
289GNUNET_RECLAIM_credential_list_serialize (
290 const struct GNUNET_RECLAIM_CredentialList *credentials,
291 char *result)
292{
293 struct GNUNET_RECLAIM_CredentialListEntry *le;
294 size_t len;
295 size_t total_len;
296 char *write_ptr;
297 write_ptr = result;
298 total_len = 0;
299 for (le = credentials->list_head; NULL != le; le = le->next)
300 {
301 GNUNET_assert (NULL != le->credential);
302 len = GNUNET_RECLAIM_credential_serialize (le->credential, write_ptr);
303 total_len += len;
304 write_ptr += len;
305 }
306 return total_len;
307}
308
309
310/**
311 * Deserialize an credential list
312 *
313 * @param data the serialized attribute list
314 * @param data_size the length of the serialized data
315 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
316 */
317struct GNUNET_RECLAIM_CredentialList *
318GNUNET_RECLAIM_credential_list_deserialize (const char *data, size_t data_size)
319{
320 struct GNUNET_RECLAIM_CredentialList *al;
321 struct GNUNET_RECLAIM_CredentialListEntry *ale;
322 size_t att_len;
323 const char *read_ptr;
324
325 al = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
326
327 if ((data_size < sizeof(struct
328 Credential)
329 + sizeof(struct GNUNET_RECLAIM_CredentialListEntry)))
330 return al;
331
332 read_ptr = data;
333 while (((data + data_size) - read_ptr) >= sizeof(struct Credential))
334 {
335 ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
336 ale->credential =
337 GNUNET_RECLAIM_credential_deserialize (read_ptr,
338 data_size - (read_ptr - data));
339 if (NULL == ale->credential)
340 {
341 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
342 "Failed to deserialize malformed credential.\n");
343 GNUNET_free (ale);
344 return al;
345 }
346 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
347 att_len = GNUNET_RECLAIM_credential_serialize_get_size (ale->credential);
348 read_ptr += att_len;
349 }
350 return al;
351}
352
353
354/**
355 * Make a (deep) copy of the credential list
356 * @param attrs claim list to copy
357 * @return copied claim list
358 */
359struct GNUNET_RECLAIM_CredentialList *
360GNUNET_RECLAIM_credential_list_dup (
361 const struct GNUNET_RECLAIM_CredentialList *al)
362{
363 struct GNUNET_RECLAIM_CredentialListEntry *ale;
364 struct GNUNET_RECLAIM_CredentialListEntry *result_ale;
365 struct GNUNET_RECLAIM_CredentialList *result;
366
367 result = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
368 for (ale = al->list_head; NULL != ale; ale = ale->next)
369 {
370 result_ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
371 GNUNET_assert (NULL != ale->credential);
372 result_ale->credential =
373 GNUNET_RECLAIM_credential_new (ale->credential->name,
374 ale->credential->type,
375 ale->credential->data,
376 ale->credential->data_size);
377 result_ale->credential->id = ale->credential->id;
378 GNUNET_CONTAINER_DLL_insert (result->list_head,
379 result->list_tail,
380 result_ale);
381 }
382 return result;
383}
384
385
386/**
387 * Destroy credential list
388 *
389 * @param attrs list to destroy
390 */
391void
392GNUNET_RECLAIM_credential_list_destroy (
393 struct GNUNET_RECLAIM_CredentialList *al)
394{
395 struct GNUNET_RECLAIM_CredentialListEntry *ale;
396 struct GNUNET_RECLAIM_CredentialListEntry *tmp_ale;
397
398 for (ale = al->list_head; NULL != ale;)
399 {
400 if (NULL != ale->credential)
401 GNUNET_free (ale->credential);
402 tmp_ale = ale;
403 ale = ale->next;
404 GNUNET_free (tmp_ale);
405 }
406 GNUNET_free (al);
407}
408
409
410/**
411 * Get required size for serialization buffer
412 *
413 * @param attr the credential to serialize
414 * @return the required buffer size
415 */
416size_t
417GNUNET_RECLAIM_credential_serialize_get_size (
418 const struct GNUNET_RECLAIM_Credential *credential)
419{
420 return sizeof(struct Credential) + strlen (credential->name)
421 + credential->data_size;
422}
423
424
425/**
426 * Serialize an credential
427 *
428 * @param attr the credential to serialize
429 * @param result the serialized credential
430 * @return length of serialized data
431 */
432size_t
433GNUNET_RECLAIM_credential_serialize (
434 const struct GNUNET_RECLAIM_Credential *credential,
435 char *result)
436{
437 size_t data_len_ser;
438 size_t name_len;
439 struct Credential *atts;
440 char *write_ptr;
441
442 atts = (struct Credential *) result;
443 atts->credential_type = htons (credential->type);
444 atts->credential_flag = htonl (credential->flag);
445 atts->credential_id = credential->id;
446 name_len = strlen (credential->name);
447 atts->name_len = htons (name_len);
448 write_ptr = (char *) &atts[1];
449 GNUNET_memcpy (write_ptr, credential->name, name_len);
450 write_ptr += name_len;
451 // TODO plugin-ize
452 // data_len_ser = plugin->serialize_attribute_value (attr,
453 // &attr_ser[1]);
454 data_len_ser = credential->data_size;
455 GNUNET_memcpy (write_ptr, credential->data, credential->data_size);
456 atts->data_size = htons (data_len_ser);
457
458 return sizeof(struct Credential) + strlen (credential->name)
459 + credential->data_size;
460}
461
462
463/**
464 * Deserialize an credential
465 *
466 * @param data the serialized credential
467 * @param data_size the length of the serialized data
468 *
469 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
470 */
471struct GNUNET_RECLAIM_Credential *
472GNUNET_RECLAIM_credential_deserialize (const char *data, size_t data_size)
473{
474 struct GNUNET_RECLAIM_Credential *credential;
475 struct Credential *atts;
476 size_t data_len;
477 size_t name_len;
478 char *write_ptr;
479
480 if (data_size < sizeof(struct Credential))
481 return NULL;
482
483 atts = (struct Credential *) data;
484 data_len = ntohs (atts->data_size);
485 name_len = ntohs (atts->name_len);
486 if (data_size < sizeof(struct Credential) + data_len + name_len)
487 {
488 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
489 "Buffer too small to deserialize\n");
490 return NULL;
491 }
492 credential = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
493 + data_len + name_len + 1);
494 credential->type = ntohs (atts->credential_type);
495 credential->flag = ntohl (atts->credential_flag);
496 credential->id = atts->credential_id;
497 credential->data_size = data_len;
498
499 write_ptr = (char *) &credential[1];
500 GNUNET_memcpy (write_ptr, &atts[1], name_len);
501 write_ptr[name_len] = '\0';
502 credential->name = write_ptr;
503
504 write_ptr += name_len + 1;
505 GNUNET_memcpy (write_ptr, (char *) &atts[1] + name_len,
506 credential->data_size);
507 credential->data = write_ptr;
508 return credential;
509}
510
511
512struct GNUNET_RECLAIM_AttributeList*
513GNUNET_RECLAIM_credential_get_attributes (const struct
514 GNUNET_RECLAIM_Credential *credential)
515{
516 unsigned int i;
517 struct Plugin *plugin;
518 struct GNUNET_RECLAIM_AttributeList *ret;
519 init ();
520 for (i = 0; i < num_plugins; i++)
521 {
522 plugin = credential_plugins[i];
523 if (NULL !=
524 (ret = plugin->api->get_attributes (plugin->api->cls,
525 credential)))
526 return ret;
527 }
528 return NULL;
529}
530
531
532char*
533GNUNET_RECLAIM_credential_get_issuer (const struct
534 GNUNET_RECLAIM_Credential *credential)
535{
536 unsigned int i;
537 struct Plugin *plugin;
538 char *ret;
539 init ();
540 for (i = 0; i < num_plugins; i++)
541 {
542 plugin = credential_plugins[i];
543 if (NULL !=
544 (ret = plugin->api->get_issuer (plugin->api->cls,
545 credential)))
546 return ret;
547 }
548 return NULL;
549}
550
551
552int
553GNUNET_RECLAIM_credential_get_expiration (const struct
554 GNUNET_RECLAIM_Credential *credential,
555 struct GNUNET_TIME_Absolute*exp)
556{
557 unsigned int i;
558 struct Plugin *plugin;
559 init ();
560 for (i = 0; i < num_plugins; i++)
561 {
562 plugin = credential_plugins[i];
563 if (GNUNET_OK != plugin->api->get_expiration (plugin->api->cls,
564 credential,
565 exp))
566 continue;
567 return GNUNET_OK;
568 }
569 return GNUNET_SYSERR;
570}
571
572
573/**
574 * Convert an presentation type name to the corresponding number
575 *
576 * @param typename name to convert
577 * @return corresponding number, UINT32_MAX on error
578 */
579uint32_t
580GNUNET_RECLAIM_presentation_typename_to_number (const char *typename)
581{
582 unsigned int i;
583 struct Plugin *plugin;
584 uint32_t ret;
585 init ();
586 for (i = 0; i < num_plugins; i++)
587 {
588 plugin = credential_plugins[i];
589 if (UINT32_MAX !=
590 (ret = plugin->api->typename_to_number_p (plugin->api->cls,
591 typename)))
592 return ret;
593 }
594 return UINT32_MAX;
595}
596
597
598/**
599 * Convert an presentation type number to the corresponding presentation type string
600 *
601 * @param type number of a type
602 * @return corresponding typestring, NULL on error
603 */
604const char *
605GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type)
606{
607 unsigned int i;
608 struct Plugin *plugin;
609 const char *ret;
610
611 init ();
612 for (i = 0; i < num_plugins; i++)
613 {
614 plugin = credential_plugins[i];
615 if (NULL !=
616 (ret = plugin->api->number_to_typename_p (plugin->api->cls, type)))
617 return ret;
618 }
619 return NULL;
620}
621
622
623/**
624 * Convert human-readable version of a 'claim' of an presentation to the binary
625 * representation
626 *
627 * @param type type of the claim
628 * @param s human-readable string
629 * @param data set to value in binary encoding (will be allocated)
630 * @param data_size set to number of bytes in @a data
631 * @return #GNUNET_OK on success
632 */
633int
634GNUNET_RECLAIM_presentation_string_to_value (uint32_t type,
635 const char *s,
636 void **data,
637 size_t *data_size)
638{
639 unsigned int i;
640 struct Plugin *plugin;
641
642 init ();
643 for (i = 0; i < num_plugins; i++)
644 {
645 plugin = credential_plugins[i];
646 if (GNUNET_OK == plugin->api->string_to_value_p (plugin->api->cls,
647 type,
648 s,
649 data,
650 data_size))
651 return GNUNET_OK;
652 }
653 return GNUNET_SYSERR;
654}
655
656
657/**
658 * Convert the 'claim' of an presentation to a string
659 *
660 * @param type the type of presentation
661 * @param data claim in binary encoding
662 * @param data_size number of bytes in @a data
663 * @return NULL on error, otherwise human-readable representation of the claim
664 */
665char *
666GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
667 const void *data,
668 size_t data_size)
669{
670 unsigned int i;
671 struct Plugin *plugin;
672 char *ret;
673
674 init ();
675 for (i = 0; i < num_plugins; i++)
676 {
677 plugin = credential_plugins[i];
678 if (NULL != (ret = plugin->api->value_to_string_p (plugin->api->cls,
679 type,
680 data,
681 data_size)))
682 return ret;
683 }
684 return NULL;
685}
686
687
688struct GNUNET_RECLAIM_Presentation *
689GNUNET_RECLAIM_presentation_new (uint32_t type,
690 const void *data,
691 size_t data_size)
692{
693 struct GNUNET_RECLAIM_Presentation *attr;
694 char *write_ptr;
695
696 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
697 + data_size);
698 attr->type = type;
699 attr->data_size = data_size;
700 write_ptr = (char *) &attr[1];
701 GNUNET_memcpy (write_ptr, data, data_size);
702 attr->data = write_ptr;
703 return attr;
704}
705
706
707/**
708 * Get required size for serialization buffer
709 *
710 * @param attrs the attribute list to serialize
711 * @return the required buffer size
712 */
713size_t
714GNUNET_RECLAIM_presentation_list_serialize_get_size (
715 const struct GNUNET_RECLAIM_PresentationList *presentations)
716{
717 struct GNUNET_RECLAIM_PresentationListEntry *le;
718 size_t len = 0;
719
720 for (le = presentations->list_head; NULL != le; le = le->next)
721 {
722 GNUNET_assert (NULL != le->presentation);
723 len += GNUNET_RECLAIM_presentation_serialize_get_size (le->presentation);
724 len += sizeof(struct GNUNET_RECLAIM_PresentationListEntry);
725 }
726 return len;
727}
728
729
730/**
731 * Serialize an attribute list
732 *
733 * @param attrs the attribute list to serialize
734 * @param result the serialized attribute
735 * @return length of serialized data
736 */
737size_t
738GNUNET_RECLAIM_presentation_list_serialize (
739 const struct GNUNET_RECLAIM_PresentationList *presentations,
740 char *result)
741{
742 struct GNUNET_RECLAIM_PresentationListEntry *le;
743 size_t len;
744 size_t total_len;
745 char *write_ptr;
746 write_ptr = result;
747 total_len = 0;
748 for (le = presentations->list_head; NULL != le; le = le->next)
749 {
750 GNUNET_assert (NULL != le->presentation);
751 len = GNUNET_RECLAIM_presentation_serialize (le->presentation, write_ptr);
752 total_len += len;
753 write_ptr += len;
754 }
755 return total_len;
756}
757
758
759/**
760 * Deserialize an presentation list
761 *
762 * @param data the serialized attribute list
763 * @param data_size the length of the serialized data
764 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
765 */
766struct GNUNET_RECLAIM_PresentationList *
767GNUNET_RECLAIM_presentation_list_deserialize (const char *data, size_t
768 data_size)
769{
770 struct GNUNET_RECLAIM_PresentationList *al;
771 struct GNUNET_RECLAIM_PresentationListEntry *ale;
772 size_t att_len;
773 const char *read_ptr;
774
775 al = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
776
777 if ((data_size < sizeof(struct Presentation)
778 + sizeof(struct GNUNET_RECLAIM_PresentationListEntry)))
779 return al;
780
781 read_ptr = data;
782 while (((data + data_size) - read_ptr) >= sizeof(struct Presentation))
783 {
784 ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
785 ale->presentation =
786 GNUNET_RECLAIM_presentation_deserialize (read_ptr,
787 data_size - (read_ptr - data));
788 if (NULL == ale->presentation)
789 {
790 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
791 "Failed to deserialize malformed presentation.\n");
792 GNUNET_free (ale);
793 return al;
794 }
795 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
796 att_len = GNUNET_RECLAIM_presentation_serialize_get_size (
797 ale->presentation);
798 read_ptr += att_len;
799 }
800 return al;
801}
802
803
804/**
805 * Make a (deep) copy of the presentation list
806 * @param attrs claim list to copy
807 * @return copied claim list
808 */
809struct GNUNET_RECLAIM_PresentationList *
810GNUNET_RECLAIM_presentation_list_dup (
811 const struct GNUNET_RECLAIM_PresentationList *al)
812{
813 struct GNUNET_RECLAIM_PresentationListEntry *ale;
814 struct GNUNET_RECLAIM_PresentationListEntry *result_ale;
815 struct GNUNET_RECLAIM_PresentationList *result;
816
817 result = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
818 for (ale = al->list_head; NULL != ale; ale = ale->next)
819 {
820 result_ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
821 GNUNET_assert (NULL != ale->presentation);
822 result_ale->presentation =
823 GNUNET_RECLAIM_presentation_new (ale->presentation->type,
824 ale->presentation->data,
825 ale->presentation->data_size);
826 result_ale->presentation->credential_id = ale->presentation->credential_id;
827 GNUNET_CONTAINER_DLL_insert (result->list_head,
828 result->list_tail,
829 result_ale);
830 }
831 return result;
832}
833
834
835/**
836 * Destroy presentation list
837 *
838 * @param attrs list to destroy
839 */
840void
841GNUNET_RECLAIM_presentation_list_destroy (
842 struct GNUNET_RECLAIM_PresentationList *al)
843{
844 struct GNUNET_RECLAIM_PresentationListEntry *ale;
845 struct GNUNET_RECLAIM_PresentationListEntry *tmp_ale;
846
847 for (ale = al->list_head; NULL != ale;)
848 {
849 if (NULL != ale->presentation)
850 GNUNET_free (ale->presentation);
851 tmp_ale = ale;
852 ale = ale->next;
853 GNUNET_free (tmp_ale);
854 }
855 GNUNET_free (al);
856}
857
858
859/**
860 * Get required size for serialization buffer
861 *
862 * @param attr the presentation to serialize
863 * @return the required buffer size
864 */
865size_t
866GNUNET_RECLAIM_presentation_serialize_get_size (
867 const struct GNUNET_RECLAIM_Presentation *presentation)
868{
869 return sizeof(struct Presentation) + presentation->data_size;
870}
871
872
873/**
874 * Serialize an presentation
875 *
876 * @param attr the presentation to serialize
877 * @param result the serialized presentation
878 * @return length of serialized data
879 */
880size_t
881GNUNET_RECLAIM_presentation_serialize (
882 const struct GNUNET_RECLAIM_Presentation *presentation,
883 char *result)
884{
885 struct Presentation *atts;
886 char *write_ptr;
887
888 atts = (struct Presentation *) result;
889 atts->presentation_type = htons (presentation->type);
890 atts->credential_id = presentation->credential_id;
891 write_ptr = (char *) &atts[1];
892 GNUNET_memcpy (write_ptr, presentation->data, presentation->data_size);
893 atts->data_size = htons (presentation->data_size);
894
895 return sizeof(struct Presentation) + presentation->data_size;
896}
897
898
899/**
900 * Deserialize an presentation
901 *
902 * @param data the serialized presentation
903 * @param data_size the length of the serialized data
904 *
905 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
906 */
907struct GNUNET_RECLAIM_Presentation *
908GNUNET_RECLAIM_presentation_deserialize (const char *data, size_t data_size)
909{
910 struct GNUNET_RECLAIM_Presentation *presentation;
911 struct Presentation *atts;
912 size_t data_len;
913 char *write_ptr;
914
915 if (data_size < sizeof(struct Presentation))
916 return NULL;
917
918 atts = (struct Presentation *) data;
919 data_len = ntohs (atts->data_size);
920 if (data_size < sizeof(struct Presentation) + data_len)
921 {
922 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
923 "Buffer too small to deserialize\n");
924 return NULL;
925 }
926 presentation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
927 + data_len);
928 presentation->type = ntohs (atts->presentation_type);
929 presentation->credential_id = atts->credential_id;
930 presentation->data_size = data_len;
931
932 write_ptr = (char *) &presentation[1];
933 GNUNET_memcpy (write_ptr, &atts[1], data_len);
934 presentation->data = write_ptr;
935 return presentation;
936}
937
938
939struct GNUNET_RECLAIM_AttributeList*
940GNUNET_RECLAIM_presentation_get_attributes (const struct
941 GNUNET_RECLAIM_Presentation *
942 presentation)
943{
944 unsigned int i;
945 struct Plugin *plugin;
946 struct GNUNET_RECLAIM_AttributeList *ret;
947 init ();
948 for (i = 0; i < num_plugins; i++)
949 {
950 plugin = credential_plugins[i];
951 if (NULL !=
952 (ret = plugin->api->get_attributes_p (plugin->api->cls,
953 presentation)))
954 return ret;
955 }
956 return NULL;
957}
958
959
960char*
961GNUNET_RECLAIM_presentation_get_issuer (const struct
962 GNUNET_RECLAIM_Presentation *
963 presentation)
964{
965 unsigned int i;
966 struct Plugin *plugin;
967 char *ret;
968 init ();
969 for (i = 0; i < num_plugins; i++)
970 {
971 plugin = credential_plugins[i];
972 if (NULL !=
973 (ret = plugin->api->get_issuer_p (plugin->api->cls,
974 presentation)))
975 return ret;
976 }
977 return NULL;
978}
979
980
981int
982GNUNET_RECLAIM_presentation_get_expiration (const struct
983 GNUNET_RECLAIM_Presentation *
984 presentation,
985 struct GNUNET_TIME_Absolute*exp)
986{
987 unsigned int i;
988 struct Plugin *plugin;
989 init ();
990 for (i = 0; i < num_plugins; i++)
991 {
992 plugin = credential_plugins[i];
993 if (GNUNET_OK != plugin->api->get_expiration_p (plugin->api->cls,
994 presentation,
995 exp))
996 continue;
997 return GNUNET_OK;
998 }
999 return GNUNET_SYSERR;
1000}
1001
1002/**
1003 * Create a presentation from a credential and a lift of (selected)
1004 * attributes in the credential.
1005 * FIXME not yet implemented
1006 *
1007 * @param cred the credential to use
1008 * @param attrs the attributes to present from the credential
1009 * @return the credential presentation presenting the attributes according
1010 * to the presentation mechanism of the credential
1011 * or NULL on error.
1012 */
1013int
1014GNUNET_RECLAIM_credential_get_presentation (
1015 const struct GNUNET_RECLAIM_Credential *cred,
1016 const struct GNUNET_RECLAIM_AttributeList *attrs,
1017 struct GNUNET_RECLAIM_Presentation **pres)
1018{
1019 unsigned int i;
1020 struct Plugin *plugin;
1021 init ();
1022 for (i = 0; i < num_plugins; i++)
1023 {
1024 plugin = credential_plugins[i];
1025 if (GNUNET_OK != plugin->api->create_presentation (plugin->api->cls,
1026 cred,
1027 attrs,
1028 pres))
1029 continue;
1030 (*pres)->credential_id = cred->id;
1031 return GNUNET_OK;
1032 }
1033 return GNUNET_SYSERR;
1034}
1035
1036
1037
diff --git a/src/reclaim/reclaim_credential.h b/src/reclaim/reclaim_credential.h
deleted file mode 100644
index 7704ed968..000000000
--- a/src/reclaim/reclaim_credential.h
+++ /dev/null
@@ -1,99 +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 * @file reclaim/reclaim_credential.h
23 * @brief GNUnet reclaim identity attribute credentials
24 *
25 */
26#ifndef RECLAIM_CREDENTIAL_H
27#define RECLAIM_CREDENTIAL_H
28
29#include "gnunet_reclaim_service.h"
30
31/**
32 * Serialized credential claim
33 */
34struct Credential
35{
36 /**
37 * Credential type
38 */
39 uint32_t credential_type;
40
41 /**
42 * Credential flag
43 */
44 uint32_t credential_flag;
45
46 /**
47 * Credential ID
48 */
49 struct GNUNET_RECLAIM_Identifier credential_id;
50
51 /**
52 * Name length
53 */
54 uint32_t name_len;
55
56 /**
57 * Data size
58 */
59 uint32_t data_size;
60
61 // followed by data_size Credential value data
62};
63
64
65/**
66 * Serialized presentation claim
67 */
68struct Presentation
69{
70 /**
71 * Presentation type
72 */
73 uint32_t presentation_type;
74
75 /**
76 * Presentation flag
77 */
78 uint32_t presentation_flag;
79
80 /**
81 * Credential ID
82 */
83 struct GNUNET_RECLAIM_Identifier credential_id;
84
85 /**
86 * Name length
87 */
88 uint32_t name_len;
89
90 /**
91 * Data size
92 */
93 uint32_t data_size;
94
95 // followed by data_size Presentation value data
96};
97
98
99#endif
diff --git a/src/reclaim/test_reclaim.conf b/src/reclaim/test_reclaim.conf
deleted file mode 100644
index ec19056e4..000000000
--- a/src/reclaim/test_reclaim.conf
+++ /dev/null
@@ -1,34 +0,0 @@
1@INLINE@ test_reclaim_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-reclaim-peer-1/
5
6[dht]
7START_ON_DEMAND = YES
8
9[rest]
10START_ON_DEMAND = YES
11PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=$GNUNET_TMP/restlog
12
13[transport]
14PLUGINS =
15
16[reclaim]
17START_ON_DEMAND = YES
18TICKET_REFRESH_INTERVAL = 15s
19#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=$GNUNET_TMP/idplog
20
21[gns]
22#PREFIX = valgrind --leak-check=full --track-origins=yes
23START_ON_DEMAND = YES
24AUTO_IMPORT_PKEY = YES
25MAX_PARALLEL_BACKGROUND_QUERIES = 10
26DEFAULT_LOOKUP_TIMEOUT = 15 s
27RECORD_PUT_INTERVAL = 1 h
28ZONE_PUBLISH_TIME_WINDOW = 1 h
29DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
30
31[reclaim-rest-plugin]
32address = http://localhost:8000/#/login
33psw = mysupersecretpassword
34expiration_time = 3600
diff --git a/src/reclaim/test_reclaim.sh b/src/reclaim/test_reclaim.sh
deleted file mode 100755
index da93b10f7..000000000
--- a/src/reclaim/test_reclaim.sh
+++ /dev/null
@@ -1,31 +0,0 @@
1#!/bin/sh
2#trap "gnunet-arm -e -c test_reclaim_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_reclaim.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_reclaim.conf
27gnunet-identity -C testego -c test_reclaim.conf
28valgrind gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
29gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf
30gnunet-reclaim -e testego -D -c test_reclaim.conf
31gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_attribute.c b/src/reclaim/test_reclaim_attribute.c
deleted file mode 100644
index f8faf8021..000000000
--- a/src/reclaim/test_reclaim_attribute.c
+++ /dev/null
@@ -1,49 +0,0 @@
1#include "platform.h"
2#include "gnunet_common.h"
3#include "gnunet_reclaim_lib.h"
4#include "gnunet_container_lib.h"
5
6int
7main (int argc, char *argv[])
8{
9 struct GNUNET_RECLAIM_AttributeList *al;
10 struct GNUNET_RECLAIM_AttributeList *al_two;
11 struct GNUNET_RECLAIM_AttributeListEntry *ale;
12 char attrname[100];
13 char attrdata[100];
14 size_t ser_len_claimed;
15 size_t ser_len_actual;
16 char *ser_data;
17 int count = 0;
18
19 al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
20 for (int i = 0; i < 12; i++)
21 {
22 memset (attrname, 0, 100);
23 memset (attrdata, 0, 100);
24 sprintf (attrname, "attr%d", i);
25 sprintf (attrdata, "%d", i);
26 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
27 ale->attribute = GNUNET_RECLAIM_attribute_new (attrname,
28 &GNUNET_RECLAIM_ID_ZERO,
29 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
30 attrdata,
31 strlen (attrdata));
32 GNUNET_CONTAINER_DLL_insert (al->list_head,
33 al->list_tail,
34 ale);
35 }
36 ser_len_claimed = GNUNET_RECLAIM_attribute_list_serialize_get_size (al);
37 ser_data = GNUNET_malloc (ser_len_claimed);
38 ser_len_actual = GNUNET_RECLAIM_attribute_list_serialize (al,
39 ser_data);
40 GNUNET_assert (ser_len_claimed == ser_len_actual);
41 al_two = GNUNET_RECLAIM_attribute_list_deserialize (ser_data,
42 ser_len_actual);
43 for (ale = al_two->list_head; NULL != ale; ale = ale->next)
44 count++;
45 GNUNET_assert (12 == count);
46 //GNUNET_assert (-1 != deser_len);
47 GNUNET_free (ser_data);
48 GNUNET_RECLAIM_attribute_list_destroy (al);
49}
diff --git a/src/reclaim/test_reclaim_attribute.sh b/src/reclaim/test_reclaim_attribute.sh
deleted file mode 100755
index 744c898ed..000000000
--- a/src/reclaim/test_reclaim_attribute.sh
+++ /dev/null
@@ -1,40 +0,0 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_reclaim.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_reclaim.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_reclaim.conf
27#gnunet-arm -i rest -c test_reclaim.conf
28gnunet-identity -C testego -c test_reclaim.conf
29gnunet-identity -C rpego -c test_reclaim.conf
30TEST_KEY=$(gnunet-identity -d -e testego -q -c test_reclaim.conf)
31gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
32gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf > /dev/null 2>&1
33if test $? != 0
34then
35 echo "Failed."
36 exit 1
37fi
38
39#curl localhost:7776/reclaim/attributes/testego
40gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_consume.sh b/src/reclaim/test_reclaim_consume.sh
deleted file mode 100755
index 55f6ff22c..000000000
--- a/src/reclaim/test_reclaim_consume.sh
+++ /dev/null
@@ -1,43 +0,0 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_reclaim.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_reclaim.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_reclaim.conf
27#gnunet-arm -i rest -c test_reclaim.conf
28gnunet-identity -C testego -c test_reclaim.conf
29gnunet-identity -C rpego -c test_reclaim.conf
30SUBJECT_KEY=$(gnunet-identity -d -e rpego -q -c test_reclaim.conf)
31TEST_KEY=$(gnunet-identity -d -e testego -q -c test_reclaim.conf)
32gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
33gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf
34TICKET=$(gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf | awk '{print $1}')
35gnunet-reclaim -e rpego -C $TICKET -c test_reclaim.conf > /dev/null 2>&1
36
37if test $? != 0
38then
39 "Failed."
40 exit 1
41fi
42#curl http://localhost:7776/reclaim/tickets/testego
43gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_defaults.conf b/src/reclaim/test_reclaim_defaults.conf
deleted file mode 100644
index a9a197dea..000000000
--- a/src/reclaim/test_reclaim_defaults.conf
+++ /dev/null
@@ -1,24 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-idp-testing/
5
6[namestore-sqlite]
7FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
8
9[namecache-sqlite]
10FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
11
12[identity]
13# Directory where we store information about our egos
14EGODIR = $GNUNET_TEST_HOME/identity/egos/
15
16[dhtcache]
17DATABASE = heap
18
19[transport]
20PLUGINS = tcp
21
22[transport-tcp]
23BINDTO = 127.0.0.1
24
diff --git a/src/reclaim/test_reclaim_issue.sh b/src/reclaim/test_reclaim_issue.sh
deleted file mode 100755
index 7ab8a6980..000000000
--- a/src/reclaim/test_reclaim_issue.sh
+++ /dev/null
@@ -1,42 +0,0 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_reclaim.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_reclaim.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_reclaim.conf
27#gnunet-arm -i rest -c test_reclaim.conf
28gnunet-identity -C testego -c test_reclaim.conf
29gnunet-identity -C rpego -c test_reclaim.conf
30SUBJECT_KEY=$(gnunet-identity -d -e rpego -q -c test_reclaim.conf)
31TEST_KEY=$(gnunet-identity -d -e testego -q -c test_reclaim.conf)
32gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf > /dev/null 2>&1
33gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf > /dev/null 2>&1
34#gnunet-reclaim -e testego -D -c test_reclaim.conf
35gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf > /dev/null 2>&1
36if test $? != 0
37then
38 echo "Failed."
39 exit 1
40fi
41#curl http://localhost:7776/reclaim/attributes/testego
42gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_revoke.sh b/src/reclaim/test_reclaim_revoke.sh
deleted file mode 100755
index ffbc7ef2b..000000000
--- a/src/reclaim/test_reclaim_revoke.sh
+++ /dev/null
@@ -1,65 +0,0 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_reclaim.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_reclaim.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_reclaim.conf 2&>1 > /dev/null
27gnunet-identity -C alice -c test_reclaim.conf
28gnunet-identity -C bob -c test_reclaim.conf
29gnunet-identity -C eve -c test_reclaim.conf
30ALICE_KEY=$(gnunet-identity -d -e alice -q -c test_reclaim.conf)
31BOB_KEY=$(gnunet-identity -d -e bob -q -c test_reclaim.conf)
32EVE_KEY=$(gnunet-identity -d -e eve -q -c test_reclaim.conf)
33gnunet-reclaim -e alice -E 15s -a email -V john@doe.gnu -c test_reclaim.conf
34gnunet-reclaim -e alice -E 15s -a name -V John -c test_reclaim.conf
35TICKET_BOB=$(gnunet-reclaim -e alice -i "email,name" -r $BOB_KEY -c test_reclaim.conf | awk '{print $1}')
36#gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf
37TICKET_EVE=$(gnunet-reclaim -e alice -i "email" -r $EVE_KEY -c test_reclaim.conf | awk '{print $1}')
38gnunet-namestore -z alice -D
39echo "Revoking $TICKET"
40gnunet-reclaim -e alice -R $TICKET_EVE -c test_reclaim.conf
41gnunet-namestore -z alice -D
42sleep 16
43echo "Consuming $TICKET"
44
45gnunet-reclaim -e eve -C $TICKET_EVE -c test_reclaim.conf
46if test $? == 0
47then
48 echo "Eve can still resolve attributes..."
49 gnunet-arm -e -c test_reclaim.conf
50 exit 1
51fi
52
53gnunet-arm -e -c test_reclaim.conf
54gnunet-arm -s -c test_reclaim.conf 2&>1 > /dev/null
55
56gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf
57#gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf 2&>1 >/dev/null
58if test $? != 0
59then
60 echo "Bob cannot resolve attributes..."
61 gnunet-arm -e -c test_reclaim.conf
62 exit 1
63fi
64
65gnunet-arm -e -c test_reclaim.conf