aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-19 12:49:08 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-19 12:49:08 +0200
commit39e327905f421c470b9cbd5c1ea548261bcae026 (patch)
treefa0df2a80fe4c785e12c609f619eb5f95e55904c /src/reclaim
parenta2de0769515468c733b72698f04b24d03190f719 (diff)
downloadgnunet-39e327905f421c470b9cbd5c1ea548261bcae026.tar.gz
gnunet-39e327905f421c470b9cbd5c1ea548261bcae026.zip
BUILD: Move reclaim to service
Diffstat (limited to 'src/reclaim')
-rw-r--r--src/reclaim/.gitignore5
-rw-r--r--src/reclaim/Makefile.am252
-rw-r--r--src/reclaim/did.h49
-rw-r--r--src/reclaim/did_core.c265
-rw-r--r--src/reclaim/did_core.h138
-rw-r--r--src/reclaim/did_helper.c203
-rw-r--r--src/reclaim/did_helper.h74
-rw-r--r--src/reclaim/did_misc.c70
-rw-r--r--src/reclaim/gnunet-did.c647
-rw-r--r--src/reclaim/gnunet-reclaim.c928
-rw-r--r--src/reclaim/gnunet-service-reclaim.c2814
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.c1894
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.h280
-rw-r--r--src/reclaim/json_reclaim.c398
-rw-r--r--src/reclaim/json_reclaim.h57
-rw-r--r--src/reclaim/meson.build144
-rw-r--r--src/reclaim/oidc_helper.c1026
-rw-r--r--src/reclaim/oidc_helper.h196
-rw-r--r--src/reclaim/pabc_helper.c366
-rw-r--r--src/reclaim/pabc_helper.h41
-rw-r--r--src/reclaim/plugin_gnsrecord_reclaim.c195
-rw-r--r--src/reclaim/plugin_reclaim_attribute_basic.c181
-rw-r--r--src/reclaim/plugin_reclaim_credential_jwt.c512
-rw-r--r--src/reclaim/plugin_reclaim_credential_pabc.c572
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c3162
-rw-r--r--src/reclaim/plugin_rest_pabc.c667
-rw-r--r--src/reclaim/plugin_rest_reclaim.c1564
-rw-r--r--src/reclaim/reclaim.conf22
-rw-r--r--src/reclaim/reclaim.h600
-rw-r--r--src/reclaim/reclaim_api.c1813
-rw-r--r--src/reclaim/reclaim_attribute.c547
-rw-r--r--src/reclaim/reclaim_attribute.h83
-rw-r--r--src/reclaim/reclaim_credential.c1004
-rw-r--r--src/reclaim/reclaim_credential.h119
-rw-r--r--src/reclaim/test_did_helper.c137
-rw-r--r--src/reclaim/test_reclaim.conf38
-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.sh49
-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
-rw-r--r--src/reclaim/test_w3c_ed25519_2020.c69
44 files changed, 0 insertions, 21432 deletions
diff --git a/src/reclaim/.gitignore b/src/reclaim/.gitignore
deleted file mode 100644
index e22aa5011..000000000
--- a/src/reclaim/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
1gnunet-reclaim
2gnunet-service-reclaim
3gnunet-did
4test_did_helper
5test_reclaim_attribute
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am
deleted file mode 100644
index e5603d662..000000000
--- a/src/reclaim/Makefile.am
+++ /dev/null
@@ -1,252 +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_reclaim.la
14
15if HAVE_JOSE
16REST_PLUGIN += libgnunet_plugin_rest_openid_connect.la
17endif
18
19CREDENTIAL_PLUGIN = \
20 libgnunet_plugin_reclaim_credential_jwt.la
21
22if HAVE_PABC
23 CREDENTIAL_PLUGIN += libgnunet_plugin_reclaim_credential_pabc.la
24 REST_PLUGIN += libgnunet_plugin_rest_pabc.la
25endif
26
27EXTRA_DIST = \
28 reclaim.conf \
29 test_reclaim_defaults.conf \
30 test_reclaim.conf \
31 $(check_SCRIPTS)
32
33pkgcfgdir= $(pkgdatadir)/config.d/
34
35libexecdir= $(pkglibdir)/libexec/
36
37pkgcfg_DATA = \
38 reclaim.conf
39
40lib_LTLIBRARIES = \
41 libgnunetreclaim.la \
42 libgnunetdid.la
43plugin_LTLIBRARIES = \
44 libgnunet_plugin_gnsrecord_reclaim.la \
45 libgnunet_plugin_reclaim_attribute_basic.la \
46 $(CREDENTIAL_PLUGIN) \
47 $(REST_PLUGIN)
48
49bin_PROGRAMS = \
50 gnunet-reclaim \
51 gnunet-did
52
53libexec_PROGRAMS = \
54 gnunet-service-reclaim
55
56libgnunet_plugin_rest_reclaim_la_SOURCES = \
57 plugin_rest_reclaim.c \
58 json_reclaim.h \
59 json_reclaim.c
60libgnunet_plugin_rest_reclaim_la_LIBADD = \
61 $(top_builddir)/src/service/identity/libgnunetidentity.la \
62 libgnunetreclaim.la \
63 $(top_builddir)/src/lib/json/libgnunetjson.la \
64 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
65 $(top_builddir)/src/service/rest/libgnunetrest.la \
66 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
67 $(top_builddir)/src/lib/util/libgnunetutil.la $(XLIBS) \
68 $(LTLIBINTL) -ljansson $(MHD_LIBS)
69libgnunet_plugin_rest_reclaim_la_LDFLAGS = \
70 $(GN_PLUGIN_LDFLAGS)
71libgnunet_plugin_rest_reclaim_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
72
73if HAVE_JOSE
74libgnunet_plugin_rest_openid_connect_la_SOURCES = \
75 plugin_rest_openid_connect.c \
76 oidc_helper.h \
77 oidc_helper.c
78libgnunet_plugin_rest_openid_connect_la_LIBADD = \
79 $(top_builddir)/src/service/identity/libgnunetidentity.la \
80 libgnunetreclaim.la \
81 $(top_builddir)/src/service/rest/libgnunetrest.la \
82 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
83 $(top_builddir)/src/service/gns/libgnunetgns.la \
84 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
85 $(top_builddir)/src/lib/util/libgnunetutil.la $(XLIBS) \
86 $(LTLIBINTL) -ljansson -ljose $(MHD_LIBS) \
87 $(LIBGCRYPT_LIBS)
88libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \
89 $(GN_PLUGIN_LDFLAGS)
90libgnunet_plugin_rest_openid_connect_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
91endif
92
93if HAVE_PABC
94libgnunet_plugin_rest_pabc_la_SOURCES = \
95 plugin_rest_pabc.c \
96 pabc_helper.c
97libgnunet_plugin_rest_pabc_la_LIBADD = \
98 libgnunetreclaim.la \
99 $(top_builddir)/src/lib/json/libgnunetjson.la \
100 $(top_builddir)/src/service/rest/libgnunetrest.la \
101 $(top_builddir)/src/lib/util/libgnunetutil.la $(XLIBS) \
102 $(LTLIBINTL) -ljansson -lpabc $(MHD_LIBS)
103libgnunet_plugin_rest_pabc_la_LDFLAGS = \
104 $(GN_PLUGIN_LDFLAGS)
105libgnunet_plugin_rest_pabc_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
106endif
107
108
109libgnunet_plugin_gnsrecord_reclaim_la_SOURCES = \
110 plugin_gnsrecord_reclaim.c
111libgnunet_plugin_gnsrecord_reclaim_la_LIBADD = \
112 $(top_builddir)/src/lib/util/libgnunetutil.la \
113 $(LTLIBINTL)
114libgnunet_plugin_gnsrecord_reclaim_la_LDFLAGS = \
115 $(GN_PLUGIN_LDFLAGS)
116
117
118gnunet_service_reclaim_SOURCES = \
119 gnunet-service-reclaim.c \
120 gnunet-service-reclaim_tickets.c \
121 gnunet-service-reclaim_tickets.h
122gnunet_service_reclaim_LDADD = \
123 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
124 $(top_builddir)/src/service/identity/libgnunetidentity.la \
125 $(top_builddir)/src/lib/util/libgnunetutil.la \
126 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
127 $(top_builddir)/src/service/statistics/libgnunetstatistics.la \
128 libgnunetreclaim.la \
129 $(top_builddir)/src/service/gns/libgnunetgns.la \
130 $(GN_LIBINTL)
131
132libgnunetreclaim_la_SOURCES = \
133 reclaim_api.c \
134 reclaim.h \
135 reclaim_attribute.c \
136 reclaim_attribute.h \
137 reclaim_credential.c \
138 reclaim_credential.h
139libgnunetreclaim_la_LIBADD = \
140 $(top_builddir)/src/lib/util/libgnunetutil.la \
141 $(top_builddir)/src/service/identity/libgnunetidentity.la \
142 $(GN_LIBINTL) $(XLIB)
143libgnunetreclaim_la_LDFLAGS = \
144 $(GN_LIB_LDFLAGS) \
145 -version-info 0:0:0
146
147libgnunetdid_la_SOURCES = \
148 did_helper.c \
149 did_helper.h \
150 did_core.h \
151 did_core.c
152libgnunetdid_la_LIBADD = \
153 $(top_builddir)/src/lib/util/libgnunetutil.la \
154 $(top_builddir)/src/service/gns/libgnunetgns.la \
155 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
156 $(top_builddir)/src/service/identity/libgnunetidentity.la \
157 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
158 -ljansson \
159 $(GN_LIBINTL) $(XLIB)
160libgnunetdid_la_LDFLAGS = \
161 $(GN_LIB_LDFLAGS) \
162 -version-info 0:0:0
163
164libgnunet_plugin_reclaim_attribute_basic_la_SOURCES = \
165 plugin_reclaim_attribute_basic.c
166libgnunet_plugin_reclaim_attribute_basic_la_LIBADD = \
167 $(top_builddir)/src/lib/util/libgnunetutil.la \
168 $(LTLIBINTL)
169libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \
170 $(GN_PLUGIN_LDFLAGS)
171
172if HAVE_PABC
173libgnunet_plugin_reclaim_credential_pabc_la_SOURCES = \
174 plugin_reclaim_credential_pabc.c \
175 pabc_helper.c \
176 pabc_helper.h
177libgnunet_plugin_reclaim_credential_pabc_la_LIBADD = \
178 $(top_builddir)/src/lib/util/libgnunetutil.la \
179 libgnunetreclaim.la \
180 -ljansson\
181 -lpabc \
182 $(LTLIBINTL)
183libgnunet_plugin_reclaim_credential_pabc_la_LDFLAGS = \
184 $(GN_PLUGIN_LDFLAGS)
185endif
186
187
188libgnunet_plugin_reclaim_credential_jwt_la_SOURCES = \
189 plugin_reclaim_credential_jwt.c
190libgnunet_plugin_reclaim_credential_jwt_la_LIBADD = \
191 $(top_builddir)/src/service/identity/libgnunetidentity.la \
192 $(top_builddir)/src/lib/util/libgnunetutil.la \
193 libgnunetreclaim.la \
194 -ljansson\
195 $(LTLIBINTL)
196libgnunet_plugin_reclaim_credential_jwt_la_LDFLAGS = \
197 $(GN_PLUGIN_LDFLAGS)
198
199gnunet_reclaim_SOURCES = \
200 gnunet-reclaim.c
201gnunet_reclaim_LDADD = \
202 $(top_builddir)/src/lib/util/libgnunetutil.la \
203 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
204 libgnunetreclaim.la \
205 $(top_builddir)/src/service/identity/libgnunetidentity.la \
206 $(GN_LIBINTL)
207
208test_reclaim_attribute_SOURCES = \
209 test_reclaim_attribute.c
210test_reclaim_attribute_LDADD = \
211 $(top_builddir)/src/lib/util/libgnunetutil.la \
212 libgnunetreclaim.la \
213 $(GN_LIBINTL)
214
215gnunet_did_SOURCES = \
216 gnunet-did.c
217gnunet_did_LDADD = \
218 $(top_builddir)/src/lib/util/libgnunetutil.la \
219 $(top_builddir)/src/service/gns/libgnunetgns.la \
220 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
221 $(top_builddir)/src/service/identity/libgnunetidentity.la \
222 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
223 libgnunetdid.la \
224 -ljansson
225
226
227test_did_helper_SOURCES = \
228 test_did_helper.c
229test_did_helper_LDADD = \
230 $(top_builddir)/src/lib/util/libgnunetutil.la \
231 $(top_builddir)/src/service/gns/libgnunetgns.la \
232 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
233 $(top_builddir)/src/service/identity/libgnunetidentity.la \
234 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
235 libgnunetdid.la \
236 -ljansson
237
238check_SCRIPTS = \
239 test_reclaim_attribute.sh \
240 test_reclaim_issue.sh \
241 test_reclaim_consume.sh
242
243check_PROGRAMS = \
244 test_reclaim_attribute \
245 test_did_helper
246
247if ENABLE_TEST_RUN
248 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
249 TESTS = \
250 $(check_SCRIPTS) \
251 $(check_PROGRAMS)
252endif
diff --git a/src/reclaim/did.h b/src/reclaim/did.h
deleted file mode 100644
index ab1b65925..000000000
--- a/src/reclaim/did.h
+++ /dev/null
@@ -1,49 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2022 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#ifndef RECLAIM_DID_H
22#define RECLAIM_DID_H
23
24#define GNUNET_RECLAIM_DID_METHOD_PREFIX "did:gns:"
25
26/**
27 * Create a DID string from an ego in the format
28 * did:gns:\<pubkey\>
29 *
30 * @param ego the Ego to use
31 * @return the DID string
32 */
33char*
34DID_ego_to_did (struct GNUNET_IDENTITY_Ego *ego);
35
36
37/**
38 * Extract the public key from a DID
39 * in the format did:gns:\<pubkey\>
40 *
41 * @param did the DID parse
42 * @param pk where to store the public key
43 * @return GNUNET_OK if successful
44 */
45enum GNUNET_GenericReturnValue
46DID_public_key_from_did (const char* did,
47 struct GNUNET_CRYPTO_PublicKey *pk);
48
49#endif
diff --git a/src/reclaim/did_core.c b/src/reclaim/did_core.c
deleted file mode 100644
index ce3336b91..000000000
--- a/src/reclaim/did_core.c
+++ /dev/null
@@ -1,265 +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/did_core.c
23 * @brief Core functionality for DID
24 * @author Tristan Schwieren
25 */
26
27// TODO: DID documents do not have an expiration date. Still we add one
28// TODO: Store DID document with empty label and own type (maybe DID-Document or JSON??)
29
30#include "platform.h"
31#include "did_core.h"
32
33struct DID_resolve_return
34{
35 DID_resolve_callback *cb;
36 void *cls;
37};
38
39struct DID_action_return
40{
41 DID_action_callback *cb;
42 void *cls;
43};
44
45// ------------------------------------------------ //
46// -------------------- Resolve ------------------- //
47// ------------------------------------------------ //
48
49/**
50 * @brief GNS lookup callback. Calls the given callback function
51 * and gives it the DID Document.
52 * Fails if there is more than one DID record.
53 *
54 * @param cls closure
55 * @param rd_count number of records in rd
56 * @param rd the records in the reply
57 */
58static void
59DID_resolve_gns_lookup_cb (
60 void *cls,
61 uint32_t rd_count,
62 const struct GNUNET_GNSRECORD_Data *rd)
63{
64 char *did_document;
65 DID_resolve_callback *cb = ((struct DID_resolve_return *) cls)->cb;
66 void *cls_did_resolve_cb = ((struct DID_resolve_return *) cls)->cls;
67 free (cls);
68
69 for (int i = 0; i < rd_count; i++) {
70 if (rd[i].record_type != GNUNET_GNSRECORD_TYPE_DID_DOCUMENT)
71 continue;
72 did_document = (char *) rd[i].data;
73 cb (GNUNET_OK, did_document, cls_did_resolve_cb);
74 return;
75 }
76 cb (GNUNET_NO, "DID Document is not a DID_DOCUMENT record\n",
77 cls_did_resolve_cb);
78}
79
80/**
81 * @brief Resolve a DID.
82 * Calls the given callback function with the resolved DID Document and the given closure.
83 * If the did can not be resolved did_document is NULL.
84 *
85 * @param did DID that is resolve
86 */
87enum GNUNET_GenericReturnValue
88DID_resolve (const char *did,
89 struct GNUNET_GNS_Handle *gns_handle,
90 DID_resolve_callback *cont,
91 void *cls)
92{
93 struct GNUNET_CRYPTO_PublicKey pkey;
94
95 // did, gns_handle and cont must me set
96 if ((did == NULL) || (gns_handle == NULL) || (cont == NULL))
97 return GNUNET_NO;
98
99 if (GNUNET_OK != DID_did_to_pkey (did, &pkey))
100 return GNUNET_NO;
101
102 // Create closure for lookup callback
103 struct DID_resolve_return *cls_gns_lookup_cb
104 = malloc (sizeof(struct DID_resolve_return));
105 cls_gns_lookup_cb->cb = cont;
106 cls_gns_lookup_cb->cls = cls;
107
108 GNUNET_GNS_lookup (gns_handle,
109 DID_DOCUMENT_LABEL,
110 &pkey,
111 GNUNET_GNSRECORD_TYPE_DID_DOCUMENT,
112 GNUNET_GNS_LO_DEFAULT,
113 &DID_resolve_gns_lookup_cb,
114 cls_gns_lookup_cb);
115
116 return GNUNET_OK;
117}
118
119// ------------------------------------------------ //
120// -------------------- Create -------------------- //
121// ------------------------------------------------ //
122
123static void
124DID_create_did_store_cb (void *cls,
125 enum GNUNET_ErrorCode ec)
126{
127 DID_action_callback *cb = ((struct DID_action_return *) cls)->cb;
128 void *cls_did_create_cb = ((struct DID_action_return *) cls)->cls;
129 free (cls);
130
131 if (GNUNET_EC_NONE == ec)
132 {
133 cb (GNUNET_OK, (void *) cls_did_create_cb);
134 }
135 else
136 {
137 // TODO: Log emsg. Not writing it to STDOUT
138 printf ("%s\n", GNUNET_ErrorCode_get_hint (ec));
139 cb (GNUNET_NO, (void *) cls_did_create_cb);
140 }
141}
142
143struct DID_create_namestore_lookup_closure
144{
145 const char *did_document;
146 struct GNUNET_TIME_Relative expire_time;
147 struct GNUNET_NAMESTORE_Handle *namestore_handle;
148 struct DID_action_return *ret;
149};
150
151static void
152DID_create_namestore_lookup_cb (void *cls,
153 const struct
154 GNUNET_CRYPTO_PrivateKey *zone,
155 const char *label,
156 unsigned int rd_count,
157 const struct GNUNET_GNSRECORD_Data *rd)
158{
159 struct GNUNET_GNSRECORD_Data record_data;
160 struct GNUNET_CRYPTO_PublicKey pkey;
161
162 const char *did_document
163 = ((struct DID_create_namestore_lookup_closure *) cls)->did_document;
164
165 const struct GNUNET_TIME_Relative expire_time
166 = ((struct DID_create_namestore_lookup_closure *) cls)->expire_time;
167
168 struct GNUNET_NAMESTORE_Handle *namestore_handle
169 = ((struct DID_create_namestore_lookup_closure *) cls)->namestore_handle;
170
171 struct DID_action_return *cls_record_store_cb
172 = ((struct DID_create_namestore_lookup_closure *) cls)->ret;
173
174 free (cls);
175
176 if (rd_count > 0)
177 {
178 printf ("Ego already has a DID Document. Abort.\n");
179 cls_record_store_cb->cb (GNUNET_NO, cls_record_store_cb->cls);
180 }
181 else {
182 // Get public key
183 GNUNET_CRYPTO_key_get_public (zone, &pkey);
184
185 // If no DID Document is given a default one is created
186 if (did_document != NULL)
187 printf (
188 "DID Docuement is read from \"DID-document\" argument (EXPERIMENTAL)\n");
189 else
190 did_document = DID_pkey_to_did_document (&pkey);
191
192 // Create record
193 record_data.data = did_document;
194 record_data.expiration_time = expire_time.rel_value_us;
195 record_data.data_size = strlen (did_document) + 1;
196 record_data.record_type = GNUNET_GNSRECORD_typename_to_number ("TXT"),
197 record_data.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
198
199 // Store record
200 GNUNET_NAMESTORE_records_store (namestore_handle,
201 zone,
202 DID_DOCUMENT_LABEL,
203 1, // FIXME what if GNUNET_GNS_EMPTY_LABEL_AT has records
204 &record_data,
205 &DID_create_did_store_cb,
206 (void *) cls_record_store_cb);
207 }
208}
209
210/**
211 * @brief Creates a DID and saves DID Document in Namestore.
212 *
213 * @param ego ego for which the DID should be created.
214 * @param did_document did_document that should be saved in namestore.
215 * If did_document==NULL -> Default DID document is created.
216 * @param namestore_handle
217 * @param cont callback function
218 * @param cls closure
219 */
220enum GNUNET_GenericReturnValue
221DID_create (const struct GNUNET_IDENTITY_Ego *ego,
222 const char *did_document,
223 const struct GNUNET_TIME_Relative *expire_time,
224 struct GNUNET_NAMESTORE_Handle *namestore_handle,
225 DID_action_callback *cont,
226 void *cls)
227{
228 struct GNUNET_CRYPTO_PublicKey pkey;
229
230 // Ego, namestore_handle and cont must be set
231 if ((ego == NULL) || (namestore_handle == NULL) || (cont == NULL))
232 return GNUNET_NO;
233
234 // Check if ego has EdDSA key
235 GNUNET_IDENTITY_ego_get_public_key ((struct GNUNET_IDENTITY_Ego *) ego,
236 &pkey);
237 if (ntohl (pkey.type) != GNUNET_GNSRECORD_TYPE_EDKEY)
238 {
239 printf ("The EGO has to have an EdDSA key pair\n");
240 return GNUNET_NO;
241 }
242
243 struct DID_action_return *ret
244 = malloc (sizeof(struct DID_action_return));
245 ret->cb = cont;
246 ret->cls = cls;
247
248 struct DID_create_namestore_lookup_closure *cls_name_store_lookup_cb
249 = malloc (sizeof(struct DID_create_namestore_lookup_closure));
250 cls_name_store_lookup_cb->did_document = did_document;
251 cls_name_store_lookup_cb->expire_time = (*expire_time);
252 cls_name_store_lookup_cb->namestore_handle = namestore_handle;
253 cls_name_store_lookup_cb->ret = ret;
254
255 // Check if ego already has a DID Document
256 GNUNET_NAMESTORE_records_lookup (namestore_handle,
257 GNUNET_IDENTITY_ego_get_private_key (ego),
258 DID_DOCUMENT_LABEL,
259 NULL,
260 NULL,
261 DID_create_namestore_lookup_cb,
262 (void *) cls_name_store_lookup_cb);
263
264 return GNUNET_OK;
265}
diff --git a/src/reclaim/did_core.h b/src/reclaim/did_core.h
deleted file mode 100644
index 842424e14..000000000
--- a/src/reclaim/did_core.h
+++ /dev/null
@@ -1,138 +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/did_core.h
23 * @brief Core functionality for GNUNET Decentralized Identifier
24 * @author Tristan Schwieren
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_gns_service.h"
31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_identity_service.h"
33#include "did_helper.h"
34#include "jansson.h"
35
36// #define DID_DOCUMENT_LABEL GNUNET_GNS_EMPTY_LABEL_AT
37#define DID_DOCUMENT_LABEL "didd"
38#define DID_DOCUMENT_DEFAULT_EXPIRATION_TIME "365d"
39
40/**
41 * @brief Signature of a callback function that is called after a did has been resolved.
42 * did_document contains an Error message if DID can not be resolved.
43 * Calls the given callback function with the resolved DID Document and the given closure.
44 * If the did can not be resolved did_document is NULL.
45 * @param status Equals GNUNET_OK if DID Docuemnt has been resolved
46 * @param did_document resolved DID Document
47 * @param cls previsouly given closure
48 */
49typedef void
50 DID_resolve_callback (enum GNUNET_GenericReturnValue status, char *did_document, void *cls);
51
52/**
53 * @brief Signature of a callback function that is called after a did has been removed
54 * status = 0 if action was sucessfull
55 * status = 1 if action failed
56 *
57 * @param status status of the perfermormed action.
58 * @param cls previsouly given closure
59 */
60typedef void
61 DID_action_callback (enum GNUNET_GenericReturnValue status, void *cls);
62
63
64/**
65 * @brief Resolve a DID.
66 * Calls the given callback function with the resolved DID Document and the given closure.
67 * If the did can not be resolved did_document is NULL.
68 *
69 * @param did DID that is resolved
70 * @param gns_handle pointer to gns handle.
71 * @param cont callback function
72 * @param cls closure
73 */
74enum GNUNET_GenericReturnValue
75DID_resolve (const char *did,
76 struct GNUNET_GNS_Handle *gns_handle,
77 DID_resolve_callback *cont,
78 void *cls);
79
80
81/**
82 * @brief Removes the DID Document from namestore.
83 * Ego is not removed.
84 * Calls the callback function with status and the given closure.
85 *
86 * @param ego ego which controlls the DID
87 * @param cfg_handle pointer to configuration handle
88 * @param namestore_handle pointer to namestore handle
89 * @param cont callback function
90 * @param cls closure
91 */
92enum GNUNET_GenericReturnValue
93DID_remove (const struct GNUNET_IDENTITY_Ego *ego,
94 struct GNUNET_CONFIGURATION_Handle *cfg_handle,
95 struct GNUNET_NAMESTORE_Handle *namestore_handle,
96 DID_action_callback *cont,
97 void *cls);
98
99
100/**
101 * @brief Creates a DID and saves DID Document in Namestore.
102 *
103 * @param ego ego for which the DID should be created.
104 * @param did_document did_document that should be saved in namestore.
105 * If did_document==NULL -> Default DID document is created.
106 * @param expire_time
107 * @param namestore_handle
108 * @param cont callback function
109 * @param cls closure
110 */
111enum GNUNET_GenericReturnValue
112DID_create (const struct GNUNET_IDENTITY_Ego *ego,
113 const char *did_document,
114 const struct GNUNET_TIME_Relative *expire_time,
115 struct GNUNET_NAMESTORE_Handle *namestore_handle,
116 DID_action_callback *cont,
117 void *cls);
118
119
120/**
121 * @brief Replace the DID Document of a DID.
122 *
123 * @param ego ego for which the DID Document should be replaced
124 * @param did_document new DID Document
125 * @param cfg_handle pointer to configuration handle
126 * @param identity_handle pointer to configuration handle
127 * @param namestore_handle pointer to namestore handle
128 * @param cont callback function
129 * @param cls closure
130 */
131enum GNUNET_GenericReturnValue
132DID_replace (struct GNUNET_IDENTITY_Ego *ego,
133 char *did_document,
134 const struct GNUNET_CONFIGURATION_Handle *cfg_handle,
135 struct GNUNET_IDENTITY_Handle *identity_handle,
136 struct GNUNET_NAMESTORE_Handle *namestore_handle,
137 DID_action_callback *cont,
138 void *cls);
diff --git a/src/reclaim/did_helper.c b/src/reclaim/did_helper.c
deleted file mode 100644
index 3aac027ee..000000000
--- a/src/reclaim/did_helper.c
+++ /dev/null
@@ -1,203 +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/did_helper.c
23 * @brief helper library for DID related functions
24 * @author Tristan Schwieren
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_namestore_service.h"
29#include "gnunet_gns_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "did_helper.h"
32#include "jansson.h"
33
34#define STR_INDIR(x) #x
35#define STR(x) STR_INDIR (x)
36
37/**
38 * @brief Generate a DID for a given GNUNET public key
39 *
40 * @param pkey
41 * @return char* Returns the DID. Caller must free
42 * TODO: Check if EdDSA
43 */
44char*
45DID_pkey_to_did (struct GNUNET_CRYPTO_PublicKey *pkey)
46{
47 char *pkey_str;
48 char *did_str;
49
50 pkey_str = GNUNET_CRYPTO_public_key_to_string (pkey);
51 GNUNET_asprintf (&did_str, "%s%s",
52 GNUNET_DID_METHOD_PREFIX,
53 pkey_str);
54
55 GNUNET_free (pkey_str);
56 return did_str;
57}
58
59/**
60 * @brief Generate a DID for a given gnunet EGO.
61 * Wrapper around GNUNET_DID_pkey_to_did
62 *
63 * @param ego
64 * @return char* Returns the DID. Caller must free
65 */
66char*
67DID_identity_to_did (struct GNUNET_IDENTITY_Ego *ego)
68{
69 struct GNUNET_CRYPTO_PublicKey pkey;
70
71 GNUNET_IDENTITY_ego_get_public_key (ego, &pkey);
72 return DID_pkey_to_did (&pkey);
73}
74
75/**
76 * @brief Return the public key of a DID
77 */
78enum GNUNET_GenericReturnValue
79DID_did_to_pkey (const char *did, struct GNUNET_CRYPTO_PublicKey *pkey)
80{
81 char pkey_str[MAX_DID_SPECIFIC_IDENTIFIER_LENGTH + 1]; /* 0-term */
82
83 if ((1 != (sscanf (did,
84 GNUNET_DID_METHOD_PREFIX "%"
85 STR (MAX_DID_SPECIFIC_IDENTIFIER_LENGTH)
86 "s", pkey_str))) ||
87 (GNUNET_OK != GNUNET_CRYPTO_public_key_from_string (pkey_str, pkey)))
88 {
89 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not decode given DID: %s\n",
90 did);
91 return GNUNET_NO;
92 }
93
94 return GNUNET_OK;
95}
96
97/**
98 * @brief Convert a base 64 encoded public key to a GNUNET key
99 */
100struct GNUNET_CRYPTO_PublicKey *
101GNUNET_DID_key_convert_multibase_base64_to_gnunet (char *pkey_str)
102{
103 return NULL;
104}
105
106/**
107 * @brief Convert GNUNET key to a base 64 encoded public key
108 */
109char *
110DID_key_convert_gnunet_to_multibase_base64 (struct
111 GNUNET_CRYPTO_PublicKey *
112 pkey)
113{
114 struct GNUNET_CRYPTO_EddsaPublicKey pubkey = pkey->eddsa_key;
115
116 // This is how to convert out pubkeys to W3c Ed25519-2020 multibase (base64url no padding)
117 char *pkey_base_64;
118 char *pkey_multibase;
119 char pkx[34];
120
121 pkx[0] = 0xed;
122 pkx[1] = 0x01;
123 memcpy (pkx + 2, &pubkey, sizeof (pubkey));
124 GNUNET_STRINGS_base64url_encode (pkx, sizeof (pkx), &pkey_base_64);
125 GNUNET_asprintf (&pkey_multibase, "u%s", pkey_base_64);
126
127 GNUNET_free (pkey_base_64);
128 return pkey_multibase;
129}
130
131/**
132 * @brief Create a did generate did object
133 *
134 * @param pkey
135 * @return void* Return pointer to the DID Document
136 */
137char *
138DID_pkey_to_did_document (struct GNUNET_CRYPTO_PublicKey *pkey)
139{
140
141 /* FIXME-MSC: This is effectively creating a DID Document default template for
142 * the initial document.
143 * Maybe this can be refactored to generate such a template for an identity?
144 * Even if higher layers add/modify it, there should probably still be a
145 * GNUNET_DID_document_template_from_identity()
146 */
147
148 char *did_str;
149 char *verify_id_str;
150 char *pkey_multibase_str;
151 char *didd_str;
152 json_t *didd_json;
153
154 did_str = DID_pkey_to_did (pkey);
155 GNUNET_asprintf (&verify_id_str, "%s#key-1", did_str);
156
157 pkey_multibase_str = DID_key_convert_gnunet_to_multibase_base64 (pkey);
158
159 didd_json = json_pack (
160 "{s:[ss], s:s, s:[{s:s, s:s, s:s, s:s}], s:[s], s:[s]}",
161 "@context",
162 "https://www.w3.org/ns/did/v1",
163 "https://w3id.org/security/suites/ed25519-2020/v1",
164 "id",
165 did_str,
166 "verificationMethod",
167 "id",
168 verify_id_str,
169 "type",
170 "Ed25519VerificationKey2020",
171 "controller",
172 did_str,
173 "publicKeyMultibase",
174 pkey_multibase_str,
175 "authentication",
176 "#key-1",
177 "assertionMethod",
178 "#key-1");
179
180 // Encode DID Document as JSON string
181 didd_str = json_dumps (didd_json, JSON_INDENT (2));
182
183 // Free
184 GNUNET_free (did_str);
185 GNUNET_free (verify_id_str);
186 GNUNET_free (pkey_multibase_str);
187 json_decref (didd_json);
188
189 return didd_str;
190}
191
192/**
193 * @brief Generate the default DID document for a GNUNET ego
194 * Wrapper around GNUNET_DID_pkey_to_did_document
195 */
196char *
197DID_identity_to_did_document (struct GNUNET_IDENTITY_Ego *ego)
198{
199 struct GNUNET_CRYPTO_PublicKey pkey;
200
201 GNUNET_IDENTITY_ego_get_public_key (ego, &pkey);
202 return DID_pkey_to_did (&pkey);
203} \ No newline at end of file
diff --git a/src/reclaim/did_helper.h b/src/reclaim/did_helper.h
deleted file mode 100644
index d61992c68..000000000
--- a/src/reclaim/did_helper.h
+++ /dev/null
@@ -1,74 +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/did_helper.h
23 * @brief helper library for DID related functions
24 * @author Tristan Schwieren
25 */
26
27#define GNUNET_DID_METHOD_PREFIX "did:gns:"
28#define MAX_DID_SPECIFIC_IDENTIFIER_LENGTH 59
29
30/**
31 * @brief Return a DID for a given GNUNET public key
32 */
33char *
34DID_pkey_to_did (struct GNUNET_CRYPTO_PublicKey *pkey);
35
36/**
37 * @brief Generate a DID for a given gnunet EGO
38 *
39 * @param ego
40 * @return char * Returns the DID. Caller must free
41 */
42char *
43DID_identity_to_did (struct GNUNET_IDENTITY_Ego *ego);
44
45/**
46 * @brief Return the public key of a DID
47 */
48enum GNUNET_GenericReturnValue
49DID_did_to_pkey (const char *did, struct GNUNET_CRYPTO_PublicKey *pkey);
50
51// /**
52// * @brief Convert a base 64 encoded public key to a GNUNET key
53// */
54// struct GNUNET_CRYPTO_PublicKey *
55// GNUNET_DID_key_convert_multibase_base64_to_gnunet(char *);
56
57/**
58 * @brief Convert GNUNET key to a base 64 encoded public key
59 */
60char *
61DID_key_convert_gnunet_to_multibase_base64 (struct
62 GNUNET_CRYPTO_PublicKey *);
63
64/**
65 * @brief Generate the default DID document for a GNUNET public key
66 */
67char *
68DID_pkey_to_did_document (struct GNUNET_CRYPTO_PublicKey *pkey);
69
70/**
71 * @brief Generate the default DID document for a GNUNET ego
72 */
73char *
74DID_identity_to_did_document (struct GNUNET_IDENTITY_Ego *ego);
diff --git a/src/reclaim/did_misc.c b/src/reclaim/did_misc.c
deleted file mode 100644
index 32b127b2b..000000000
--- a/src/reclaim/did_misc.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2022 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/did_misc.c
24 * @brief Helper functions for DIDs
25 *
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_identity_service.h"
30#include "jansson.h"
31#include "did.h"
32
33char*
34DID_ego_to_did (struct GNUNET_IDENTITY_Ego *ego)
35{
36 struct GNUNET_CRYPTO_PublicKey pkey; // Get Public key
37 char *pkey_str;
38 char *did_str;
39 size_t pkey_len;
40
41 GNUNET_IDENTITY_ego_get_public_key (ego, &pkey);
42
43 pkey_str = GNUNET_CRYPTO_public_key_to_string (&pkey);
44 GNUNET_asprintf (&did_str, "%s%s",
45 GNUNET_RECLAIM_DID_METHOD_PREFIX,
46 pkey_str);
47
48 GNUNET_free (pkey_str);
49 return did_str;
50}
51
52enum GNUNET_GenericReturnValue
53DID_public_key_from_did (const char* did,
54 struct GNUNET_CRYPTO_PublicKey *pk)
55{
56 /* FIXME-MSC: I suggest introducing a
57 * #define MAX_DID_LENGTH <something>
58 * here and use it for parsing
59 */
60 char pkey_str[59];
61
62 if ((1 != (sscanf (did, GNUNET_RECLAIM_DID_METHOD_PREFIX"%58s", pkey_str))) ||
63 (GNUNET_OK != GNUNET_CRYPTO_public_key_from_string (pkey_str, pk)))
64 {
65 return GNUNET_SYSERR;
66 }
67 return GNUNET_OK;
68}
69
70
diff --git a/src/reclaim/gnunet-did.c b/src/reclaim/gnunet-did.c
deleted file mode 100644
index e88a3671e..000000000
--- a/src/reclaim/gnunet-did.c
+++ /dev/null
@@ -1,647 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2022 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 * FIXME: Do we only want to handle EdDSA identities?
23 * TODO: Own GNS record type
24 * TODO: Fix overwrite of records in @ if present look for other with same sub
25 * TODO. Tests
26 * TODO: Move constants to did.h
27 * FIXME: Remove and lookup require differnt representations (did vs egoname)
28 */
29
30/**
31 * @author Tristan Schwieren
32 * @file src/did/gnunet-did.c
33 * @brief DID Method Wrapper
34 *
35 */
36#include "platform.h"
37#include "gnunet_util_lib.h"
38#include "gnunet_namestore_service.h"
39#include "gnunet_identity_service.h"
40#include "gnunet_gns_service.h"
41#include "gnunet_gnsrecord_lib.h"
42#include "did_helper.h"
43#include "did_core.h"
44#include "jansson.h"
45
46#define GNUNET_DID_DEFAULT_DID_DOCUMENT_EXPIRATION_TIME "1d"
47
48/**
49 * return value
50 */
51static int ret;
52
53/**
54 * Replace DID Document Flag
55 */
56static int replace;
57
58/**
59 * Remove DID Document Flag
60 */
61static int remove_did;
62
63/**
64 * Get DID Documement for DID Flag
65 */
66static int get;
67
68/**
69 * Create DID Document Flag
70 */
71static int create;
72
73/**
74 * Show DID for Ego Flag
75 */
76static int show;
77
78/**
79 * Show DID for Ego Flag
80 */
81static int show_all;
82
83/**
84 * DID Attribut String
85 */
86static char *did;
87
88/**
89 * DID Document Attribut String
90 */
91static char *didd;
92
93/**
94 * Ego Attribut String
95 */
96static char *egoname;
97
98/**
99 * DID Document expiration Date Attribut String
100 */
101static char *expire;
102
103/*
104 * Handle to the GNS service
105 */
106static struct GNUNET_GNS_Handle *gns_handle;
107
108/*
109 * Handle to the NAMESTORE service
110 */
111static struct GNUNET_NAMESTORE_Handle *namestore_handle;
112
113/*
114 * Handle to the IDENTITY service
115 */
116static struct GNUNET_IDENTITY_Handle *identity_handle;
117
118
119/*
120 * The configuration
121 */
122const static struct GNUNET_CONFIGURATION_Handle *my_cfg;
123
124/**
125 * Give ego exists
126 */
127static int ego_exists = 0;
128
129/**
130 * @brief Disconnect and shutdown
131 * @param cls closure
132 */
133static void
134cleanup (void *cls)
135{
136 if (NULL != gns_handle)
137 GNUNET_GNS_disconnect (gns_handle);
138 if (NULL != namestore_handle)
139 GNUNET_NAMESTORE_disconnect (namestore_handle);
140 if (NULL != identity_handle)
141 GNUNET_IDENTITY_disconnect (identity_handle);
142
143 GNUNET_free (did);
144 GNUNET_free (didd);
145 GNUNET_free (egoname);
146 GNUNET_free (expire);
147
148 GNUNET_SCHEDULER_shutdown ();
149}
150
151/**
152 * @brief GNS lookup callback. Prints the DID Document to standard out.
153 * Fails if there is more than one DID record.
154 *
155 * @param cls closure
156 * @param rd_count number of records in @a rd
157 * @param rd the records in the reply
158 */
159static void
160print_did_document (
161 enum GNUNET_GenericReturnValue status,
162 char *did_document,
163 void *cls
164 )
165{
166 if (GNUNET_OK == status)
167 printf ("%s\n", did_document);
168 else
169 printf ("An error occured: %s\n", did_document);
170
171 GNUNET_SCHEDULER_add_now (cleanup, NULL);
172 ret = 0;
173 return;
174}
175
176/**
177 * @brief Resolve a DID given by the user.
178 */
179static void
180resolve_did ()
181{
182
183 if (did == NULL)
184 {
185 printf ("Set DID option to resolve DID\n");
186 GNUNET_SCHEDULER_add_now (cleanup, NULL);
187 ret = 1;
188 return;
189 }
190
191 if (GNUNET_OK != DID_resolve (did, gns_handle, print_did_document, NULL))
192 {
193 printf ("An error occured while resoling the DID\n");
194 GNUNET_SCHEDULER_add_now (cleanup, NULL);
195 ret = 0;
196 return;
197 }
198}
199
200
201/**
202 * @brief Signature of a callback function that is called after a did has been removed
203 */
204typedef void
205(*remove_did_document_callback) (void *cls);
206
207/**
208 * @brief A Structure containing a cont and cls. Can be passed as a cls to a callback function
209 *
210 */
211struct Event
212{
213 remove_did_document_callback cont;
214 void *cls;
215};
216
217/**
218 * @brief Implements the GNUNET_NAMESTORE_ContinuationWithStatus
219 * Calls the callback function and cls in the event struct
220 *
221 * @param cls closure containing the event struct
222 * @param success
223 * @param emgs
224 */
225static void
226remove_did_document_namestore_cb (void *cls, enum GNUNET_ErrorCode ec)
227{
228 struct Event *event;
229
230 if (GNUNET_EC_NONE == ec)
231 {
232 event = (struct Event *) cls;
233
234 if (event->cont != NULL)
235 {
236 event->cont (event->cls);
237 free (event);
238 }
239 else {
240 free (event);
241 GNUNET_SCHEDULER_add_now (cleanup, NULL);
242 ret = 0;
243 return;
244 }
245 }
246 else {
247 printf ("Something went wrong when deleting the DID Document\n");
248
249 printf ("%s\n", GNUNET_ErrorCode_get_hint (ec));
250
251 GNUNET_SCHEDULER_add_now (cleanup, NULL);
252 ret = 0;
253 return;
254 }
255}
256
257/**
258 * @brief Callback called after the ego has been locked up
259 *
260 * @param cls closure
261 * @param ego the ego returned by the identity service
262 */
263static void
264remove_did_document_ego_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
265{
266 const struct GNUNET_CRYPTO_PrivateKey *skey =
267 GNUNET_IDENTITY_ego_get_private_key (ego);
268
269 GNUNET_NAMESTORE_records_store (namestore_handle,
270 skey,
271 GNUNET_GNS_EMPTY_LABEL_AT,
272 0,
273 NULL,
274 &remove_did_document_namestore_cb,
275 cls);
276}
277
278/**
279 * @brief Remove a DID Document
280 */
281static void
282remove_did_document (remove_did_document_callback cont, void *cls)
283{
284 struct Event *event;
285
286 if (egoname == NULL)
287 {
288 printf ("Remove requieres an ego option\n");
289 GNUNET_SCHEDULER_add_now (cleanup, NULL);
290 ret = 1;
291 return;
292 }
293 else {
294 event = malloc (sizeof(*event));
295 event->cont = cont;
296 event->cls = cls;
297
298 GNUNET_IDENTITY_ego_lookup (my_cfg,
299 egoname,
300 &remove_did_document_ego_lookup_cb,
301 (void *) event);
302 }
303}
304
305// Needed because create_did_ego_lookup_cb() and
306// create_did_ego_create_cb() can call each other
307static void create_did_ego_lockup_cb ();
308
309/**
310 * @brief Create a DID(-Document). Called after DID has been created
311 * Prints status and the DID.
312 *
313 */
314static void
315create_did_cb (enum GNUNET_GenericReturnValue status, void *cls)
316{
317 if (GNUNET_OK == status)
318 {
319 printf ("DID has been created.\n%s\n", (char *) cls);
320 free (cls);
321 ret = 0;
322 }
323 else
324 {
325 printf ("An error occured while creating the DID.\n");
326 ret = 1;
327 }
328
329 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
330 return;
331}
332
333/**
334 * @brief Create a DID(-Document) - Called after a new Identity has been created.
335 */
336static void
337create_did_ego_create_cb (void *cls,
338 const struct GNUNET_CRYPTO_PrivateKey *pk,
339 enum GNUNET_ErrorCode ec)
340{
341 if (GNUNET_EC_NONE != ec)
342 {
343 printf ("%s\n", GNUNET_ErrorCode_get_hint (ec));
344 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
345 ret = 1;
346 return;
347 }
348
349 GNUNET_IDENTITY_ego_lookup (my_cfg,
350 egoname,
351 &create_did_ego_lockup_cb,
352 NULL);
353}
354
355/**
356 * @brief Create a DID(-Document). Called after ego lookup
357 *
358 */
359static void
360create_did_ego_lockup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
361{
362 if (ego == NULL)
363 {
364 // If Ego was not found. Create new one first
365 printf ("Ego was not found. Creating new one.\n");
366 GNUNET_IDENTITY_create (identity_handle,
367 egoname,
368 NULL,
369 GNUNET_PUBLIC_KEY_TYPE_EDDSA,
370 &create_did_ego_create_cb,
371 egoname);
372 }
373 else
374 {
375 char *did = DID_identity_to_did (ego);
376 void *cls = malloc (strlen (did) + 1);
377 struct GNUNET_TIME_Relative expire_relative;
378
379 if (expire == NULL)
380 {
381 GNUNET_STRINGS_fancy_time_to_relative (
382 DID_DOCUMENT_DEFAULT_EXPIRATION_TIME, &expire_relative);
383 }
384 else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (expire,
385 &
386 expire_relative))
387 {
388 printf ("Failed to read given expiration time\n");
389 GNUNET_SCHEDULER_add_now (cleanup, NULL);
390 ret = 1;
391 return;
392 }
393
394 strcpy (cls, did);
395 // TODO: Add DID_document argument
396 if (GNUNET_OK != DID_create (ego,
397 NULL,
398 &expire_relative,
399 namestore_handle,
400 create_did_cb,
401 cls))
402 {
403 printf ("An error occured while creating the DID.\n");
404 ret = 1;
405 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
406 return;
407 }
408 }
409}
410
411/**
412 * @brief Create a DID(-Document).
413 *
414 */
415static void
416create_did ()
417{
418 // Ego name to be set
419 if (egoname == NULL)
420 {
421 printf ("Set the Ego argument to create a new DID(-Document)\n");
422 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
423 ret = 1;
424 return;
425 }
426
427 GNUNET_IDENTITY_ego_lookup (my_cfg,
428 egoname,
429 &create_did_ego_lockup_cb,
430 NULL);
431}
432
433
434/**
435 * @brief Replace a DID Docuemnt. Callback function after ego lockup
436 *
437 * @param cls
438 * @param ego
439 */
440static void
441replace_did_document_ego_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
442{
443 // create_did_store (didd, ego);
444}
445
446/**
447 * @brief Replace a DID Document. Callback functiona after remove
448 *
449 * @param cls
450 */
451static void
452replace_did_document_remove_cb (void *cls)
453{
454 GNUNET_IDENTITY_ego_lookup (my_cfg,
455 egoname,
456 &replace_did_document_ego_lookup_cb,
457 NULL);
458}
459
460/**
461 * @brief Replace a DID Docuemnt
462 *
463 */
464static void
465replace_did_document ()
466{
467 if ((didd != NULL) && (expire != NULL))
468 {
469 remove_did_document (&replace_did_document_remove_cb, NULL);
470 }
471 else {
472 printf (
473 "Set the DID Document and expiration time argument to replace the DID Document\n");
474 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
475 ret = 1;
476 return;
477 }
478}
479
480static void
481post_ego_iteration (void *cls)
482{
483 // TODO: Check that only one argument is set
484
485 if (1 == replace)
486 {
487 replace_did_document ();
488 }
489 else if (1 == get)
490 {
491 resolve_did ();
492 }
493 else if (1 == remove_did)
494 {
495 remove_did_document (NULL, NULL);
496 }
497 else if (1 == create)
498 {
499 create_did ();
500 }
501 else {
502 // No Argument found
503 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
504 return;
505 }
506}
507
508static void
509process_dids (void *cls, struct GNUNET_IDENTITY_Ego *ego,
510 void **ctx, const char*name)
511{
512 char *did_str;
513
514 if (ego == NULL)
515 {
516 if (1 == ego_exists)
517 {
518 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
519 return;
520 }
521 GNUNET_SCHEDULER_add_now (&post_ego_iteration, NULL);
522 return;
523 }
524
525 if (1 == show_all)
526 {
527 did_str = DID_identity_to_did (ego);
528 printf ("%s:\n\t%s\n", name, did_str);
529 GNUNET_free (did_str);
530 return;
531 }
532 if (1 == show)
533 {
534 if (0 == strncmp (name, egoname, strlen (egoname)))
535 {
536 did_str = DID_identity_to_did (ego);
537 printf ("%s:\n\t%s\n", name, did_str);
538 GNUNET_free (did_str);
539 return;
540 }
541 }
542}
543
544
545
546static void
547run (void *cls,
548 char *const *args,
549 const char *cfgfile,
550 const struct GNUNET_CONFIGURATION_Handle *c)
551{
552 gns_handle = GNUNET_GNS_connect (c);
553 namestore_handle = GNUNET_NAMESTORE_connect (c);
554 my_cfg = c;
555
556 // check if GNS_handle could connect
557 if (gns_handle == NULL)
558 {
559 ret = 1;
560 return;
561 }
562
563 // check if NAMESTORE_handle could connect
564 if (namestore_handle == NULL)
565 {
566 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
567 ret = 1;
568 return;
569 }
570
571 identity_handle = GNUNET_IDENTITY_connect (c, &process_dids, NULL);
572 if (identity_handle == NULL)
573 {
574 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
575 ret = 1;
576 return;
577 }
578}
579
580int
581main (int argc, char *const argv[])
582{
583 struct GNUNET_GETOPT_CommandLineOption options[] = {
584 GNUNET_GETOPT_option_flag ('C',
585 "create",
586 gettext_noop (
587 "Create a DID Document and display its DID"),
588 &create),
589 GNUNET_GETOPT_option_flag ('g',
590 "get",
591 gettext_noop (
592 "Get the DID Document associated with the given DID"),
593 &get),
594 GNUNET_GETOPT_option_flag ('r',
595 "remove",
596 gettext_noop (
597 "Remove the DID"),
598 &remove_did),
599 GNUNET_GETOPT_option_flag ('R',
600 "replace",
601 gettext_noop ("Replace the DID Document."),
602 &replace),
603 GNUNET_GETOPT_option_flag ('s',
604 "show",
605 gettext_noop ("Show the DID for a given ego"),
606 &show),
607 GNUNET_GETOPT_option_flag ('A',
608 "show-all",
609 gettext_noop ("Show egos with DIDs"),
610 &show_all),
611 GNUNET_GETOPT_option_string ('d',
612 "did",
613 "DID",
614 gettext_noop (
615 "The Decentralized Identity (DID)"),
616 &did),
617 GNUNET_GETOPT_option_string ('D',
618 "did-document",
619 "JSON",
620 gettext_noop (
621 "The DID Document to store in GNUNET"),
622 &didd),
623 GNUNET_GETOPT_option_string ('e',
624 "ego",
625 "EGO",
626 gettext_noop ("The name of the EGO"),
627 &egoname),
628 GNUNET_GETOPT_option_string ('t',
629 "expiration-time",
630 "TIME",
631 gettext_noop (
632 "The time until the DID Document is going to expire (e.g. 5d)"),
633 &expire),
634 GNUNET_GETOPT_OPTION_END
635 };
636
637 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
638 argv,
639 "gnunet-did",
640 "Manage Decentralized Identities (DIDs)",
641 options,
642 &run,
643 NULL))
644 return 1;
645 else
646 return ret;
647}
diff --git a/src/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c
deleted file mode 100644
index efb2c2902..000000000
--- a/src/reclaim/gnunet-reclaim.c
+++ /dev/null
@@ -1,928 +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_CRYPTO_PrivateKey *pkey;
156
157/**
158 * rp public key
159 */
160static struct GNUNET_CRYPTO_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 {
222 GNUNET_RECLAIM_attribute_list_destroy (attr_list);
223 attr_list = NULL;
224 }
225 if (NULL != attr_to_delete)
226 GNUNET_free (attr_to_delete);
227 if (NULL == credential_type)
228 GNUNET_free (credential_type);
229}
230
231
232static void
233ticket_issue_cb (void *cls,
234 const struct GNUNET_RECLAIM_Ticket *ticket,
235 const struct GNUNET_RECLAIM_PresentationList *presentations)
236{
237 char *ticket_str;
238
239 reclaim_op = NULL;
240 if (NULL != ticket)
241 {
242 ticket_str =
243 GNUNET_STRINGS_data_to_string_alloc (ticket,
244 sizeof(
245 struct GNUNET_RECLAIM_Ticket));
246 printf ("%s\n", ticket_str);
247 GNUNET_free (ticket_str);
248 }
249 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
250}
251
252
253static void
254store_cont (void *cls, int32_t success, const char *emsg)
255{
256 reclaim_op = NULL;
257 if (GNUNET_SYSERR == success)
258 {
259 fprintf (stderr, "%s\n", emsg);
260 }
261 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
262}
263
264
265static void
266process_attrs (void *cls,
267 const struct GNUNET_CRYPTO_PublicKey *identity,
268 const struct GNUNET_RECLAIM_Attribute *attr,
269 const struct GNUNET_RECLAIM_Presentation *presentation)
270{
271 char *value_str;
272 char *id;
273 const char *attr_type;
274
275 if (NULL == identity)
276 {
277 reclaim_op = NULL;
278 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
279 return;
280 }
281 if (NULL == attr)
282 {
283 ret = 1;
284 return;
285 }
286 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
287 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
288 value_str = NULL;
289 if (NULL == presentation)
290 {
291 value_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
292 attr->data,
293 attr->data_size);
294 }
295 else
296 {
297 struct GNUNET_RECLAIM_AttributeListEntry *ale;
298 struct GNUNET_RECLAIM_AttributeList *al
299 = GNUNET_RECLAIM_presentation_get_attributes (presentation);
300
301 for (ale = al->list_head; NULL != ale; ale = ale->next)
302 {
303 if (0 != strncmp (attr->data, ale->attribute->name, attr->data_size))
304 continue;
305 value_str
306 = GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
307 ale->attribute->data,
308 ale->attribute->data_size);
309 break;
310 }
311 }
312 fprintf (stdout,
313 "Name: %s; Value: %s (%s); Flag %u; ID: %s %s\n",
314 attr->name,
315 (NULL != value_str) ? value_str : "???",
316 attr_type,
317 attr->flag,
318 id,
319 (NULL == presentation) ? "" : "(ATTESTED)");
320 GNUNET_free (value_str);
321 GNUNET_free (id);
322}
323
324
325static void
326ticket_iter_err (void *cls)
327{
328 ticket_iterator = NULL;
329 fprintf (stderr, "Failed to iterate over tickets\n");
330 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
331}
332
333
334static void
335ticket_iter_fin (void *cls)
336{
337 ticket_iterator = NULL;
338 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
339}
340
341
342static void
343ticket_iter (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
344{
345 char *aud;
346 char *ref;
347 char *tkt;
348
349 aud =
350 GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
351 sizeof(struct
352 GNUNET_CRYPTO_PublicKey));
353 ref = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
354 tkt =
355 GNUNET_STRINGS_data_to_string_alloc (ticket,
356 sizeof(struct GNUNET_RECLAIM_Ticket));
357 fprintf (stdout, "Ticket: %s | ID: %s | Audience: %s\n", tkt, ref, aud);
358 GNUNET_free (aud);
359 GNUNET_free (ref);
360 GNUNET_free (tkt);
361 GNUNET_RECLAIM_ticket_iteration_next (ticket_iterator);
362}
363
364
365static void
366iter_error (void *cls)
367{
368 attr_iterator = NULL;
369 cred_iterator = NULL;
370 fprintf (stderr, "Failed\n");
371
372 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
373}
374
375
376static void
377timeout_task (void *cls)
378{
379 timeout = NULL;
380 ret = 1;
381 fprintf (stderr, "Timeout\n");
382 if (NULL == cleanup_task)
383 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
384}
385
386
387static void
388process_rvk (void *cls, int success, const char *msg)
389{
390 reclaim_op = NULL;
391 if (GNUNET_OK != success)
392 {
393 fprintf (stderr, "Revocation failed.\n");
394 ret = 1;
395 }
396 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
397}
398
399
400static void
401process_delete (void *cls, int success, const char *msg)
402{
403 reclaim_op = NULL;
404 if (GNUNET_OK != success)
405 {
406 fprintf (stderr, "Deletion failed.\n");
407 ret = 1;
408 }
409 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
410}
411
412
413static void
414iter_finished (void *cls)
415{
416 char *data;
417 size_t data_size;
418 int type;
419
420 attr_iterator = NULL;
421 if (list)
422 {
423 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
424 return;
425 }
426
427 if (issue_attrs)
428 {
429 reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle,
430 pkey,
431 &rp_key,
432 attr_list,
433 &ticket_issue_cb,
434 NULL);
435 return;
436 }
437 if (consume_ticket)
438 {
439 reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle,
440 pkey,
441 &ticket,
442 &process_attrs,
443 NULL);
444 timeout = GNUNET_SCHEDULER_add_delayed (
445 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
446 &timeout_task,
447 NULL);
448 return;
449 }
450 if (revoke_ticket)
451 {
452 reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle,
453 pkey,
454 &ticket,
455 &process_rvk,
456 NULL);
457 return;
458 }
459 if (attr_delete)
460 {
461 if (NULL == attr_to_delete)
462 {
463 fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
464 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
465 return;
466 }
467 reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle,
468 pkey,
469 attr_to_delete,
470 &process_delete,
471 NULL);
472 return;
473 }
474 if (attr_name)
475 {
476 if (NULL == type_str)
477 type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING;
478 else
479 type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
480
481 GNUNET_assert (GNUNET_SYSERR !=
482 GNUNET_RECLAIM_attribute_string_to_value (type,
483 attr_value,
484 (void **) &data,
485 &data_size));
486 if (NULL != claim)
487 {
488 claim->type = type;
489 claim->data = data;
490 claim->data_size = data_size;
491 }
492 else
493 {
494 claim =
495 GNUNET_RECLAIM_attribute_new (attr_name, NULL, type, data, data_size);
496 }
497 if (NULL != credential_id)
498 {
499 claim->credential = credential;
500 }
501 reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
502 pkey,
503 claim,
504 &exp_interval,
505 &store_cont,
506 NULL);
507 GNUNET_free (data);
508 GNUNET_free (claim);
509 return;
510 }
511 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
512}
513
514
515static void
516iter_cb (void *cls,
517 const struct GNUNET_CRYPTO_PublicKey *identity,
518 const struct GNUNET_RECLAIM_Attribute *attr)
519{
520 struct GNUNET_RECLAIM_AttributeListEntry *le;
521 char *attrs_tmp;
522 char *attr_str;
523 char *label;
524 char *id;
525 const char *attr_type;
526
527 if ((NULL != attr_name) && (NULL == claim))
528 {
529 if (0 == strcasecmp (attr_name, attr->name))
530 {
531 claim = GNUNET_RECLAIM_attribute_new (attr->name,
532 &attr->credential,
533 attr->type,
534 attr->data,
535 attr->data_size);
536 claim->id = attr->id;
537 }
538 }
539 else if (issue_attrs)
540 {
541 attrs_tmp = GNUNET_strdup (issue_attrs);
542 attr_str = strtok (attrs_tmp, ",");
543 while (NULL != attr_str)
544 {
545 if (0 != strcasecmp (attr_str, attr->name))
546 {
547 attr_str = strtok (NULL, ",");
548 continue;
549 }
550 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
551 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
552 &attr->credential,
553 attr->type,
554 attr->data,
555 attr->data_size);
556 le->attribute->flag = attr->flag;
557 le->attribute->id = attr->id;
558 GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
559 attr_list->list_tail,
560 le);
561 break;
562 }
563 GNUNET_free (attrs_tmp);
564 }
565 else if (attr_delete && (NULL == attr_to_delete))
566 {
567 label = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
568 if (0 == strcasecmp (attr_delete, label))
569 {
570 attr_to_delete = GNUNET_RECLAIM_attribute_new (attr->name,
571 &attr->credential,
572 attr->type,
573 attr->data,
574 attr->data_size);
575 attr_to_delete->id = attr->id;
576 }
577 GNUNET_free (label);
578 }
579 else if (list)
580 {
581 attr_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
582 attr->data,
583 attr->data_size);
584 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
585 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
586 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->credential))
587 {
588 fprintf (stdout,
589 "%s: ``%s'' (%s); ID: %s\n",
590 attr->name,
591 attr_str,
592 attr_type,
593 id);
594 }
595 else
596 {
597 char *cred_id =
598 GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
599 sizeof(attr->credential));
600 fprintf (stdout,
601 "%s: ``%s'' in credential presentation `%s' (%s); ID: %s\n",
602 attr->name,
603 attr_str,
604 cred_id,
605 attr_type,
606 id);
607 GNUNET_free (cred_id);
608
609 }
610 GNUNET_free (id);
611 }
612 GNUNET_RECLAIM_get_attributes_next (attr_iterator);
613}
614
615
616static void
617cred_iter_finished (void *cls)
618{
619 cred_iterator = NULL;
620
621 // Add new credential
622 if ((NULL != credential_name) &&
623 (NULL != attr_value))
624 {
625 enum GNUNET_RECLAIM_CredentialType ctype =
626 GNUNET_RECLAIM_credential_typename_to_number (credential_type);
627 struct GNUNET_RECLAIM_Credential *credential =
628 GNUNET_RECLAIM_credential_new (credential_name,
629 ctype,
630 attr_value,
631 strlen (attr_value));
632 reclaim_op = GNUNET_RECLAIM_credential_store (reclaim_handle,
633 pkey,
634 credential,
635 &exp_interval,
636 store_cont,
637 NULL);
638 return;
639
640 }
641 if (list_credentials)
642 {
643 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
644 return;
645 }
646 attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle,
647 pkey,
648 &iter_error,
649 NULL,
650 &iter_cb,
651 NULL,
652 &iter_finished,
653 NULL);
654
655}
656
657
658static void
659cred_iter_cb (void *cls,
660 const struct GNUNET_CRYPTO_PublicKey *identity,
661 const struct GNUNET_RECLAIM_Credential *cred)
662{
663 char *cred_str;
664 char *attr_str;
665 char *id;
666 const char *cred_type;
667 struct GNUNET_RECLAIM_AttributeListEntry *ale;
668
669 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&credential,
670 &cred->id))
671 credential_exists = GNUNET_YES;
672 if (list_credentials)
673 {
674 cred_str = GNUNET_RECLAIM_credential_value_to_string (cred->type,
675 cred->data,
676 cred->data_size);
677 cred_type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
678 id = GNUNET_STRINGS_data_to_string_alloc (&cred->id, sizeof(cred->id));
679 fprintf (stdout,
680 "%s: ``%s'' (%s); ID: %s\n",
681 cred->name,
682 cred_str,
683 cred_type,
684 id);
685 struct GNUNET_RECLAIM_AttributeList *attrs =
686 GNUNET_RECLAIM_credential_get_attributes (cred);
687 if (NULL != attrs)
688 {
689 fprintf (stdout,
690 "\t Attributes:\n");
691 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
692 {
693 attr_str = GNUNET_RECLAIM_attribute_value_to_string (
694 ale->attribute->type,
695 ale->attribute->data,
696 ale->attribute->data_size);
697 fprintf (stdout,
698 "\t %s: %s\n", ale->attribute->name, attr_str);
699 GNUNET_free (attr_str);
700 }
701 GNUNET_RECLAIM_attribute_list_destroy (attrs);
702 }
703 GNUNET_free (id);
704 }
705 GNUNET_RECLAIM_get_credentials_next (cred_iterator);
706}
707
708
709static void
710start_process ()
711{
712 if (NULL == pkey)
713 {
714 fprintf (stderr, "Ego %s not found\n", ego_name);
715 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
716 return;
717 }
718 if (NULL == credential_type)
719 credential_type = GNUNET_strdup ("JWT");
720 credential = GNUNET_RECLAIM_ID_ZERO;
721 if (NULL != credential_id)
722 GNUNET_STRINGS_string_to_data (credential_id,
723 strlen (credential_id),
724 &credential, sizeof(credential));
725 credential_exists = GNUNET_NO;
726 if (list_tickets)
727 {
728 ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (reclaim_handle,
729 pkey,
730 &ticket_iter_err,
731 NULL,
732 &ticket_iter,
733 NULL,
734 &ticket_iter_fin,
735 NULL);
736 return;
737 }
738
739 if ((NULL != rp) &&
740 (GNUNET_OK !=
741 GNUNET_CRYPTO_public_key_from_string (rp, &rp_key)) )
742 {
743 fprintf (stderr, "%s is not a public key!\n", rp);
744 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
745 return;
746 }
747 if (NULL != consume_ticket)
748 GNUNET_STRINGS_string_to_data (consume_ticket,
749 strlen (consume_ticket),
750 &ticket,
751 sizeof(struct GNUNET_RECLAIM_Ticket));
752 if (NULL != revoke_ticket)
753 GNUNET_STRINGS_string_to_data (revoke_ticket,
754 strlen (revoke_ticket),
755 &ticket,
756 sizeof(struct GNUNET_RECLAIM_Ticket));
757
758 attr_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
759 claim = NULL;
760 cred_iterator = GNUNET_RECLAIM_get_credentials_start (reclaim_handle,
761 pkey,
762 &iter_error,
763 NULL,
764 &cred_iter_cb,
765 NULL,
766 &cred_iter_finished,
767 NULL);
768
769}
770
771
772static int init = GNUNET_YES;
773
774static void
775ego_cb (void *cls,
776 struct GNUNET_IDENTITY_Ego *ego,
777 void **ctx,
778 const char *name)
779{
780 if (NULL == name)
781 {
782 if (GNUNET_YES == init)
783 {
784 init = GNUNET_NO;
785 start_process ();
786 }
787 return;
788 }
789 if (0 != strcmp (name, ego_name))
790 return;
791 pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
792}
793
794
795static void
796run (void *cls,
797 char *const *args,
798 const char *cfgfile,
799 const struct GNUNET_CONFIGURATION_Handle *c)
800{
801 ret = 0;
802 if (NULL == ego_name)
803 {
804 ret = 1;
805 fprintf (stderr, _ ("Ego is required\n"));
806 return;
807 }
808
809 if ((NULL == attr_value) && (NULL != attr_name))
810 {
811 ret = 1;
812 fprintf (stderr, _ ("Attribute value missing!\n"));
813 return;
814 }
815
816 if ((NULL == rp) && (NULL != issue_attrs))
817 {
818 ret = 1;
819 fprintf (stderr, _ ("Requesting party key is required!\n"));
820 return;
821 }
822
823 reclaim_handle = GNUNET_RECLAIM_connect (c);
824 // Get Ego
825 identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, NULL);
826}
827
828
829int
830main (int argc, char *const argv[])
831{
832 exp_interval = GNUNET_TIME_UNIT_HOURS;
833 struct GNUNET_GETOPT_CommandLineOption options[] = {
834 GNUNET_GETOPT_option_string ('a',
835 "add",
836 "NAME",
837 gettext_noop ("Add or update an attribute NAME"),
838 &attr_name),
839 GNUNET_GETOPT_option_string ('d',
840 "delete",
841 "ID",
842 gettext_noop ("Delete the attribute with ID"),
843 &attr_delete),
844 GNUNET_GETOPT_option_string ('V',
845 "value",
846 "VALUE",
847 gettext_noop ("The attribute VALUE"),
848 &attr_value),
849 GNUNET_GETOPT_option_string ('e',
850 "ego",
851 "EGO",
852 gettext_noop ("The EGO to use"),
853 &ego_name),
854 GNUNET_GETOPT_option_string ('r',
855 "rp",
856 "RP",
857 gettext_noop (
858 "Specify the relying party for issue"),
859 &rp),
860 GNUNET_GETOPT_option_flag ('D',
861 "dump",
862 gettext_noop ("List attributes for EGO"),
863 &list),
864 GNUNET_GETOPT_option_flag ('A',
865 "credentials",
866 gettext_noop ("List credentials for EGO"),
867 &list_credentials),
868 GNUNET_GETOPT_option_string ('I',
869 "credential-id",
870 "CREDENTIAL_ID",
871 gettext_noop (
872 "Credential to use for attribute"),
873 &credential_id),
874 GNUNET_GETOPT_option_string ('N',
875 "credential-name",
876 "NAME",
877 gettext_noop ("Credential name"),
878 &credential_name),
879 GNUNET_GETOPT_option_string ('i',
880 "issue",
881 "A1,A2,...",
882 gettext_noop (
883 "Issue a ticket for a set of attributes separated by comma"),
884 &issue_attrs),
885 GNUNET_GETOPT_option_string ('C',
886 "consume",
887 "TICKET",
888 gettext_noop ("Consume a ticket"),
889 &consume_ticket),
890 GNUNET_GETOPT_option_string ('R',
891 "revoke",
892 "TICKET",
893 gettext_noop ("Revoke a ticket"),
894 &revoke_ticket),
895 GNUNET_GETOPT_option_string ('t',
896 "type",
897 "TYPE",
898 gettext_noop ("Type of attribute"),
899 &type_str),
900 GNUNET_GETOPT_option_string ('u',
901 "credential-type",
902 "TYPE",
903 gettext_noop ("Type of credential"),
904 &credential_type),
905 GNUNET_GETOPT_option_flag ('T',
906 "tickets",
907 gettext_noop ("List tickets of ego"),
908 &list_tickets),
909 GNUNET_GETOPT_option_relative_time ('E',
910 "expiration",
911 "INTERVAL",
912 gettext_noop (
913 "Expiration interval of the attribute"),
914 &exp_interval),
915
916 GNUNET_GETOPT_OPTION_END
917 };
918 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
919 argv,
920 "gnunet-reclaim",
921 _ ("re:claimID command line tool"),
922 options,
923 &run,
924 NULL))
925 return 1;
926 else
927 return ret;
928}
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
deleted file mode 100644
index 47a86a3e8..000000000
--- a/src/reclaim/gnunet-service-reclaim.c
+++ /dev/null
@@ -1,2814 +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 for 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_CRYPTO_PrivateKey identity;
114
115 /**
116 * Namestore iterator
117 */
118 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
119
120 /**
121 * The operation id for 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_CRYPTO_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 * Existing attributes
304 */
305 struct GNUNET_RECLAIM_AttributeList *existing_attributes;
306
307 /**
308 * Existing credentials
309 */
310 struct GNUNET_RECLAIM_CredentialList *existing_credentials;
311
312 /**
313 * Attribute label
314 */
315 char *label;
316
317 /**
318 * request id
319 */
320 uint32_t r_id;
321};
322
323
324/**
325 * Handle for attribute store request
326 */
327struct AttributeStoreHandle
328{
329 /**
330 * DLL
331 */
332 struct AttributeStoreHandle *next;
333
334 /**
335 * DLL
336 */
337 struct AttributeStoreHandle *prev;
338
339 /**
340 * Client connection
341 */
342 struct IdpClient *client;
343
344 /**
345 * Identity
346 */
347 struct GNUNET_CRYPTO_PrivateKey identity;
348
349 /**
350 * Identity pubkey
351 */
352 struct GNUNET_CRYPTO_PublicKey identity_pkey;
353
354 /**
355 * QueueEntry
356 */
357 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
358
359 /**
360 * The attribute to store
361 */
362 struct GNUNET_RECLAIM_Attribute *claim;
363
364 /**
365 * The credential to store
366 */
367 struct GNUNET_RECLAIM_Credential *credential;
368
369 /**
370 * The attribute expiration interval
371 */
372 struct GNUNET_TIME_Relative exp;
373
374 /**
375 * request id
376 */
377 uint32_t r_id;
378};
379
380
381/**
382 * Handle for ticket consume request
383 */
384struct ConsumeTicketOperation
385{
386 /**
387 * DLL
388 */
389 struct ConsumeTicketOperation *next;
390
391 /**
392 * DLL
393 */
394 struct ConsumeTicketOperation *prev;
395
396 /**
397 * Client connection
398 */
399 struct IdpClient *client;
400
401 /**
402 * request id
403 */
404 uint32_t r_id;
405
406 /**
407 * Ticket consume handle
408 */
409 struct RECLAIM_TICKETS_ConsumeHandle *ch;
410};
411
412
413/**
414 * Ticket revocation request handle
415 */
416struct TicketRevocationOperation
417{
418 /**
419 * DLL
420 */
421 struct TicketRevocationOperation *prev;
422
423 /**
424 * DLL
425 */
426 struct TicketRevocationOperation *next;
427
428 /**
429 * Client connection
430 */
431 struct IdpClient *client;
432
433 /**
434 * Revocation handle
435 */
436 struct RECLAIM_TICKETS_RevokeHandle *rh;
437
438 /**
439 * request id
440 */
441 uint32_t r_id;
442};
443
444
445/**
446 * Ticket issue operation handle
447 */
448struct TicketIssueOperation
449{
450 /**
451 * DLL
452 */
453 struct TicketIssueOperation *prev;
454
455 /**
456 * DLL
457 */
458 struct TicketIssueOperation *next;
459
460 /**
461 * Client connection
462 */
463 struct IdpClient *client;
464
465 /**
466 * request id
467 */
468 uint32_t r_id;
469};
470
471
472/**
473 * Client list
474 */
475static struct IdpClient *client_list_head = NULL;
476
477/**
478 * Client list
479 */
480static struct IdpClient *client_list_tail = NULL;
481
482
483/**
484 * Cleanup attribute delete handle
485 *
486 * @param adh the attribute to cleanup
487 */
488static void
489cleanup_adh (struct AttributeDeleteHandle *adh)
490{
491 struct TicketRecordsEntry *le;
492
493 if (NULL != adh->ns_it)
494 GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
495 if (NULL != adh->ns_qe)
496 GNUNET_NAMESTORE_cancel (adh->ns_qe);
497 if (NULL != adh->label)
498 GNUNET_free (adh->label);
499 if (NULL != adh->claim)
500 GNUNET_free (adh->claim);
501 if (NULL != adh->credential)
502 GNUNET_free (adh->credential);
503 if (NULL != adh->existing_credentials)
504 GNUNET_RECLAIM_credential_list_destroy (adh->existing_credentials);
505 if (NULL != adh->existing_attributes)
506 GNUNET_RECLAIM_attribute_list_destroy (adh->existing_attributes);
507 while (NULL != (le = adh->tickets_to_update_head))
508 {
509 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
510 adh->tickets_to_update_tail,
511 le);
512 if (NULL != le->label)
513 GNUNET_free (le->label);
514 if (NULL != le->data)
515 GNUNET_free (le->data);
516 GNUNET_free (le);
517 }
518 GNUNET_free (adh);
519}
520
521
522/**
523 * Cleanup attribute store handle
524 *
525 * @param ash handle to clean up
526 */
527static void
528cleanup_as_handle (struct AttributeStoreHandle *ash)
529{
530 if (NULL != ash->ns_qe)
531 GNUNET_NAMESTORE_cancel (ash->ns_qe);
532 if (NULL != ash->claim)
533 GNUNET_free (ash->claim);
534 if (NULL != ash->credential)
535 GNUNET_free (ash->credential);
536 GNUNET_free (ash);
537}
538
539
540/**
541 * Cleanup client
542 *
543 * @param idp the client to clean up
544 */
545static void
546cleanup_client (struct IdpClient *idp)
547{
548 struct Iterator *ai;
549 struct TicketIteration *ti;
550 struct TicketRevocationOperation *rop;
551 struct TicketIssueOperation *iss;
552 struct ConsumeTicketOperation *ct;
553 struct AttributeStoreHandle *as;
554 struct AttributeDeleteHandle *adh;
555
556 while (NULL != (iss = idp->issue_op_head))
557 {
558 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
559 GNUNET_free (iss);
560 }
561 while (NULL != (ct = idp->consume_op_head))
562 {
563 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
564 idp->consume_op_tail,
565 ct);
566 if (NULL != ct->ch)
567 RECLAIM_TICKETS_consume_cancel (ct->ch);
568 GNUNET_free (ct);
569 }
570 while (NULL != (as = idp->store_op_head))
571 {
572 GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
573 cleanup_as_handle (as);
574 }
575 while (NULL != (adh = idp->delete_op_head))
576 {
577 GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
578 cleanup_adh (adh);
579 }
580
581 while (NULL != (ai = idp->attr_iter_head))
582 {
583 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
584 GNUNET_free (ai);
585 }
586 while (NULL != (ai = idp->cred_iter_head))
587 {
588 GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
589 ai);
590 GNUNET_free (ai);
591 }
592
593 while (NULL != (rop = idp->revoke_op_head))
594 {
595 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
596 if (NULL != rop->rh)
597 RECLAIM_TICKETS_revoke_cancel (rop->rh);
598 GNUNET_free (rop);
599 }
600 while (NULL != (ti = idp->ticket_iter_head))
601 {
602 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
603 idp->ticket_iter_tail,
604 ti);
605 if (NULL != ti->iter)
606 RECLAIM_TICKETS_iteration_stop (ti->iter);
607 GNUNET_free (ti);
608 }
609 GNUNET_free (idp);
610}
611
612
613/**
614 * Cleanup task
615 */
616static void
617cleanup ()
618{
619 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
620
621 RECLAIM_TICKETS_deinit ();
622 if (NULL != timeout_task)
623 GNUNET_SCHEDULER_cancel (timeout_task);
624 if (NULL != nsh)
625 GNUNET_NAMESTORE_disconnect (nsh);
626}
627
628
629/**
630 * Shutdown task
631 *
632 * @param cls NULL
633 */
634static void
635do_shutdown (void *cls)
636{
637 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
638 cleanup ();
639}
640
641
642/**
643 * Sends a ticket result message to the client
644 *
645 * @param client the client to send to
646 * @param r_id the request message ID to reply to
647 * @param ticket the ticket to include (may be NULL)
648 * @param success the success status of the request
649 */
650static void
651send_ticket_result (const struct IdpClient *client,
652 uint32_t r_id,
653 const struct GNUNET_RECLAIM_Ticket *ticket,
654 const struct GNUNET_RECLAIM_PresentationList *presentations,
655 uint32_t success)
656{
657 struct TicketResultMessage *irm;
658 struct GNUNET_MQ_Envelope *env;
659 size_t pres_len = 0;
660 size_t tkt_len = 0;
661 ssize_t written;
662 char *buf;
663
664 if (NULL != presentations)
665 {
666 pres_len =
667 GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
668 }
669 if (NULL != ticket)
670 tkt_len = GNUNET_RECLAIM_ticket_serialize_get_size (ticket);
671 env = GNUNET_MQ_msg_extra (irm,
672 pres_len + tkt_len,
673 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
674 buf = (char*) &irm[1];
675 if (NULL != ticket)
676 {
677 irm->tkt_len = htons (tkt_len);
678 written = GNUNET_RECLAIM_write_ticket_to_buffer (ticket, buf, tkt_len);
679 GNUNET_assert (0 <= written);
680 buf += written;
681 }
682 // TODO add success member
683 irm->id = htonl (r_id);
684 irm->presentations_len = htons (pres_len);
685 if (NULL != presentations)
686 {
687 GNUNET_RECLAIM_presentation_list_serialize (presentations,
688 buf);
689 }
690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
691 GNUNET_MQ_send (client->mq, env);
692}
693
694
695/**
696 * Issue ticket result
697 *
698 * @param cls out ticket issue operation handle
699 * @param ticket the issued ticket
700 * @param presentations newly created credential presentations (NULL on error)
701 * @param success issue success status (GNUNET_OK if successful)
702 * @param emsg error message (NULL of success is GNUNET_OK)
703 */
704static void
705issue_ticket_result_cb (void *cls,
706 struct GNUNET_RECLAIM_Ticket *ticket,
707 struct GNUNET_RECLAIM_PresentationList *presentations,
708 int32_t success,
709 const char *emsg)
710{
711 struct TicketIssueOperation *tio = cls;
712
713 if (GNUNET_OK != success)
714 {
715 send_ticket_result (tio->client, tio->r_id, NULL, NULL, GNUNET_SYSERR);
716 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
717 tio->client->issue_op_tail,
718 tio);
719 GNUNET_free (tio);
720 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
721 return;
722 }
723 send_ticket_result (tio->client, tio->r_id,
724 ticket, presentations, GNUNET_SYSERR);
725 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
726 tio->client->issue_op_tail,
727 tio);
728 GNUNET_free (tio);
729}
730
731
732/**
733 * Check issue ticket message
734 *
735 * @param cls unused
736 * @param im message to check
737 * @return GNUNET_OK if message is ok
738 */
739static int
740check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
741{
742 uint16_t size;
743 size_t attrs_len;
744 size_t key_len;
745 size_t pkey_len;
746
747 size = ntohs (im->header.size);
748 attrs_len = ntohs (im->attr_len);
749 key_len = ntohs (im->key_len);
750 pkey_len = ntohs (im->pkey_len);
751 if (size != attrs_len + key_len + pkey_len + sizeof(struct
752 IssueTicketMessage))
753 {
754 GNUNET_break (0);
755 return GNUNET_SYSERR;
756 }
757 return GNUNET_OK;
758}
759
760
761/**
762 * Handle ticket issue message
763 *
764 * @param cls our client
765 * @param im the message
766 */
767static void
768handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
769{
770 struct TicketIssueOperation *tio;
771 struct IdpClient *idp = cls;
772 struct GNUNET_RECLAIM_AttributeList *attrs;
773 struct GNUNET_RECLAIM_AttributeListEntry *le;
774 struct GNUNET_CRYPTO_PrivateKey identity;
775 struct GNUNET_CRYPTO_PublicKey rp;
776 size_t attrs_len;
777 size_t key_len;
778 size_t pkey_len;
779 size_t read;
780 char *buf;
781
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
783 key_len = ntohs (im->key_len);
784 buf = (char *) &im[1];
785 if ((GNUNET_SYSERR ==
786 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
787 &identity, &read)) ||
788 (read != key_len))
789 {
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
791 "Failed to read private key\n");
792 GNUNET_SERVICE_client_drop (idp->client);
793 return;
794 }
795 buf += read;
796 pkey_len = ntohs (im->pkey_len);
797 if ((GNUNET_SYSERR ==
798 GNUNET_CRYPTO_read_public_key_from_buffer (buf, pkey_len,
799 &rp, &read)) ||
800 (read != pkey_len))
801 {
802 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
803 "Failed to read public key\n");
804 GNUNET_SERVICE_client_drop (idp->client);
805 return;
806 }
807 buf += read;
808 tio = GNUNET_new (struct TicketIssueOperation);
809 attrs_len = ntohs (im->attr_len);
810 attrs = GNUNET_RECLAIM_attribute_list_deserialize (buf,
811 attrs_len);
812 for (le = attrs->list_head; NULL != le; le = le->next)
813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
814 "List entry: %s\n", le->attribute->name);
815
816 tio->r_id = ntohl (im->id);
817 tio->client = idp;
818 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
819 RECLAIM_TICKETS_issue (&identity,
820 attrs,
821 &rp,
822 &issue_ticket_result_cb,
823 tio);
824 GNUNET_SERVICE_client_continue (idp->client);
825 GNUNET_RECLAIM_attribute_list_destroy (attrs);
826}
827
828
829/**********************************************************
830* Revocation
831**********************************************************/
832
833/**
834 * Handles revocation result
835 *
836 * @param cls our revocation operation handle
837 * @param success revocation result (GNUNET_OK if successful)
838 */
839static void
840revoke_result_cb (void *cls, int32_t success)
841{
842 struct TicketRevocationOperation *rop = cls;
843 struct GNUNET_MQ_Envelope *env;
844 struct RevokeTicketResultMessage *trm;
845
846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
847 "Sending REVOKE_TICKET_RESULT message\n");
848 rop->rh = NULL;
849 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
850 trm->id = htonl (rop->r_id);
851 trm->success = htonl (success);
852 GNUNET_MQ_send (rop->client->mq, env);
853 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
854 rop->client->revoke_op_tail,
855 rop);
856 GNUNET_free (rop);
857}
858
859
860/**
861 * Check revocation message format
862 *
863 * @param cls unused
864 * @param im the message to check
865 * @return GNUNET_OK if message is ok
866 */
867static int
868check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
869{
870 uint16_t size;
871
872 size = ntohs (im->header.size);
873 if (size != sizeof(struct RevokeTicketMessage))
874 {
875 GNUNET_break (0);
876 return GNUNET_SYSERR;
877 }
878 return GNUNET_OK;
879}
880
881
882/**
883 * Handle a revocation message to a ticket.
884 *
885 * @param cls our client
886 * @param rm the message to handle
887 */
888static void
889handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
890{
891 struct TicketRevocationOperation *rop;
892 struct IdpClient *idp = cls;
893 struct GNUNET_CRYPTO_PrivateKey identity;
894 struct GNUNET_RECLAIM_Ticket ticket;
895 size_t key_len;
896 size_t tkt_len;
897 size_t read;
898 char *buf;
899
900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
901 key_len = ntohs (rm->key_len);
902 buf = (char *) &rm[1];
903 if ((GNUNET_SYSERR ==
904 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
905 &identity, &read)) ||
906 (read != key_len))
907 {
908 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
909 "Failed to read private key\n");
910 GNUNET_SERVICE_client_drop (idp->client);
911 return;
912 }
913 buf += read;
914 tkt_len = ntohs (rm->tkt_len);
915 if ((GNUNET_SYSERR ==
916 GNUNET_RECLAIM_read_ticket_from_buffer (buf, tkt_len,
917 &ticket, &read)) ||
918 (read != tkt_len))
919 {
920 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
921 "Failed to read ticket\n");
922 GNUNET_SERVICE_client_drop (idp->client);
923 return;
924 }
925 rop = GNUNET_new (struct TicketRevocationOperation);
926 rop->r_id = ntohl (rm->id);
927 rop->client = idp;
928 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
929 rop->rh
930 = RECLAIM_TICKETS_revoke (&ticket, &identity, &revoke_result_cb, rop);
931 GNUNET_SERVICE_client_continue (idp->client);
932}
933
934
935/**
936 * Handle a ticket consume result
937 *
938 * @param cls our consume ticket operation handle
939 * @param identity the attribute authority
940 * @param attrs the attribute/claim list
941 * @param success GNUNET_OK if successful
942 * @param emsg error message (NULL if success=GNUNET_OK)
943 */
944static void
945consume_result_cb (void *cls,
946 const struct GNUNET_CRYPTO_PublicKey *identity,
947 const struct GNUNET_RECLAIM_AttributeList *attrs,
948 const struct GNUNET_RECLAIM_PresentationList *presentations,
949 int32_t success,
950 const char *emsg)
951{
952 struct ConsumeTicketOperation *cop = cls;
953 struct ConsumeTicketResultMessage *crm;
954 struct GNUNET_MQ_Envelope *env;
955 char *data_tmp;
956 size_t attrs_len = 0;
957 size_t pres_len = 0;
958 size_t key_len;
959 ssize_t written;
960
961 if (GNUNET_OK != success)
962 {
963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
964 }
965 attrs_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
966 pres_len = GNUNET_RECLAIM_presentation_list_serialize_get_size (
967 presentations);
968 key_len = GNUNET_CRYPTO_public_key_get_length (identity);
969 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
970 "Sending CONSUME_TICKET_RESULT message\n");
971 env = GNUNET_MQ_msg_extra (crm,
972 attrs_len + pres_len + key_len,
973 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
974 crm->id = htonl (cop->r_id);
975 crm->attrs_len = htons (attrs_len);
976 crm->presentations_len = htons (pres_len);
977 crm->key_len = htons (key_len);
978 crm->result = htons (success);
979 data_tmp = (char *) &crm[1];
980 written = GNUNET_CRYPTO_write_public_key_to_buffer (identity,
981 data_tmp,
982 key_len);
983 GNUNET_assert (0 <= written);
984 data_tmp += written;
985 GNUNET_RECLAIM_attribute_list_serialize (attrs, data_tmp);
986 data_tmp += attrs_len;
987 GNUNET_RECLAIM_presentation_list_serialize (presentations, data_tmp);
988 GNUNET_MQ_send (cop->client->mq, env);
989 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
990 cop->client->consume_op_tail,
991 cop);
992 GNUNET_free (cop);
993}
994
995
996/**
997 * Check a consume ticket message
998 *
999 * @param cls unused
1000 * @param cm the message to handle
1001 */
1002static int
1003check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
1004{
1005 uint16_t size;
1006
1007 size = ntohs (cm->header.size);
1008 if (size <= sizeof(struct ConsumeTicketMessage))
1009 {
1010 GNUNET_break (0);
1011 return GNUNET_SYSERR;
1012 }
1013 return GNUNET_OK;
1014}
1015
1016
1017/**
1018 * Handle a consume ticket message
1019 *
1020 * @param cls our client handle
1021 * @param cm the message to handle
1022 */
1023static void
1024handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
1025{
1026 struct ConsumeTicketOperation *cop;
1027 struct IdpClient *idp = cls;
1028 struct GNUNET_CRYPTO_PrivateKey identity;
1029 struct GNUNET_RECLAIM_Ticket ticket;
1030 size_t key_len;
1031 size_t tkt_len;
1032 size_t read;
1033 char *buf;
1034
1035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
1036 key_len = ntohs (cm->key_len);
1037 buf = (char *) &cm[1];
1038 if ((GNUNET_SYSERR ==
1039 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1040 &identity, &read)) ||
1041 (read != key_len))
1042 {
1043 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1044 "Failed to read private key\n");
1045 GNUNET_SERVICE_client_drop (idp->client);
1046 return;
1047 }
1048 buf += read;
1049 tkt_len = ntohs (cm->tkt_len);
1050 if ((GNUNET_SYSERR ==
1051 GNUNET_RECLAIM_read_ticket_from_buffer (buf, tkt_len,
1052 &ticket, &read)) ||
1053 (read != tkt_len))
1054 {
1055 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1056 "Failed to read ticket\n");
1057 GNUNET_SERVICE_client_drop (idp->client);
1058 return;
1059 }
1060 cop = GNUNET_new (struct ConsumeTicketOperation);
1061 cop->r_id = ntohl (cm->id);
1062 cop->client = idp;
1063 cop->ch
1064 = RECLAIM_TICKETS_consume (&identity, &ticket, &consume_result_cb,
1065 cop);
1066 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
1067 GNUNET_SERVICE_client_continue (idp->client);
1068}
1069
1070
1071/*****************************************
1072* Attribute store
1073*****************************************/
1074
1075
1076/**
1077 * Attribute store result handler
1078 *
1079 * @param cls our attribute store handle
1080 * @param success GNUNET_OK if successful
1081 * @param emsg error message (NULL if success=GNUNET_OK)
1082 */
1083static void
1084attr_store_cont (void *cls, enum GNUNET_ErrorCode ec)
1085{
1086 struct AttributeStoreHandle *ash = cls;
1087 struct GNUNET_MQ_Envelope *env;
1088 struct SuccessResultMessage *acr_msg;
1089
1090 ash->ns_qe = NULL;
1091 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1092 ash->client->store_op_tail,
1093 ash);
1094
1095 if (GNUNET_EC_NONE != ec)
1096 {
1097 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1098 "Failed to store attribute %s\n",
1099 GNUNET_ErrorCode_get_hint (ec));
1100 cleanup_as_handle (ash);
1101 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1102 return;
1103 }
1104
1105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1106 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1107 acr_msg->id = htonl (ash->r_id);
1108 acr_msg->op_result = htonl (GNUNET_OK);
1109 GNUNET_MQ_send (ash->client->mq, env);
1110 cleanup_as_handle (ash);
1111}
1112
1113
1114/**
1115 * Add a new attribute
1116 *
1117 * @param cls the AttributeStoreHandle
1118 */
1119static void
1120attr_store_task (void *cls)
1121{
1122 struct AttributeStoreHandle *ash = cls;
1123 struct GNUNET_GNSRECORD_Data rd[1];
1124 char *buf;
1125 char *label;
1126 size_t buf_size;
1127
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
1129 buf_size = GNUNET_RECLAIM_attribute_serialize_get_size (ash->claim);
1130 buf = GNUNET_malloc (buf_size);
1131 // Give the ash a new id if unset
1132 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->claim->id))
1133 GNUNET_RECLAIM_id_generate (&ash->claim->id);
1134 GNUNET_RECLAIM_attribute_serialize (ash->claim, buf);
1135 label
1136 = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id,
1137 sizeof (ash->claim->id));
1138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1139
1140 rd[0].data_size = buf_size;
1141 rd[0].data = buf;
1142 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE;
1143 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1144 rd[0].expiration_time = ash->exp.rel_value_us;
1145 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1146 &ash->identity,
1147 label,
1148 1,
1149 rd,
1150 &attr_store_cont,
1151 ash);
1152 GNUNET_free (buf);
1153 GNUNET_free (label);
1154}
1155
1156
1157/**
1158 * Check an attribute store message
1159 *
1160 * @param cls unused
1161 * @param sam the message to check
1162 */
1163static int
1164check_attribute_store_message (void *cls,
1165 const struct AttributeStoreMessage *sam)
1166{
1167 uint16_t size;
1168
1169 size = ntohs (sam->header.size);
1170 if (size <= sizeof(struct AttributeStoreMessage))
1171 {
1172 GNUNET_break (0);
1173 return GNUNET_SYSERR;
1174 }
1175 return GNUNET_OK;
1176}
1177
1178
1179/**
1180 * Handle an attribute store message
1181 *
1182 * @param cls our client
1183 * @param sam the message to handle
1184 */
1185static void
1186handle_attribute_store_message (void *cls,
1187 const struct AttributeStoreMessage *sam)
1188{
1189 struct AttributeStoreHandle *ash;
1190 struct IdpClient *idp = cls;
1191 struct GNUNET_CRYPTO_PrivateKey identity;
1192 size_t data_len;
1193 size_t key_len;
1194 size_t read;
1195 char *buf;
1196
1197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1198
1199 data_len = ntohs (sam->attr_len);
1200 key_len = ntohs (sam->key_len);
1201 buf = (char *) &sam[1];
1202 if ((GNUNET_SYSERR ==
1203 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1204 &identity, &read)) ||
1205 (read != key_len))
1206 {
1207 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1208 "Failed to read private key\n");
1209 GNUNET_SERVICE_client_drop (idp->client);
1210 return;
1211 }
1212 buf += read;
1213 ash = GNUNET_new (struct AttributeStoreHandle);
1214 GNUNET_RECLAIM_attribute_deserialize (buf,
1215 data_len,
1216 &ash->claim);
1217
1218 ash->r_id = ntohl (sam->id);
1219 ash->identity = identity;
1220 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1221 GNUNET_CRYPTO_key_get_public (&identity, &ash->identity_pkey);
1222
1223 GNUNET_SERVICE_client_continue (idp->client);
1224 ash->client = idp;
1225 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1226 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1227}
1228
1229
1230/**
1231 * Credential store result handler
1232 *
1233 * @param cls our attribute store handle
1234 * @param success GNUNET_OK if successful
1235 * @param emsg error message (NULL if success=GNUNET_OK)
1236 */
1237static void
1238cred_store_cont (void *cls, enum GNUNET_ErrorCode ec)
1239{
1240 struct AttributeStoreHandle *ash = cls;
1241 struct GNUNET_MQ_Envelope *env;
1242 struct SuccessResultMessage *acr_msg;
1243
1244 ash->ns_qe = NULL;
1245 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1246 ash->client->store_op_tail,
1247 ash);
1248
1249 if (GNUNET_EC_NONE != ec)
1250 {
1251 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1252 "Failed to store credential: %s\n",
1253 GNUNET_ErrorCode_get_hint (ec));
1254 cleanup_as_handle (ash);
1255 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1256 return;
1257 }
1258
1259 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1260 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1261 acr_msg->id = htonl (ash->r_id);
1262 acr_msg->op_result = htonl (GNUNET_OK);
1263 GNUNET_MQ_send (ash->client->mq, env);
1264 cleanup_as_handle (ash);
1265}
1266
1267
1268/**
1269 * Error looking up potential credential. Abort.
1270 *
1271 * @param cls our attribute store handle
1272 */
1273static void
1274cred_error (void *cls)
1275{
1276 struct AttributeStoreHandle *ash = cls;
1277 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1278 "Failed to check for existing credential.\n");
1279 cleanup_as_handle (ash);
1280 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1281 return;
1282}
1283
1284
1285/**
1286* Check for existing record before storing credential
1287*
1288* @param cls our attribute store handle
1289* @param zone zone we are iterating
1290* @param label label of the records
1291* @param rd_count record count
1292* @param rd records
1293*/
1294static void
1295cred_add_cb (void *cls,
1296 const struct GNUNET_CRYPTO_PrivateKey *zone,
1297 const char *label,
1298 unsigned int rd_count,
1299 const struct GNUNET_GNSRECORD_Data *rd)
1300{
1301 struct AttributeStoreHandle *ash = cls;
1302 struct GNUNET_GNSRECORD_Data rd_new[1];
1303 char *buf;
1304 size_t buf_size;
1305
1306 buf_size = GNUNET_RECLAIM_credential_serialize_get_size (ash->credential);
1307 buf = GNUNET_malloc (buf_size);
1308 GNUNET_RECLAIM_credential_serialize (ash->credential, buf);
1309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1310 "Storing new credential under `%s'.\n",
1311 label);
1312 rd_new[0].data_size = buf_size;
1313 rd_new[0].data = buf;
1314 rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL;
1315 rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1316 rd_new[0].expiration_time = ash->exp.rel_value_us;
1317 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1318 &ash->identity,
1319 label,
1320 1,
1321 rd_new,
1322 &cred_store_cont,
1323 ash);
1324 GNUNET_free (buf);
1325 return;
1326}
1327
1328
1329/**
1330 * Add a new credential
1331 *
1332 * @param cls the AttributeStoreHandle
1333 */
1334static void
1335cred_store_task (void *cls)
1336{
1337 struct AttributeStoreHandle *ash = cls;
1338 char *label;
1339
1340 // Give the ash a new id if unset
1341 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->credential->id))
1342 GNUNET_RECLAIM_id_generate (&ash->credential->id);
1343 label = GNUNET_STRINGS_data_to_string_alloc (&ash->credential->id,
1344 sizeof (ash->credential->id));
1345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1346 "Looking up existing data under label `%s'\n", label);
1347 ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1348 &ash->identity,
1349 label,
1350 &cred_error,
1351 ash,
1352 &cred_add_cb,
1353 ash);
1354 GNUNET_free (label);
1355}
1356
1357
1358/**
1359 * Check an credential store message
1360 *
1361 * @param cls unused
1362 * @param sam the message to check
1363 */
1364static int
1365check_credential_store_message (void *cls,
1366 const struct AttributeStoreMessage *sam)
1367{
1368 uint16_t size;
1369
1370 size = ntohs (sam->header.size);
1371 if (size <= sizeof(struct AttributeStoreMessage))
1372 {
1373 GNUNET_break (0);
1374 return GNUNET_SYSERR;
1375 }
1376 return GNUNET_OK;
1377}
1378
1379
1380/**
1381* Handle a credential store message
1382*
1383* @param cls our client
1384* @param sam the message to handle
1385*/
1386static void
1387handle_credential_store_message (void *cls,
1388 const struct AttributeStoreMessage *sam)
1389{
1390 struct AttributeStoreHandle *ash;
1391 struct IdpClient *idp = cls;
1392 struct GNUNET_CRYPTO_PrivateKey identity;
1393 size_t data_len;
1394 size_t key_len;
1395 size_t read;
1396 char *buf;
1397
1398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_STORE message\n");
1399
1400 data_len = ntohs (sam->attr_len);
1401 key_len = ntohs (sam->key_len);
1402 buf = (char *) &sam[1];
1403 if ((GNUNET_SYSERR ==
1404 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1405 &identity, &read)) ||
1406 (read != key_len))
1407 {
1408 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1409 "Failed to read private key\n");
1410 GNUNET_SERVICE_client_drop (idp->client);
1411 return;
1412 }
1413 buf += read;
1414 ash = GNUNET_new (struct AttributeStoreHandle);
1415 ash->credential = GNUNET_RECLAIM_credential_deserialize (buf,
1416 data_len);
1417
1418 ash->r_id = ntohl (sam->id);
1419 ash->identity = identity;
1420 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1421 GNUNET_CRYPTO_key_get_public (&identity, &ash->identity_pkey);
1422
1423 GNUNET_SERVICE_client_continue (idp->client);
1424 ash->client = idp;
1425 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1426 GNUNET_SCHEDULER_add_now (&cred_store_task, ash);
1427}
1428
1429
1430/**
1431 * Send a deletion success response
1432 *
1433 * @param adh our attribute deletion handle
1434 * @param success the success status
1435 */
1436static void
1437send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1438{
1439 struct GNUNET_MQ_Envelope *env;
1440 struct SuccessResultMessage *acr_msg;
1441
1442 GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1443 adh->client->delete_op_tail,
1444 adh);
1445
1446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1447 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1448 acr_msg->id = htonl (adh->r_id);
1449 acr_msg->op_result = htonl (success);
1450 GNUNET_MQ_send (adh->client->mq, env);
1451}
1452
1453
1454/**
1455 * Namestore iteration within attribute deletion.
1456 * We need to reissue tickets with the deleted attribute removed.
1457 *
1458 * @param cls our attribute deletion handle
1459 * @param zone the private key of the ticket issuer
1460 * @param label the label of the record
1461 * @param rd_count number of records
1462 * @param rd record data
1463 */
1464static void
1465consistency_iter (void *cls,
1466 const struct GNUNET_CRYPTO_PrivateKey *zone,
1467 const char *label,
1468 unsigned int rd_count,
1469 const struct GNUNET_GNSRECORD_Data *rd)
1470{
1471 struct AttributeDeleteHandle *adh = cls;
1472 struct TicketRecordsEntry *le;
1473 struct GNUNET_RECLAIM_AttributeListEntry *ale;
1474 struct GNUNET_RECLAIM_CredentialListEntry *cle;
1475 int is_ticket = GNUNET_NO;
1476 for (int i = 0; i < rd_count; i++)
1477 {
1478 switch (rd[i].record_type)
1479 {
1480 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
1481 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1482 GNUNET_RECLAIM_attribute_deserialize (rd[i].data,
1483 rd[i].data_size,
1484 &ale->attribute);
1485 GNUNET_CONTAINER_DLL_insert (adh->existing_attributes->list_head,
1486 adh->existing_attributes->list_tail,
1487 ale);
1488 break;
1489 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
1490 cle = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
1491 cle->credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
1492 rd[i].data_size);
1493 GNUNET_CONTAINER_DLL_insert (adh->existing_credentials->list_head,
1494 adh->existing_credentials->list_tail,
1495 cle);
1496 break;
1497 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
1498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1499 "Ticket to delete found (%s)\n",
1500 label);
1501 is_ticket = GNUNET_YES;
1502 break;
1503 default:
1504 break;
1505 }
1506 if (GNUNET_YES == is_ticket)
1507 break;
1508 }
1509 if (GNUNET_YES == is_ticket)
1510 {
1511 le = GNUNET_new (struct TicketRecordsEntry);
1512 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1513 le->data = GNUNET_malloc (le->data_size);
1514 le->rd_count = rd_count;
1515 le->label = GNUNET_strdup (label);
1516 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1517 GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1518 adh->tickets_to_update_tail,
1519 le);
1520 }
1521 GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1522}
1523
1524
1525/**
1526 * Recursion prototype for function
1527 * @param cls our deletion handle
1528 */
1529static void
1530update_tickets (void *cls);
1531
1532
1533/**
1534 * Callback called when a ticket was updated
1535 *
1536 * @param cls our attribute deletion handle
1537 * @param success GNUNET_OK if successful
1538 * @param emsg error message (NULL if success=GNUNET_OK)
1539 */
1540static void
1541ticket_updated (void *cls, enum GNUNET_ErrorCode ec)
1542{
1543 struct AttributeDeleteHandle *adh = cls;
1544
1545 adh->ns_qe = NULL;
1546 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1547}
1548
1549
1550/**
1551 * Update tickets: Remove shared attribute which has just been deleted.
1552 * This method is called recursively until all tickets are processed.
1553 * Eventually, the updated tickets are stored using ``update_tickets''.
1554 *
1555 * @param cls our attribute deletion handle
1556 */
1557static void
1558update_tickets (void *cls)
1559{
1560 struct AttributeDeleteHandle *adh = cls;
1561 struct TicketRecordsEntry *le;
1562
1563 if (NULL == adh->tickets_to_update_head)
1564 {
1565 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1566 "Finished updating tickets, success\n");
1567 send_delete_response (adh, GNUNET_OK);
1568 cleanup_adh (adh);
1569 return;
1570 }
1571 le = adh->tickets_to_update_head;
1572 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1573 adh->tickets_to_update_tail,
1574 le);
1575 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1576 struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1577 if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
1578 le->data,
1579 le->rd_count,
1580 rd))
1581 {
1582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1583 "Unable to deserialize record data!\n");
1584 send_delete_response (adh, GNUNET_SYSERR);
1585 cleanup_adh (adh);
1586 return;
1587 }
1588 int j = 0;
1589 int i = 0;
1590 struct GNUNET_RECLAIM_AttributeListEntry *ale;
1591 struct GNUNET_RECLAIM_CredentialListEntry *cle;
1592 struct GNUNET_RECLAIM_Presentation *presentation;
1593 for (i = 0; i < le->rd_count; i++)
1594 {
1595 switch (rd[i].record_type)
1596 {
1597 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
1598 for (ale = adh->existing_attributes->list_head; NULL != ale; ale =
1599 ale->next)
1600 {
1601 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1602 &ale->attribute->id))
1603 {
1604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1605 "Found attribute %s, readding...\n",
1606 ale->attribute->name);
1607 rd_new[j] = rd[i];
1608 j++;
1609 break; // Found and added
1610 }
1611 }
1612 break;
1613 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
1614 presentation = GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1615 rd[i].data_size);
1616 for (cle = adh->existing_credentials->list_head; NULL != cle; cle =
1617 cle->next)
1618 {
1619 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (
1620 &presentation->credential_id,
1621 &cle->credential->id))
1622 {
1623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1624 "Found presentation for credential %s, readding...\n",
1625 cle->credential->name);
1626 rd_new[j] = rd[i];
1627 j++;
1628 break; // Found and added
1629 }
1630 }
1631 GNUNET_free (presentation);
1632 break;
1633 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
1634 rd_new[j] = rd[i];
1635 j++;
1636 break; // Found and added
1637 default:
1638 GNUNET_break (0);
1639 }
1640 }
1641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1642 "Updating ticket with %d entries (%d before)...\n",
1643 j, i);
1644 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1645 &adh->identity,
1646 le->label,
1647 j,
1648 rd_new,
1649 &ticket_updated,
1650 adh);
1651 GNUNET_free (le->label);
1652 GNUNET_free (le->data);
1653 GNUNET_free (le);
1654}
1655
1656
1657/**
1658 * Delete all attributes which reference credentials
1659 * that no longer exist
1660 */
1661static void
1662purge_attributes (void *cls);;
1663
1664static void
1665offending_attr_delete_cont (void *cls, enum GNUNET_ErrorCode ec)
1666{
1667 struct AttributeDeleteHandle *adh = cls;
1668
1669 adh->ns_qe = NULL;
1670 if (GNUNET_EC_NONE != ec)
1671 {
1672 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1673 "Error deleting attribute %s\n",
1674 adh->label);
1675 send_delete_response (adh, GNUNET_SYSERR);
1676 cleanup_adh (adh);
1677 return;
1678 }
1679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Continuing consistency check...\n");
1680 GNUNET_SCHEDULER_add_now (&purge_attributes, adh);
1681}
1682
1683
1684/**
1685 * Delete all attributes which reference credentials
1686 * that no longer exist
1687 */
1688static void
1689purge_attributes (void *cls)
1690{
1691 struct AttributeDeleteHandle *adh = cls;
1692 struct GNUNET_RECLAIM_AttributeListEntry *ale;
1693 struct GNUNET_RECLAIM_CredentialListEntry *cle;
1694
1695 for (ale = adh->existing_attributes->list_head; NULL != ale; ale = ale->next)
1696 {
1697 if (GNUNET_YES ==
1698 GNUNET_RECLAIM_id_is_zero (&ale->attribute->credential))
1699 continue;
1700
1701 for (cle = adh->existing_credentials->list_head;
1702 NULL != cle; cle = cle->next)
1703 {
1704 if (GNUNET_YES !=
1705 GNUNET_RECLAIM_id_is_equal (&cle->credential->id,
1706 &ale->attribute->credential))
1707 continue;
1708 break;
1709 }
1710 if (NULL == cle)
1711 {
1712 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1713 "Found attribute with missing credential\n");
1714 break;
1715 }
1716 }
1717 if (NULL == ale)
1718 {
1719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1720 "Attributes consistent, updating tickets.\n");
1721 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1722 return;
1723 }
1724 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1725 "Attributes inconsistent, deleting offending attribute.\n");
1726 char *label
1727 = GNUNET_STRINGS_data_to_string_alloc (&ale->attribute->id,
1728 sizeof(ale->attribute->id));
1729
1730 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1731 &adh->identity,
1732 label,
1733 0,
1734 NULL,
1735 &offending_attr_delete_cont,
1736 adh);
1737 GNUNET_CONTAINER_DLL_remove (adh->existing_attributes->list_head,
1738 adh->existing_attributes->list_tail,
1739 ale);
1740 GNUNET_free (ale);
1741 GNUNET_free (label);
1742}
1743
1744
1745/**
1746 * Done collecting affected tickets, start updating.
1747 *
1748 * @param cls our attribute deletion handle
1749 */
1750static void
1751consistency_iter_fin (void *cls)
1752{
1753 struct AttributeDeleteHandle *adh = cls;
1754 adh->ns_it = NULL;
1755 GNUNET_SCHEDULER_add_now (&purge_attributes, adh);
1756}
1757
1758
1759/**
1760 * Error collecting affected tickets. Abort.
1761 *
1762 * @param cls our attribute deletion handle
1763 */
1764static void
1765consistency_iter_err (void *cls)
1766{
1767 struct AttributeDeleteHandle *adh = cls;
1768
1769 adh->ns_it = NULL;
1770 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1771 "Namestore error on consistency check\n");
1772 send_delete_response (adh, GNUNET_SYSERR);
1773 cleanup_adh (adh);
1774}
1775
1776
1777/**
1778 * Start processing tickets which may still contain reference to deleted
1779 * attribute.
1780 *
1781 * @param cls attribute deletion handle
1782 */
1783static void
1784start_consistency_update (void *cls)
1785{
1786 struct AttributeDeleteHandle *adh = cls;
1787
1788 adh->existing_attributes = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1789 adh->existing_credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1790
1791 adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1792 &adh->identity,
1793 &consistency_iter_err,
1794 adh,
1795 &consistency_iter,
1796 adh,
1797 &consistency_iter_fin,
1798 adh);
1799}
1800
1801
1802/**
1803 * Attribute deleted callback
1804 *
1805 * @param cls our handle
1806 * @param success success status
1807 * @param emsg error message (NULL if success=GNUNET_OK)
1808 */
1809static void
1810attr_delete_cont (void *cls, enum GNUNET_ErrorCode ec)
1811{
1812 struct AttributeDeleteHandle *adh = cls;
1813
1814 adh->ns_qe = NULL;
1815 if (GNUNET_EC_NONE != ec)
1816 {
1817 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1818 "Error deleting attribute %s\n",
1819 adh->label);
1820 send_delete_response (adh, GNUNET_SYSERR);
1821 cleanup_adh (adh);
1822 return;
1823 }
1824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1825 GNUNET_SCHEDULER_add_now (&start_consistency_update, adh);
1826}
1827
1828
1829/**
1830 * Check attribute delete message format
1831 *
1832 * @param cls unused
1833 * @param dam message to check
1834 */
1835static int
1836check_attribute_delete_message (void *cls,
1837 const struct AttributeDeleteMessage *dam)
1838{
1839 uint16_t size;
1840
1841 size = ntohs (dam->header.size);
1842 if (size <= sizeof(struct AttributeDeleteMessage))
1843 {
1844 GNUNET_break (0);
1845 return GNUNET_SYSERR;
1846 }
1847 return GNUNET_OK;
1848}
1849
1850
1851/**
1852 * Handle attribute deletion
1853 *
1854 * @param cls our client
1855 * @param dam deletion message
1856 */
1857static void
1858handle_attribute_delete_message (void *cls,
1859 const struct AttributeDeleteMessage *dam)
1860{
1861 struct AttributeDeleteHandle *adh;
1862 struct IdpClient *idp = cls;
1863 struct GNUNET_CRYPTO_PrivateKey identity;
1864 size_t data_len;
1865 size_t key_len;
1866 size_t read;
1867 char *buf;
1868
1869 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1870
1871 data_len = ntohs (dam->attr_len);
1872 key_len = ntohs (dam->key_len);
1873 buf = (char *) &dam[1];
1874 if ((GNUNET_SYSERR ==
1875 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1876 &identity, &read)) ||
1877 (read != key_len))
1878 {
1879 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1880 "Failed to read private key\n");
1881 GNUNET_SERVICE_client_drop (idp->client);
1882 return;
1883 }
1884 buf += read;
1885 adh = GNUNET_new (struct AttributeDeleteHandle);
1886 GNUNET_RECLAIM_attribute_deserialize (buf,
1887 data_len,
1888 &adh->claim);
1889 adh->credential = NULL;
1890
1891 adh->r_id = ntohl (dam->id);
1892 adh->identity = identity;
1893 adh->label
1894 = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id,
1895 sizeof(adh->claim->id));
1896 GNUNET_SERVICE_client_continue (idp->client);
1897 adh->client = idp;
1898 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1899 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1900 &adh->identity,
1901 adh->label,
1902 0,
1903 NULL,
1904 &attr_delete_cont,
1905 adh);
1906}
1907
1908
1909/**
1910 * Credential deleted callback
1911 *
1912 * @param cls our handle
1913 * @param success success status
1914 * @param emsg error message (NULL if success=GNUNET_OK)
1915 */
1916static void
1917cred_delete_cont (void *cls, enum GNUNET_ErrorCode ec)
1918{
1919 struct AttributeDeleteHandle *adh = cls;
1920
1921 adh->ns_qe = NULL;
1922 if (GNUNET_EC_NONE != ec)
1923 {
1924 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1925 "Error deleting credential `%s'\n",
1926 adh->label);
1927 send_delete_response (adh, GNUNET_SYSERR);
1928 cleanup_adh (adh);
1929 return;
1930 }
1931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1932 GNUNET_SCHEDULER_add_now (&start_consistency_update, adh);
1933}
1934
1935
1936/**
1937 * Check credential delete message format
1938 *
1939 * @param cls unused
1940 * @param dam message to check
1941 */
1942static int
1943check_credential_delete_message (void *cls,
1944 const struct AttributeDeleteMessage *dam)
1945{
1946 uint16_t size;
1947
1948 size = ntohs (dam->header.size);
1949 if (size <= sizeof(struct AttributeDeleteMessage))
1950 {
1951 GNUNET_break (0);
1952 return GNUNET_SYSERR;
1953 }
1954 return GNUNET_OK;
1955}
1956
1957
1958/**
1959 * Handle credential deletion
1960 *
1961 * @param cls our client
1962 * @param dam deletion message
1963 */
1964static void
1965handle_credential_delete_message (void *cls,
1966 const struct AttributeDeleteMessage *dam)
1967{
1968 struct AttributeDeleteHandle *adh;
1969 struct IdpClient *idp = cls;
1970 struct GNUNET_CRYPTO_PrivateKey identity;
1971 size_t data_len;
1972 size_t key_len;
1973 size_t read;
1974 char *buf;
1975
1976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_DELETE message\n");
1977
1978 data_len = ntohs (dam->attr_len);
1979 key_len = ntohs (dam->key_len);
1980 buf = (char *) &dam[1];
1981 if ((GNUNET_SYSERR ==
1982 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1983 &identity, &read)) ||
1984 (read != key_len))
1985 {
1986 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1987 "Failed to read private key\n");
1988 GNUNET_SERVICE_client_drop (idp->client);
1989 return;
1990 }
1991 buf += read;
1992 adh = GNUNET_new (struct AttributeDeleteHandle);
1993 adh->credential = GNUNET_RECLAIM_credential_deserialize (buf,
1994 data_len);
1995 adh->claim = NULL;
1996
1997 adh->r_id = ntohl (dam->id);
1998 adh->identity = identity;
1999 adh->label
2000 = GNUNET_STRINGS_data_to_string_alloc (&adh->credential->id,
2001 sizeof(adh->credential->id));
2002 GNUNET_SERVICE_client_continue (idp->client);
2003 adh->client = idp;
2004 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
2005 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
2006 &adh->identity,
2007 adh->label,
2008 0,
2009 NULL,
2010 &cred_delete_cont,
2011 adh);
2012}
2013
2014
2015/*************************************************
2016 * Attribute iteration
2017 *************************************************/
2018
2019
2020/**
2021 * Done iterating over attributes
2022 *
2023 * @param cls our iterator handle
2024 */
2025static void
2026attr_iter_finished (void *cls)
2027{
2028 struct Iterator *ai = cls;
2029 struct GNUNET_MQ_Envelope *env;
2030 struct AttributeResultMessage *arm;
2031
2032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
2033 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2034 arm->id = htonl (ai->request_id);
2035 arm->attr_len = htons (0);
2036 arm->pkey_len = htons (0);
2037 GNUNET_MQ_send (ai->client->mq, env);
2038 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
2039 ai->client->attr_iter_tail,
2040 ai);
2041 GNUNET_free (ai);
2042}
2043
2044
2045/**
2046 * Error iterating over attributes. Abort.
2047 *
2048 * @param cls our attribute iteration handle
2049 */
2050static void
2051attr_iter_error (void *cls)
2052{
2053 struct Iterator *ai = cls;
2054
2055 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
2056 attr_iter_finished (ai);
2057}
2058
2059
2060/**
2061 * Got record. Return if it is an attribute.
2062 *
2063 * @param cls our attribute iterator
2064 * @param zone zone we are iterating
2065 * @param label label of the records
2066 * @param rd_count record count
2067 * @param rd records
2068 */
2069static void
2070attr_iter_cb (void *cls,
2071 const struct GNUNET_CRYPTO_PrivateKey *zone,
2072 const char *label,
2073 unsigned int rd_count,
2074 const struct GNUNET_GNSRECORD_Data *rd)
2075{
2076 struct Iterator *ai = cls;
2077 struct GNUNET_MQ_Envelope *env;
2078 struct GNUNET_CRYPTO_PublicKey identity;
2079 char *data_tmp;
2080 size_t key_len;
2081 ssize_t written;
2082
2083 if ((rd_count != 1) ||
2084 (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd->record_type))
2085 {
2086 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2087 return;
2088 }
2089 struct AttributeResultMessage *arm;
2090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
2091 label);
2092 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2093 "Sending ATTRIBUTE_RESULT message\n");
2094 GNUNET_CRYPTO_key_get_public (zone, &identity);
2095 key_len = GNUNET_CRYPTO_public_key_get_length (&identity);
2096 env = GNUNET_MQ_msg_extra (arm,
2097 rd->data_size + key_len,
2098 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2099 arm->id = htonl (ai->request_id);
2100 arm->attr_len = htons (rd->data_size);
2101 data_tmp = (char *) &arm[1];
2102 arm->pkey_len = htons (key_len);
2103 written = GNUNET_CRYPTO_write_public_key_to_buffer (&identity,
2104 data_tmp,
2105 key_len);
2106 GNUNET_assert (0 <= written);
2107 data_tmp += written;
2108 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
2109 GNUNET_MQ_send (ai->client->mq, env);
2110}
2111
2112
2113static enum GNUNET_GenericReturnValue
2114check_iteration_start (
2115 void *cls,
2116 const struct AttributeIterationStartMessage *ais_msg)
2117{
2118 uint16_t size;
2119 size_t key_len;
2120
2121 size = ntohs (ais_msg->header.size);
2122 key_len = ntohs (ais_msg->key_len);
2123
2124 if (size < key_len + sizeof(*ais_msg))
2125 {
2126 GNUNET_break (0);
2127 return GNUNET_SYSERR;
2128 }
2129 return GNUNET_OK;
2130}
2131
2132/**
2133 * Iterate over zone to get attributes
2134 *
2135 * @param cls our client
2136 * @param ais_msg the iteration message to start
2137 */
2138static void
2139handle_iteration_start (void *cls,
2140 const struct AttributeIterationStartMessage *ais_msg)
2141{
2142 struct IdpClient *idp = cls;
2143 struct Iterator *ai;
2144 struct GNUNET_CRYPTO_PrivateKey identity;
2145 size_t key_len;
2146 size_t read;
2147
2148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2149 "Received ATTRIBUTE_ITERATION_START message\n");
2150 key_len = ntohs (ais_msg->key_len);
2151 if ((GNUNET_SYSERR ==
2152 GNUNET_CRYPTO_read_private_key_from_buffer (&ais_msg[1],
2153 key_len,
2154 &identity,
2155 &read)) ||
2156 (read != key_len))
2157 {
2158 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2159 "Failed to read private key.\n");
2160 GNUNET_SERVICE_client_drop (idp->client);
2161 return;
2162 }
2163 ai = GNUNET_new (struct Iterator);
2164 ai->request_id = ntohl (ais_msg->id);
2165 ai->client = idp;
2166 ai->identity = identity;
2167
2168 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
2169 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
2170 &ai->identity,
2171 &attr_iter_error,
2172 ai,
2173 &attr_iter_cb,
2174 ai,
2175 &attr_iter_finished,
2176 ai);
2177 GNUNET_SERVICE_client_continue (idp->client);
2178}
2179
2180
2181/**
2182 * Handle iteration stop message from client
2183 *
2184 * @param cls the client
2185 * @param ais_msg the stop message
2186 */
2187static void
2188handle_iteration_stop (void *cls,
2189 const struct AttributeIterationStopMessage *ais_msg)
2190{
2191 struct IdpClient *idp = cls;
2192 struct Iterator *ai;
2193 uint32_t rid;
2194
2195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2196 "Received `%s' message\n",
2197 "ATTRIBUTE_ITERATION_STOP");
2198 rid = ntohl (ais_msg->id);
2199 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2200 if (ai->request_id == rid)
2201 break;
2202 if (NULL == ai)
2203 {
2204 GNUNET_break (0);
2205 GNUNET_SERVICE_client_drop (idp->client);
2206 return;
2207 }
2208 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
2209 GNUNET_free (ai);
2210 GNUNET_SERVICE_client_continue (idp->client);
2211}
2212
2213
2214/**
2215 * Client requests next attribute from iterator
2216 *
2217 * @param cls the client
2218 * @param ais_msg the message
2219 */
2220static void
2221handle_iteration_next (void *cls,
2222 const struct AttributeIterationNextMessage *ais_msg)
2223{
2224 struct IdpClient *idp = cls;
2225 struct Iterator *ai;
2226 uint32_t rid;
2227
2228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2229 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2230 rid = ntohl (ais_msg->id);
2231 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2232 if (ai->request_id == rid)
2233 break;
2234 if (NULL == ai)
2235 {
2236 GNUNET_break (0);
2237 GNUNET_SERVICE_client_drop (idp->client);
2238 return;
2239 }
2240 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2241 GNUNET_SERVICE_client_continue (idp->client);
2242}
2243
2244
2245/*************************************************
2246 * Credential iteration
2247 *************************************************/
2248
2249
2250/**
2251 * Done iterating over credentials
2252 *
2253 * @param cls our iterator handle
2254 */
2255static void
2256cred_iter_finished (void *cls)
2257{
2258 struct Iterator *ai = cls;
2259 struct GNUNET_MQ_Envelope *env;
2260 struct CredentialResultMessage *arm;
2261
2262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CREDENTIAL_RESULT message\n");
2263 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
2264 arm->id = htonl (ai->request_id);
2265 arm->credential_len = htons (0);
2266 arm->key_len = htons (0);
2267 GNUNET_MQ_send (ai->client->mq, env);
2268 GNUNET_CONTAINER_DLL_remove (ai->client->cred_iter_head,
2269 ai->client->cred_iter_tail,
2270 ai);
2271 GNUNET_free (ai);
2272}
2273
2274
2275/**
2276 * Error iterating over credentials. Abort.
2277 *
2278 * @param cls our attribute iteration handle
2279 */
2280static void
2281cred_iter_error (void *cls)
2282{
2283 struct Iterator *ai = cls;
2284
2285 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over credentials\n");
2286 cred_iter_finished (ai);
2287}
2288
2289
2290/**
2291 * Got record. Return credential.
2292 *
2293 * @param cls our attribute iterator
2294 * @param zone zone we are iterating
2295 * @param label label of the records
2296 * @param rd_count record count
2297 * @param rd records
2298 */
2299static void
2300cred_iter_cb (void *cls,
2301 const struct GNUNET_CRYPTO_PrivateKey *zone,
2302 const char *label,
2303 unsigned int rd_count,
2304 const struct GNUNET_GNSRECORD_Data *rd)
2305{
2306 struct Iterator *ai = cls;
2307 struct GNUNET_MQ_Envelope *env;
2308 struct CredentialResultMessage *arm;
2309 struct GNUNET_CRYPTO_PublicKey identity;
2310 char *data_tmp;
2311 size_t key_len;
2312 ssize_t written;
2313
2314 if ((rd_count != 1) ||
2315 (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL != rd->record_type))
2316 {
2317 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2318 return;
2319 }
2320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found credential under: %s\n",
2321 label);
2322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2323 "Sending CREDENTIAL_RESULT message\n");
2324 GNUNET_CRYPTO_key_get_public (zone, &identity);
2325 key_len = GNUNET_CRYPTO_public_key_get_length (&identity);
2326 env = GNUNET_MQ_msg_extra (arm,
2327 rd->data_size + key_len,
2328 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
2329 arm->id = htonl (ai->request_id);
2330 arm->credential_len = htons (rd->data_size);
2331 arm->key_len = htons (key_len);
2332 data_tmp = (char *) &arm[1];
2333 written = GNUNET_CRYPTO_write_public_key_to_buffer (&identity,
2334 data_tmp,
2335 key_len);
2336 GNUNET_assert (written >= 0);
2337 data_tmp += written;
2338 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
2339 GNUNET_MQ_send (ai->client->mq, env);
2340}
2341
2342static enum GNUNET_GenericReturnValue
2343check_credential_iteration_start (
2344 void *cls,
2345 const struct CredentialIterationStartMessage *cis_msg)
2346{
2347 uint16_t size;
2348 size_t key_len;
2349
2350 size = ntohs (cis_msg->header.size);
2351 key_len = ntohs (cis_msg->key_len);
2352
2353 if (size < key_len + sizeof(*cis_msg))
2354 {
2355 GNUNET_break (0);
2356 return GNUNET_SYSERR;
2357 }
2358 return GNUNET_OK;
2359}
2360
2361
2362/**
2363 * Iterate over zone to get attributes
2364 *
2365 * @param cls our client
2366 * @param ais_msg the iteration message to start
2367 */
2368static void
2369handle_credential_iteration_start (void *cls,
2370 const struct
2371 CredentialIterationStartMessage *ais_msg)
2372{
2373 struct IdpClient *idp = cls;
2374 struct Iterator *ai;
2375 struct GNUNET_CRYPTO_PrivateKey identity;
2376 size_t key_len;
2377 size_t read;
2378
2379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2380 "Received CREDENTIAL_ITERATION_START message\n");
2381 key_len = ntohs (ais_msg->key_len);
2382 if ((GNUNET_SYSERR ==
2383 GNUNET_CRYPTO_read_private_key_from_buffer (&ais_msg[1],
2384 key_len,
2385 &identity,
2386 &read)) ||
2387 (read != key_len))
2388 {
2389 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2390 "Failed to read private key.\n");
2391 GNUNET_SERVICE_client_drop (idp->client);
2392 return;
2393 }
2394 ai = GNUNET_new (struct Iterator);
2395 ai->request_id = ntohl (ais_msg->id);
2396 ai->client = idp;
2397 ai->identity = identity;
2398
2399 GNUNET_CONTAINER_DLL_insert (idp->cred_iter_head, idp->cred_iter_tail,
2400 ai);
2401 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
2402 &ai->identity,
2403 &cred_iter_error,
2404 ai,
2405 &cred_iter_cb,
2406 ai,
2407 &cred_iter_finished,
2408 ai);
2409 GNUNET_SERVICE_client_continue (idp->client);
2410}
2411
2412
2413/**
2414 * Handle iteration stop message from client
2415 *
2416 * @param cls the client
2417 * @param ais_msg the stop message
2418 */
2419static void
2420handle_credential_iteration_stop (void *cls,
2421 const struct
2422 CredentialIterationStopMessage *ais_msg)
2423{
2424 struct IdpClient *idp = cls;
2425 struct Iterator *ai;
2426 uint32_t rid;
2427
2428 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2429 "Received `%s' message\n",
2430 "CREDENTIAL_ITERATION_STOP");
2431 rid = ntohl (ais_msg->id);
2432 for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
2433 if (ai->request_id == rid)
2434 break;
2435 if (NULL == ai)
2436 {
2437 GNUNET_break (0);
2438 GNUNET_SERVICE_client_drop (idp->client);
2439 return;
2440 }
2441 GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
2442 ai);
2443 GNUNET_free (ai);
2444 GNUNET_SERVICE_client_continue (idp->client);
2445}
2446
2447
2448/**
2449 * Client requests next credential from iterator
2450 *
2451 * @param cls the client
2452 * @param ais_msg the message
2453 */
2454static void
2455handle_credential_iteration_next (void *cls,
2456 const struct
2457 CredentialIterationNextMessage *ais_msg)
2458{
2459 struct IdpClient *idp = cls;
2460 struct Iterator *ai;
2461 uint32_t rid;
2462
2463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2464 "Received CREDENTIAL_ITERATION_NEXT message\n");
2465 rid = ntohl (ais_msg->id);
2466 for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
2467 if (ai->request_id == rid)
2468 break;
2469 if (NULL == ai)
2470 {
2471 GNUNET_break (0);
2472 GNUNET_SERVICE_client_drop (idp->client);
2473 return;
2474 }
2475 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2476 GNUNET_SERVICE_client_continue (idp->client);
2477}
2478
2479
2480/******************************************************
2481 * Ticket iteration
2482 ******************************************************/
2483
2484/**
2485 * Got a ticket. Return to client
2486 *
2487 * @param cls our ticket iterator
2488 * @param ticket the ticket
2489 */
2490static void
2491ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
2492{
2493 struct TicketIteration *ti = cls;
2494 struct GNUNET_MQ_Envelope *env;
2495 struct TicketResultMessage *trm;
2496 size_t tkt_len;
2497
2498 if (NULL == ticket)
2499 tkt_len = 0;
2500 else
2501 tkt_len = GNUNET_RECLAIM_ticket_serialize_get_size (ticket);
2502
2503 env = GNUNET_MQ_msg_extra (trm,
2504 tkt_len,
2505 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
2506 if (NULL == ticket)
2507 {
2508 /* send empty response to indicate end of list */
2509 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2510 ti->client->ticket_iter_tail,
2511 ti);
2512 }
2513 else
2514 {
2515 GNUNET_RECLAIM_write_ticket_to_buffer (ticket,
2516 &trm[1],
2517 tkt_len);
2518 }
2519 trm->tkt_len = htons (tkt_len);
2520 trm->id = htonl (ti->r_id);
2521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
2522 GNUNET_MQ_send (ti->client->mq, env);
2523 if (NULL == ticket)
2524 GNUNET_free (ti);
2525}
2526
2527static enum GNUNET_GenericReturnValue
2528check_ticket_iteration_start (
2529 void *cls,
2530 const struct TicketIterationStartMessage *tis_msg)
2531{
2532 uint16_t size;
2533 size_t key_len;
2534
2535 size = ntohs (tis_msg->header.size);
2536 key_len = ntohs (tis_msg->key_len);
2537
2538 if (size < key_len + sizeof(*tis_msg))
2539 {
2540 GNUNET_break (0);
2541 return GNUNET_SYSERR;
2542 }
2543 return GNUNET_OK;
2544}
2545
2546/**
2547 * Client requests a ticket iteration
2548 *
2549 * @param cls the client
2550 * @param tis_msg the iteration request message
2551 */
2552static void
2553handle_ticket_iteration_start (
2554 void *cls,
2555 const struct TicketIterationStartMessage *tis_msg)
2556{
2557 struct GNUNET_CRYPTO_PrivateKey identity;
2558 struct IdpClient *client = cls;
2559 struct TicketIteration *ti;
2560 size_t key_len;
2561 size_t read;
2562
2563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2564 "Received TICKET_ITERATION_START message\n");
2565 key_len = ntohs (tis_msg->key_len);
2566 if ((GNUNET_SYSERR ==
2567 GNUNET_CRYPTO_read_private_key_from_buffer (&tis_msg[1],
2568 key_len,
2569 &identity,
2570 &read)) ||
2571 (read != key_len))
2572 {
2573 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2574 "Failed to read private key\n");
2575 GNUNET_SERVICE_client_drop (client->client);
2576 return;
2577 }
2578 ti = GNUNET_new (struct TicketIteration);
2579 ti->r_id = ntohl (tis_msg->id);
2580 ti->client = client;
2581 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2582 client->ticket_iter_tail,
2583 ti);
2584 ti->iter
2585 = RECLAIM_TICKETS_iteration_start (&identity, &ticket_iter_cb, ti);
2586 GNUNET_SERVICE_client_continue (client->client);
2587}
2588
2589
2590/**
2591 * Client has had enough tickets
2592 *
2593 * @param cls the client
2594 * @param tis_msg the stop message
2595 */
2596static void
2597handle_ticket_iteration_stop (void *cls,
2598 const struct TicketIterationStopMessage *tis_msg)
2599{
2600 struct IdpClient *client = cls;
2601 struct TicketIteration *ti;
2602 uint32_t rid;
2603
2604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2605 "Received `%s' message\n",
2606 "TICKET_ITERATION_STOP");
2607 rid = ntohl (tis_msg->id);
2608 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2609 if (ti->r_id == rid)
2610 break;
2611 if (NULL == ti)
2612 {
2613 GNUNET_break (0);
2614 GNUNET_SERVICE_client_drop (client->client);
2615 return;
2616 }
2617 RECLAIM_TICKETS_iteration_stop (ti->iter);
2618 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2619 client->ticket_iter_tail,
2620 ti);
2621 GNUNET_free (ti);
2622 GNUNET_SERVICE_client_continue (client->client);
2623}
2624
2625
2626/**
2627 * Client requests next result.
2628 *
2629 * @param cls the client
2630 * @param tis_msg the message
2631 */
2632static void
2633handle_ticket_iteration_next (void *cls,
2634 const struct TicketIterationNextMessage *tis_msg)
2635{
2636 struct IdpClient *client = cls;
2637 struct TicketIteration *ti;
2638 uint32_t rid;
2639
2640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2641 "Received TICKET_ITERATION_NEXT message\n");
2642 rid = ntohl (tis_msg->id);
2643 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2644 if (ti->r_id == rid)
2645 break;
2646 if (NULL == ti)
2647 {
2648 GNUNET_break (0);
2649 GNUNET_SERVICE_client_drop (client->client);
2650 return;
2651 }
2652 RECLAIM_TICKETS_iteration_next (ti->iter);
2653 GNUNET_SERVICE_client_continue (client->client);
2654}
2655
2656
2657/**
2658 * Main function that will be run
2659 *
2660 * @param cls closure
2661 * @param c the configuration used
2662 * @param server the service handle
2663 */
2664static void
2665run (void *cls,
2666 const struct GNUNET_CONFIGURATION_Handle *c,
2667 struct GNUNET_SERVICE_Handle *server)
2668{
2669 cfg = c;
2670
2671 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
2672 {
2673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2674 "Unable to initialize TICKETS subsystem.\n");
2675 GNUNET_SCHEDULER_shutdown ();
2676 return;
2677 }
2678 // Connect to identity and namestore services
2679 nsh = GNUNET_NAMESTORE_connect (cfg);
2680 if (NULL == nsh)
2681 {
2682 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
2683 "error connecting to namestore");
2684 }
2685
2686 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2687}
2688
2689
2690/**
2691 * Called whenever a client is disconnected.
2692 *
2693 * @param cls closure
2694 * @param client identification of the client
2695 * @param app_ctx @a client
2696 */
2697static void
2698client_disconnect_cb (void *cls,
2699 struct GNUNET_SERVICE_Client *client,
2700 void *app_ctx)
2701{
2702 struct IdpClient *idp = app_ctx;
2703
2704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
2705 GNUNET_CONTAINER_DLL_remove (client_list_head,
2706 client_list_tail,
2707 idp);
2708 cleanup_client (idp);
2709}
2710
2711
2712/**
2713 * Add a client to our list of active clients.
2714 *
2715 * @param cls NULL
2716 * @param client client to add
2717 * @param mq message queue for @a client
2718 * @return internal namestore client structure for this client
2719 */
2720static void *
2721client_connect_cb (void *cls,
2722 struct GNUNET_SERVICE_Client *client,
2723 struct GNUNET_MQ_Handle *mq)
2724{
2725 struct IdpClient *idp;
2726
2727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
2728 idp = GNUNET_new (struct IdpClient);
2729 idp->client = client;
2730 idp->mq = mq;
2731 GNUNET_CONTAINER_DLL_insert (client_list_head,
2732 client_list_tail,
2733 idp);
2734 return idp;
2735}
2736
2737
2738/**
2739 * Define "main" method using service macro.
2740 */
2741GNUNET_SERVICE_MAIN (
2742 "reclaim",
2743 GNUNET_SERVICE_OPTION_NONE,
2744 &run,
2745 &client_connect_cb,
2746 &client_disconnect_cb,
2747 NULL,
2748 GNUNET_MQ_hd_var_size (attribute_store_message,
2749 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2750 struct AttributeStoreMessage,
2751 NULL),
2752 GNUNET_MQ_hd_var_size (credential_store_message,
2753 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE,
2754 struct AttributeStoreMessage,
2755 NULL),
2756 GNUNET_MQ_hd_var_size (attribute_delete_message,
2757 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
2758 struct AttributeDeleteMessage,
2759 NULL),
2760 GNUNET_MQ_hd_var_size (credential_delete_message,
2761 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE,
2762 struct AttributeDeleteMessage,
2763 NULL),
2764 GNUNET_MQ_hd_var_size (iteration_start,
2765 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
2766 struct AttributeIterationStartMessage,
2767 NULL),
2768 GNUNET_MQ_hd_fixed_size (iteration_next,
2769 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
2770 struct AttributeIterationNextMessage,
2771 NULL),
2772 GNUNET_MQ_hd_fixed_size (iteration_stop,
2773 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2774 struct AttributeIterationStopMessage,
2775 NULL),
2776 GNUNET_MQ_hd_var_size (credential_iteration_start,
2777 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START,
2778 struct CredentialIterationStartMessage,
2779 NULL),
2780 GNUNET_MQ_hd_fixed_size (credential_iteration_next,
2781 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT,
2782 struct CredentialIterationNextMessage,
2783 NULL),
2784 GNUNET_MQ_hd_fixed_size (credential_iteration_stop,
2785 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP,
2786 struct CredentialIterationStopMessage,
2787 NULL),
2788
2789 GNUNET_MQ_hd_var_size (issue_ticket_message,
2790 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
2791 struct IssueTicketMessage,
2792 NULL),
2793 GNUNET_MQ_hd_var_size (consume_ticket_message,
2794 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
2795 struct ConsumeTicketMessage,
2796 NULL),
2797 GNUNET_MQ_hd_var_size (ticket_iteration_start,
2798 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
2799 struct TicketIterationStartMessage,
2800 NULL),
2801 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2802 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
2803 struct TicketIterationNextMessage,
2804 NULL),
2805 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2806 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
2807 struct TicketIterationStopMessage,
2808 NULL),
2809 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2810 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
2811 struct RevokeTicketMessage,
2812 NULL),
2813 GNUNET_MQ_handler_end ());
2814/* 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 689fbc429..000000000
--- a/src/reclaim/gnunet-service-reclaim_tickets.c
+++ /dev/null
@@ -1,1894 +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 "platform.h"
28#include <inttypes.h>
29#include "gnunet-service-reclaim_tickets.h"
30
31
32/**
33 * FIXME: the default ticket iteration interval should probably
34 * be the minimim attribute expiration.
35 */
36#define DEFAULT_TICKET_REFRESH_INTERVAL GNUNET_TIME_UNIT_HOURS
37
38/**
39 * Handle for a parallel GNS lookup job
40 * (Declaration further below)
41 */
42struct ParallelLookup;
43
44
45/**
46 * A reference to a ticket stored in GNS
47 */
48struct TicketReference
49{
50 /**
51 * DLL
52 */
53 struct TicketReference *next;
54
55 /**
56 * DLL
57 */
58 struct TicketReference *prev;
59
60 /**
61 * Attributes
62 */
63 struct GNUNET_RECLAIM_AttributeList *attrs;
64
65 /**
66 * Tickets
67 */
68 struct GNUNET_RECLAIM_Ticket ticket;
69};
70
71
72/**
73 * Handle to a consume operation
74 */
75struct RECLAIM_TICKETS_ConsumeHandle
76{
77 /**
78 * Ticket
79 */
80 struct GNUNET_RECLAIM_Ticket ticket;
81
82 /**
83 * LookupRequest
84 */
85 struct GNUNET_GNS_LookupRequest *lookup_request;
86
87 /**
88 * Audience Key
89 */
90 struct GNUNET_CRYPTO_PrivateKey identity;
91
92 /**
93 * Audience Key
94 */
95 struct GNUNET_CRYPTO_PublicKey identity_pub;
96
97 /**
98 * Lookup DLL
99 */
100 struct ParallelLookup *parallel_lookups_head;
101
102 /**
103 * Lookup DLL
104 */
105 struct ParallelLookup *parallel_lookups_tail;
106
107 /**
108 * Kill task
109 */
110 struct GNUNET_SCHEDULER_Task *kill_task;
111
112 /**
113 * Attributes
114 */
115 struct GNUNET_RECLAIM_AttributeList *attrs;
116
117 /**
118 * Presentations
119 */
120 struct GNUNET_RECLAIM_PresentationList *presentations;
121
122 /**
123 * Lookup time
124 */
125 struct GNUNET_TIME_Absolute lookup_start_time;
126
127 /**
128 * Callback
129 */
130 RECLAIM_TICKETS_ConsumeCallback cb;
131
132 /**
133 * Callback closure
134 */
135 void *cb_cls;
136};
137
138
139/**
140 * Handle for a parallel GNS lookup job
141 */
142struct ParallelLookup
143{
144 /* DLL */
145 struct ParallelLookup *next;
146
147 /* DLL */
148 struct ParallelLookup *prev;
149
150 /* The GNS request */
151 struct GNUNET_GNS_LookupRequest *lookup_request;
152
153 /* The handle the return to */
154 struct RECLAIM_TICKETS_ConsumeHandle *handle;
155
156 /**
157 * Lookup time
158 */
159 struct GNUNET_TIME_Absolute lookup_start_time;
160
161 /* The label to look up */
162 char *label;
163};
164
165
166/**
167 * Ticket issue request handle
168 */
169struct TicketIssueHandle
170{
171 /**
172 * Attributes to issue
173 */
174 struct GNUNET_RECLAIM_AttributeList *attrs;
175
176 /**
177 * Presentations to add
178 */
179 struct GNUNET_RECLAIM_PresentationList *presentations;
180
181 /**
182 * Issuer Key
183 */
184 struct GNUNET_CRYPTO_PrivateKey identity;
185
186 /**
187 * Ticket to issue
188 */
189 struct GNUNET_RECLAIM_Ticket ticket;
190
191 /**
192 * QueueEntry
193 */
194 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
195
196 /**
197 * Namestore Iterator
198 */
199 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
200
201 /**
202 * Callback
203 */
204 RECLAIM_TICKETS_TicketResult cb;
205
206 /**
207 * Callback cls
208 */
209 void *cb_cls;
210};
211
212
213/**
214 * Ticket iterator
215 */
216struct RECLAIM_TICKETS_Iterator
217{
218 /**
219 * Namestore queue entry
220 */
221 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
222
223 /**
224 * Iter callback
225 */
226 RECLAIM_TICKETS_TicketIter cb;
227
228 /**
229 * Iter cls
230 */
231 void *cb_cls;
232};
233
234
235struct RevokedAttributeEntry
236{
237 /**
238 * DLL
239 */
240 struct RevokedAttributeEntry *next;
241
242 /**
243 * DLL
244 */
245 struct RevokedAttributeEntry *prev;
246
247 /**
248 * Old ID of the attribute
249 */
250 struct GNUNET_RECLAIM_Identifier old_id;
251
252 /**
253 * New ID of the attribute
254 */
255 struct GNUNET_RECLAIM_Identifier new_id;
256};
257
258
259/**
260 * Ticket revocation request handle
261 */
262struct RECLAIM_TICKETS_RevokeHandle
263{
264 /**
265 * Issuer Key
266 */
267 struct GNUNET_CRYPTO_PrivateKey identity;
268
269 /**
270 * Callback
271 */
272 RECLAIM_TICKETS_RevokeCallback cb;
273
274 /**
275 * Callback cls
276 */
277 void *cb_cls;
278
279 /**
280 * Ticket to issue
281 */
282 struct GNUNET_RECLAIM_Ticket ticket;
283
284 /**
285 * QueueEntry
286 */
287 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
288
289 /**
290 * Namestore iterator
291 */
292 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
293
294 /**
295 * Revoked attributes
296 */
297 struct RevokedAttributeEntry *attrs_head;
298
299 /**
300 * Revoked attributes
301 */
302 struct RevokedAttributeEntry *attrs_tail;
303
304 /**
305 * Current attribute to move
306 */
307 struct RevokedAttributeEntry *move_attr;
308
309 /**
310 * Number of attributes in ticket
311 */
312 unsigned int ticket_attrs;
313
314 /**
315 * Tickets to update
316 */
317 struct TicketRecordsEntry *tickets_to_update_head;
318
319 /**
320 * Tickets to update
321 */
322 struct TicketRecordsEntry *tickets_to_update_tail;
323};
324
325
326/**
327 * Ticket expiration interval
328 */
329static struct GNUNET_TIME_Relative ticket_refresh_interval;
330
331
332/* Namestore handle */
333static struct GNUNET_NAMESTORE_Handle *nsh;
334
335
336/* GNS handle */
337static struct GNUNET_GNS_Handle *gns;
338
339
340/* Handle to the statistics service */
341static struct GNUNET_STATISTICS_Handle *stats;
342
343
344/**
345 * Cleanup revoke handle
346 *
347 * @param rh the ticket revocation handle
348 */
349static void
350cleanup_rvk (struct RECLAIM_TICKETS_RevokeHandle *rh)
351{
352 struct RevokedAttributeEntry *ae;
353 struct TicketRecordsEntry *le;
354
355 if (NULL != rh->ns_qe)
356 GNUNET_NAMESTORE_cancel (rh->ns_qe);
357 if (NULL != rh->ns_it)
358 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
359 while (NULL != (ae = rh->attrs_head))
360 {
361 GNUNET_CONTAINER_DLL_remove (rh->attrs_head, rh->attrs_tail, ae);
362 GNUNET_free (ae);
363 }
364 while (NULL != (le = rh->tickets_to_update_head))
365 {
366 GNUNET_CONTAINER_DLL_remove (rh->tickets_to_update_head,
367 rh->tickets_to_update_head,
368 le);
369 if (NULL != le->data)
370 GNUNET_free (le->data);
371 if (NULL != le->label)
372 GNUNET_free (le->label);
373 GNUNET_free (le);
374 }
375 GNUNET_free (rh);
376}
377
378
379/**
380 * For each ticket, store new, updated attribute references
381 * (Implementation further below)
382 *
383 * @param cls handle to the operation
384 */
385static void
386process_tickets (void *cls);
387
388
389/**
390 * Finished storing updated attribute references.
391 * Abort on error, else continue processing tickets
392 *
393 * @param cls handle to the operation
394 * @param success result of namestore operation
395 * @param emsg (NULL on success)
396 */
397static void
398ticket_processed (void *cls, enum GNUNET_ErrorCode ec)
399{
400 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
401
402 rvk->ns_qe = NULL;
403 GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
404}
405
406
407/**
408 * For each ticket, store new, updated attribute references
409 *
410 * @param cls handle to the operation
411 */
412static void
413process_tickets (void *cls)
414{
415 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
416 struct TicketRecordsEntry *le;
417 struct RevokedAttributeEntry *ae;
418
419 if (NULL == rvk->tickets_to_update_head)
420 {
421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
422 "Finished updatding tickets, success\n");
423 rvk->cb (rvk->cb_cls, GNUNET_OK);
424 cleanup_rvk (rvk);
425 return;
426 }
427 le = rvk->tickets_to_update_head;
428 GNUNET_CONTAINER_DLL_remove (rvk->tickets_to_update_head,
429 rvk->tickets_to_update_tail,
430 le);
431 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
432 if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
433 le->data,
434 le->rd_count,
435 rd))
436 {
437 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
438 "Unable to deserialize ticket record(s)\n");
439 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
440 cleanup_rvk (rvk);
441 return;
442 }
443 for (int i = 0; i < le->rd_count; i++)
444 {
445 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
446 continue;
447 for (ae = rvk->attrs_head; NULL != ae; ae = ae->next)
448 {
449 if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id)))
450 continue;
451 rd[i].data = &ae->new_id;
452 }
453 }
454 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
455 &rvk->identity,
456 le->label,
457 le->rd_count,
458 rd,
459 &ticket_processed,
460 rvk);
461 GNUNET_free (le->label);
462 GNUNET_free (le->data);
463 GNUNET_free (le);
464}
465
466
467/**
468 * Done collecting tickets. Start processing.
469 *
470 * @param cls handle to the operation
471 */
472static void
473rvk_ticket_update_finished (void *cls)
474{
475 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
476
477 rvk->ns_it = NULL;
478 GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
479}
480
481
482/**
483 * We need to update all other tickets with the new attribute IDs.
484 * We first collect them all. Processing after.
485 *
486 * @param cls handle to the operation
487 * @param zone ticket issuer private key
488 * @param label ticket rnd
489 * @param rd_count size of record set
490 * @param rd record set
491 */
492static void
493rvk_ticket_update (void *cls,
494 const struct GNUNET_CRYPTO_PrivateKey *zone,
495 const char *label,
496 unsigned int rd_count,
497 const struct GNUNET_GNSRECORD_Data *rd)
498{
499 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
500 struct TicketRecordsEntry *le;
501 struct RevokedAttributeEntry *ae;
502 int has_changed = GNUNET_NO;
503
504 /** Let everything point to the old record **/
505 for (int i = 0; i < rd_count; i++)
506 {
507 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
508 continue;
509 for (ae = rvk->attrs_head; NULL != ae; ae = ae->next)
510 {
511 if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id)))
512 continue;
513 has_changed = GNUNET_YES;
514 break;
515 }
516 if (GNUNET_YES == has_changed)
517 break;
518 }
519 if (GNUNET_YES == has_changed)
520 {
521 le = GNUNET_new (struct TicketRecordsEntry);
522 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
523 le->data = GNUNET_malloc (le->data_size);
524 le->rd_count = rd_count;
525 le->label = GNUNET_strdup (label);
526 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
527 GNUNET_CONTAINER_DLL_insert (rvk->tickets_to_update_head,
528 rvk->tickets_to_update_tail,
529 le);
530 }
531 GNUNET_NAMESTORE_zone_iterator_next (rvk->ns_it, 1);
532}
533
534
535/**
536 * Error iterating namestore. Abort.
537 *
538 * @param cls handle to the operation
539 */
540static void
541rvk_ns_iter_err (void *cls)
542{
543 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
544
545 rvk->ns_it = NULL;
546 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
547 cleanup_rvk (rvk);
548}
549
550
551/**
552 * Error storing new attribute in namestore. Abort
553 *
554 * @param cls handle to the operation
555 */
556static void
557rvk_ns_err (void *cls)
558{
559 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
560
561 rvk->ns_qe = NULL;
562 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
563 cleanup_rvk (rvk);
564}
565
566
567/**
568 * We change every attribute ID of the ticket attributes we
569 * want to revoke.
570 * When we are done, we need to update any other ticket which
571 * included references to any of the changed attributes.
572 *
573 * @param rh 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, enum GNUNET_ErrorCode ec)
601{
602 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
603
604 rvk->ns_qe = NULL;
605 if (GNUNET_EC_NONE != ec)
606 {
607 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
608 "Error removing attribute: %s\n",
609 GNUNET_ErrorCode_get_hint (ec));
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, enum GNUNET_ErrorCode ec)
630{
631 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
632 char *label;
633
634 rvk->ns_qe = NULL;
635 if (GNUNET_EC_NONE != ec)
636 {
637 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
638 "Error moving attribute: %s\n",
639 GNUNET_ErrorCode_get_hint (ec));
640 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
641 cleanup_rvk (rvk);
642 return;
643 }
644 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
645 sizeof(rvk->move_attr->old_id));
646 GNUNET_assert (NULL != label);
647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing attribute %s\n", label);
648 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
649 &rvk->identity,
650 label,
651 0,
652 NULL,
653 &del_attr_finished,
654 rvk);
655 GNUNET_free (label);
656}
657
658
659/**
660 * Got the referenced attribute. Updating the ID
661 *
662 * @param cls handle to the operation
663 * @param zone issuer identity
664 * @param label attribute ID
665 * @param rd_count size of record set (should be 1)
666 * @param rd record set (the attribute)
667 */
668static void
669rvk_move_attr_cb (void *cls,
670 const struct GNUNET_CRYPTO_PrivateKey *zone,
671 const char *label,
672 unsigned int rd_count,
673 const struct GNUNET_GNSRECORD_Data *rd)
674{
675 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
676 struct GNUNET_GNSRECORD_Data new_rd[rd_count];
677 struct RevokedAttributeEntry *le;
678 char *new_label;
679 char *attr_data;
680
681 rvk->ns_qe = NULL;
682 if (0 == rd_count)
683 {
684 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
685 "The claim %s no longer exists!\n",
686 label);
687 le = rvk->move_attr;
688 rvk->move_attr = le->next;
689 GNUNET_CONTAINER_DLL_remove (rvk->attrs_head, rvk->attrs_tail, le);
690 GNUNET_free (le);
691 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
692 return;
693 }
694 GNUNET_RECLAIM_id_generate (&rvk->move_attr->new_id);
695 new_label =
696 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
697 sizeof (rvk->move_attr->new_id));
698
699 attr_data = NULL;
700 // new_rd = *rd;
701 for (int i = 0; i < rd_count; i++)
702 {
703 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type)
704 {
705 /** find a new place for this attribute **/
706 struct GNUNET_RECLAIM_Attribute *claim;
707 GNUNET_RECLAIM_attribute_deserialize (rd[i].data,
708 rd[i].data_size,
709 &claim);
710 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
711 "Attribute to update: Name=%s\n",
712 claim->name);
713 claim->id = rvk->move_attr->new_id;
714 new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize_get_size (claim);
715 attr_data = GNUNET_malloc (rd[i].data_size);
716 new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize (claim,
717 attr_data);
718 new_rd[i].data = attr_data;
719 new_rd[i].record_type = rd[i].record_type;
720 new_rd[i].flags = rd[i].flags;
721 new_rd[i].expiration_time = rd[i].expiration_time;
722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
723 GNUNET_free (claim);
724 }
725 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
726 {
727 struct GNUNET_RECLAIM_Credential *credential;
728 credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
729 rd[i].data_size);
730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
731 "Credential to update: Name=%s\n",
732 credential->name);
733 credential->id = rvk->move_attr->new_id;
734 new_rd[i].data_size =
735 GNUNET_RECLAIM_credential_serialize_get_size (credential);
736 attr_data = GNUNET_malloc (rd[i].data_size);
737 new_rd[i].data_size = GNUNET_RECLAIM_credential_serialize (credential,
738 attr_data);
739 new_rd[i].data = attr_data;
740 new_rd[i].record_type = rd[i].record_type;
741 new_rd[i].flags = rd[i].flags;
742 new_rd[i].expiration_time = rd[i].expiration_time;
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n",
744 new_label);
745 GNUNET_free (credential);
746 }
747 else {
748 memcpy (&new_rd[i], &rd[i], sizeof (struct GNUNET_GNSRECORD_Data));
749 }
750 }
751 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
752 &rvk->identity,
753 new_label,
754 rd_count,
755 new_rd,
756 &move_attr_finished,
757 rvk);
758 GNUNET_free (new_label);
759 GNUNET_free (attr_data);
760}
761
762
763static void
764move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk)
765{
766 char *label;
767
768 if (NULL == rvk->move_attr)
769 {
770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished moving attributes\n");
771 rvk->ns_it =
772 GNUNET_NAMESTORE_zone_iteration_start (nsh,
773 &rvk->identity,
774 &rvk_ns_iter_err,
775 rvk,
776 &rvk_ticket_update,
777 rvk,
778 &rvk_ticket_update_finished,
779 rvk);
780 return;
781 }
782 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
783 sizeof (rvk->move_attr->old_id));
784 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving claim %s\n", label);
785
786 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
787 &rvk->identity,
788 label,
789 &rvk_ns_err,
790 rvk,
791 &rvk_move_attr_cb,
792 rvk);
793 GNUNET_free (label);
794}
795
796
797/**
798 * Finished deleting ticket and attribute references.
799 * Abort on failure.
800 * Else, we start changing every attribute ID in the
801 * found attribute references so that access is no longer
802 * possible.
803 *
804 * @param cls handle to the operation
805 * @param success Namestore operation return value
806 * @param emsg error message (NULL on success)
807 */
808static void
809remove_ticket_cont (void *cls, enum GNUNET_ErrorCode ec)
810{
811 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
812
813 rvk->ns_qe = NULL;
814 if (GNUNET_EC_NONE != ec)
815 {
816 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
817 GNUNET_ErrorCode_get_hint (ec));
818 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
819 cleanup_rvk (rvk);
820 return;
821 }
822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted ticket\n");
823 if (0 == rvk->ticket_attrs)
824 {
825 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
826 "No attributes to move... strange\n");
827 rvk->cb (rvk->cb_cls, GNUNET_OK);
828 cleanup_rvk (rvk);
829 return;
830 }
831 rvk->move_attr = rvk->attrs_head;
832 move_attrs (rvk);
833}
834
835
836/**
837 * We found the attribute references.
838 * Store them for later and remove the record set.
839 *
840 * @param cls handle to the operation
841 * @param zone the issuer key
842 * @param label ticket rnd
843 * @param rd_count size of record set
844 * @param rd record set
845 */
846static void
847revoke_attrs_cb (void *cls,
848 const struct GNUNET_CRYPTO_PrivateKey *zone,
849 const char *label,
850 unsigned int rd_count,
851 const struct GNUNET_GNSRECORD_Data *rd)
852
853{
854 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
855 struct RevokedAttributeEntry *le;
856
857 rvk->ns_qe = NULL;
858 /**
859 * Temporarily store attribute references.
860 * We need it later.
861 */
862 for (int i = 0; i < rd_count; i++)
863 {
864 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
865 continue;
866 le = GNUNET_new (struct RevokedAttributeEntry);
867 le->old_id = *((struct GNUNET_RECLAIM_Identifier *) rd[i].data);
868 GNUNET_CONTAINER_DLL_insert (rvk->attrs_head, rvk->attrs_tail, le);
869 rvk->ticket_attrs++;
870 }
871
872 /** Remove attribute references **/
873 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
874 &rvk->identity,
875 label,
876 0,
877 NULL,
878 &remove_ticket_cont,
879 rvk);
880}
881
882
883/**
884 * Failed to query namestore. Abort operation
885 *
886 * @param cls handle to the operation
887 */
888static void
889rvk_attrs_err_cb (void *cls)
890{
891 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
892
893 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
894 cleanup_rvk (rvk);
895}
896
897
898/**
899 * Revoke a ticket.
900 * We start by looking up attribute references in order
901 * to change attribute IDs.
902 *
903 * @param ticket ticket to revoke
904 * @param identity private key of issuer
905 * @param cb revocation status callback
906 * @param cb_cls callback closure
907 * @return handle to the operation
908 */
909struct RECLAIM_TICKETS_RevokeHandle *
910RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket,
911 const struct GNUNET_CRYPTO_PrivateKey *identity,
912 RECLAIM_TICKETS_RevokeCallback cb,
913 void *cb_cls)
914{
915 struct RECLAIM_TICKETS_RevokeHandle *rvk;
916 char *label;
917
918 rvk = GNUNET_new (struct RECLAIM_TICKETS_RevokeHandle);
919 rvk->cb = cb;
920 rvk->cb_cls = cb_cls;
921 rvk->identity = *identity;
922 rvk->ticket = *ticket;
923 GNUNET_CRYPTO_key_get_public (&rvk->identity, &rvk->ticket.identity);
924 /** Get shared attributes **/
925 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
926 sizeof(ticket->rnd));
927 GNUNET_assert (NULL != label);
928 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
929 identity,
930 label,
931 &rvk_attrs_err_cb,
932 rvk,
933 &revoke_attrs_cb,
934 rvk);
935 GNUNET_free (label);
936 return rvk;
937}
938
939
940/**
941 * Cancel a revocation.
942 *
943 * @param rh handle to the operation
944 */
945void
946RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh)
947{
948 GNUNET_assert (NULL != rh);
949 cleanup_rvk (rh);
950}
951
952
953/*******************************
954* Ticket consume
955*******************************/
956
957/**
958 * Cleanup ticket consume handle
959 *
960 * @param cth the handle to clean up
961 */
962static void
963cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
964{
965 struct ParallelLookup *lu;
966
967 if (NULL != cth->lookup_request)
968 GNUNET_GNS_lookup_cancel (cth->lookup_request);
969 if (NULL != cth->kill_task)
970 GNUNET_SCHEDULER_cancel (cth->kill_task);
971 while (NULL != (lu = cth->parallel_lookups_head))
972 {
973 if (NULL != lu->lookup_request)
974 GNUNET_GNS_lookup_cancel (lu->lookup_request);
975 GNUNET_free (lu->label);
976 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
977 cth->parallel_lookups_tail,
978 lu);
979 GNUNET_free (lu);
980 }
981
982 if (NULL != cth->attrs)
983 GNUNET_RECLAIM_attribute_list_destroy (cth->attrs);
984 if (NULL != cth->presentations)
985 GNUNET_RECLAIM_presentation_list_destroy (cth->presentations);
986 GNUNET_free (cth);
987}
988
989
990/**
991 * We found an attribute record.
992 *
993 * @param cls handle to the operation
994 * @param rd_count size of record set
995 * @param rd record set
996 */
997static void
998process_parallel_lookup_result (void *cls,
999 uint32_t rd_count,
1000 const struct GNUNET_GNSRECORD_Data *rd)
1001{
1002 struct ParallelLookup *parallel_lookup = cls;
1003 struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle;
1004 struct GNUNET_RECLAIM_AttributeListEntry *attr_le;
1005
1006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1007 "Parallel lookup finished (count=%u)\n",
1008 rd_count);
1009
1010 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
1011 cth->parallel_lookups_tail,
1012 parallel_lookup);
1013 GNUNET_free (parallel_lookup->label);
1014
1015 GNUNET_STATISTICS_update (stats,
1016 "attribute_lookup_time_total",
1017 GNUNET_TIME_absolute_get_duration (
1018 parallel_lookup->lookup_start_time)
1019 .rel_value_us,
1020 GNUNET_YES);
1021 GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES);
1022
1023
1024 GNUNET_free (parallel_lookup);
1025 if (0 == rd_count)
1026 GNUNET_break (0);
1027 // REMARK: It is possible now to find rd_count > 1
1028 for (int i = 0; i < rd_count; i++)
1029 {
1030 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type)
1031 continue;
1032 attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1033 GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size,
1034 &attr_le->attribute);
1035 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
1036 cth->attrs->list_tail,
1037 attr_le);
1038 }
1039 if (NULL != cth->parallel_lookups_head)
1040 return; // Wait for more
1041 /* Else we are done */
1042 cth->cb (cth->cb_cls, &cth->ticket.identity,
1043 cth->attrs, cth->presentations, GNUNET_OK, NULL);
1044 cleanup_cth (cth);
1045}
1046
1047
1048/**
1049 * Cancel the lookups for attribute records
1050 *
1051 * @param cls handle to the operation
1052 */
1053static void
1054abort_parallel_lookups (void *cls)
1055{
1056 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
1057 struct ParallelLookup *lu;
1058 struct ParallelLookup *tmp;
1059
1060 cth->kill_task = NULL;
1061 for (lu = cth->parallel_lookups_head; NULL != lu;)
1062 {
1063 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1064 GNUNET_free (lu->label);
1065 tmp = lu->next;
1066 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
1067 cth->parallel_lookups_tail,
1068 lu);
1069 GNUNET_free (lu);
1070 lu = tmp;
1071 }
1072 cth->cb (cth->cb_cls, NULL, NULL, NULL, GNUNET_SYSERR, "Aborted");
1073}
1074
1075
1076/**
1077 * GNS result with attribute references.
1078 * For each result, we start a (parallel) lookup of the actual
1079 * attribute record under the referenced label.
1080 *
1081 * @param cls handle to the operation
1082 * @param rd_count size of the record set
1083 * @param rd record set
1084 */
1085static void
1086lookup_authz_cb (void *cls,
1087 uint32_t rd_count,
1088 const struct GNUNET_GNSRECORD_Data *rd)
1089{
1090 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
1091 struct ParallelLookup *parallel_lookup;
1092 char *lbl;
1093 struct GNUNET_RECLAIM_PresentationListEntry *ale;
1094
1095 cth->lookup_request = NULL;
1096
1097 GNUNET_STATISTICS_update (stats,
1098 "reclaim_authz_lookup_time_total",
1099 GNUNET_TIME_absolute_get_duration (
1100 cth->lookup_start_time)
1101 .rel_value_us,
1102 GNUNET_YES);
1103 GNUNET_STATISTICS_update (stats,
1104 "reclaim_authz_lookups_count",
1105 1,
1106 GNUNET_YES);
1107
1108 for (int i = 0; i < rd_count; i++)
1109 {
1110 /**
1111 * Check if record is a credential presentation or an attribute
1112 * reference.
1113 */
1114 switch (rd[i].record_type)
1115 {
1116 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
1117 ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1118 ale->presentation =
1119 GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1120 rd[i].data_size);
1121 GNUNET_CONTAINER_DLL_insert (cth->presentations->list_head,
1122 cth->presentations->list_tail,
1123 ale);
1124 break;
1125 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
1126 lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
1127 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl);
1128 parallel_lookup = GNUNET_new (struct ParallelLookup);
1129 parallel_lookup->handle = cth;
1130 parallel_lookup->label = lbl;
1131 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
1132 parallel_lookup->lookup_request =
1133 GNUNET_GNS_lookup (gns,
1134 lbl,
1135 &cth->ticket.identity,
1136 GNUNET_GNSRECORD_TYPE_ANY,
1137 GNUNET_GNS_LO_DEFAULT,
1138 &process_parallel_lookup_result,
1139 parallel_lookup);
1140 GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
1141 cth->parallel_lookups_tail,
1142 parallel_lookup);
1143 break;
1144 default:
1145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1146 "Ignoring unknown record type %d", rd[i].record_type);
1147 }
1148 }
1149 /**
1150 * We started lookups. Add a timeout task.
1151 * FIXME: Really needed here?
1152 */
1153 if (NULL != cth->parallel_lookups_head)
1154 {
1155 cth->kill_task = GNUNET_SCHEDULER_add_delayed (
1156 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3),
1157 &abort_parallel_lookups,
1158 cth);
1159 return;
1160 }
1161 /**
1162 * No references found, return empty attribute list
1163 */
1164 cth->cb (cth->cb_cls, &cth->ticket.identity,
1165 cth->attrs, NULL, GNUNET_OK, NULL);
1166 cleanup_cth (cth);
1167}
1168
1169
1170/**
1171 * Consume a ticket.
1172 * We first looking attribute references under the label
1173 * ticket.rnd in GNS.
1174 *
1175 * @param id the audience of the ticket
1176 * @param ticket the ticket to consume
1177 * @param cb callback to call with attributes of ticket
1178 * @param cb_cls callback closure
1179 * @return handle to the operation
1180 */
1181struct RECLAIM_TICKETS_ConsumeHandle *
1182RECLAIM_TICKETS_consume (const struct GNUNET_CRYPTO_PrivateKey *id,
1183 const struct GNUNET_RECLAIM_Ticket *ticket,
1184 RECLAIM_TICKETS_ConsumeCallback cb,
1185 void *cb_cls)
1186{
1187 struct RECLAIM_TICKETS_ConsumeHandle *cth;
1188 char *label;
1189
1190 cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle);
1191
1192 cth->identity = *id;
1193 GNUNET_CRYPTO_key_get_public (&cth->identity, &cth->identity_pub);
1194 cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1195 cth->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1196 cth->ticket = *ticket;
1197 cth->cb = cb;
1198 cth->cb_cls = cb_cls;
1199 label =
1200 GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd,
1201 sizeof(cth->ticket.rnd));
1202 char *str = GNUNET_CRYPTO_public_key_to_string (&cth->ticket.identity);
1203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1204 "Looking for AuthZ info under %s in %s\n",
1205 label, str);
1206 GNUNET_free (str);
1207 cth->lookup_start_time = GNUNET_TIME_absolute_get ();
1208 cth->lookup_request =
1209 GNUNET_GNS_lookup (gns,
1210 label,
1211 &cth->ticket.identity,
1212 GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF,
1213 GNUNET_GNS_LO_DEFAULT,
1214 &lookup_authz_cb,
1215 cth);
1216 GNUNET_free (label);
1217 return cth;
1218}
1219
1220
1221/**
1222 * Cancel a consume operation
1223 *
1224 * @param cth the operation to cancel
1225 */
1226void
1227RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
1228{
1229 cleanup_cth (cth);
1230 return;
1231}
1232
1233
1234/*******************************
1235 * Ticket issue
1236 *******************************/
1237
1238/**
1239 * Cleanup ticket consume handle
1240 * @param handle the handle to clean up
1241 */
1242static void
1243cleanup_issue_handle (struct TicketIssueHandle *handle)
1244{
1245 if (NULL != handle->ns_qe)
1246 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1247 GNUNET_free (handle);
1248}
1249
1250
1251/**
1252 * Store finished, abort on error.
1253 * Else, return new ticket to caller.
1254 *
1255 * @param cls handle to the operation
1256 * @param success store operation result
1257 * @param emsg error message (or NULL on success)
1258 */
1259static void
1260store_ticket_issue_cont (void *cls, enum GNUNET_ErrorCode ec)
1261{
1262 struct TicketIssueHandle *handle = cls;
1263
1264 handle->ns_qe = NULL;
1265 if (GNUNET_EC_NONE != ec)
1266 {
1267 handle->cb (handle->cb_cls,
1268 &handle->ticket,
1269 NULL,
1270 GNUNET_SYSERR,
1271 "Error storing AuthZ ticket in GNS");
1272 return;
1273 }
1274 handle->cb (handle->cb_cls,
1275 &handle->ticket,
1276 handle->presentations,
1277 GNUNET_OK, NULL);
1278 cleanup_issue_handle (handle);
1279}
1280
1281
1282/**
1283 * Issue a new ticket.
1284 * We store references to attribute record labels and the ticket itself
1285 * under the label base64(ticket.rnd).
1286 *
1287 * @param ih handle to the operation containing relevant metadata
1288 */
1289static void
1290issue_ticket (struct TicketIssueHandle *ih)
1291{
1292 struct GNUNET_RECLAIM_AttributeListEntry *le;
1293 struct GNUNET_RECLAIM_PresentationListEntry *ple;
1294 struct GNUNET_GNSRECORD_Data *attrs_record;
1295 char *label;
1296 char *tkt_data;
1297 int i;
1298 int j;
1299 int attrs_count = 0;
1300
1301 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1302 attrs_count++;
1303
1304 // Worst case we have one presentation per attribute
1305 attrs_record =
1306 GNUNET_malloc (2 * attrs_count * sizeof(struct GNUNET_GNSRECORD_Data));
1307 i = 0;
1308 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1309 {
1310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1311 "Adding list entry: %s\n", le->attribute->name);
1312
1313 attrs_record[i].data = &le->attribute->id;
1314 attrs_record[i].data_size = sizeof(le->attribute->id);
1315 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1316 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF;
1317 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1318 i++;
1319 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
1320 {
1321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1322 "Attribute is backed by credential. Adding...\n");
1323 struct GNUNET_RECLAIM_Presentation *presentation = NULL;
1324 for (j = 0; j < i; j++)
1325 {
1326 if (attrs_record[j].record_type
1327 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
1328 continue;
1329 presentation = GNUNET_RECLAIM_presentation_deserialize (
1330 attrs_record[j].data,
1331 attrs_record[j].
1332 data_size);
1333 if (NULL == presentation)
1334 {
1335 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1336 "Failed to deserialize presentation\n");
1337 continue;
1338 }
1339 if (0 == memcmp (&presentation->credential_id,
1340 &le->attribute->credential,
1341 sizeof (le->attribute->credential)))
1342 break;
1343 GNUNET_free (presentation);
1344 presentation = NULL;
1345 }
1346 if (NULL != presentation)
1347 {
1348 GNUNET_free (presentation);
1349 continue; // Skip as we have already added this credential presentation.
1350 }
1351 for (ple = ih->presentations->list_head; NULL != ple; ple = ple->next)
1352 {
1353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1354 "Checking presentation....\n");
1355
1356 if (0 != memcmp (&le->attribute->credential,
1357 &ple->presentation->credential_id,
1358 sizeof (le->attribute->credential)))
1359 {
1360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1361 "Presentation does not match credential ID.\n");
1362 continue;
1363 }
1364 char *pres_buf;
1365 size_t pres_size;
1366
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_size =
1385 GNUNET_RECLAIM_ticket_serialize_get_size (&ih->ticket);
1386 tkt_data = GNUNET_malloc (attrs_record[i].data_size);
1387 GNUNET_RECLAIM_write_ticket_to_buffer (&ih->ticket,
1388 tkt_data,
1389 attrs_record[i].data_size);
1390 attrs_record[i].data = tkt_data;
1391 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1392 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET;
1393 attrs_record[i].flags =
1394 GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
1395 i++;
1396
1397 label =
1398 GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
1399 sizeof(ih->ticket.rnd));
1400 struct GNUNET_CRYPTO_PublicKey pub;
1401 GNUNET_CRYPTO_key_get_public (&ih->identity,
1402 &pub);
1403 char *str = GNUNET_CRYPTO_public_key_to_string (&pub);
1404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1405 "Storing AuthZ information under %s in %s\n", label, str);
1406 GNUNET_free (str);
1407 // Publish record
1408 ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1409 &ih->identity,
1410 label,
1411 i,
1412 attrs_record,
1413 &store_ticket_issue_cont,
1414 ih);
1415 for (j = 0; j < i; j++)
1416 {
1417 if (attrs_record[j].record_type
1418 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
1419 continue;
1420 // Yes, we are allowed to do this because we allocated it above
1421 char *ptr = (char*) attrs_record[j].data;
1422 GNUNET_free (ptr);
1423 }
1424 GNUNET_free (tkt_data);
1425 GNUNET_free (attrs_record);
1426 GNUNET_free (label);
1427}
1428
1429
1430/*************************************************
1431 * Ticket iteration (finding a specific ticket)
1432 *************************************************/
1433
1434
1435/**
1436 * Namestore error on issue. Abort.
1437 *
1438 * @param cls handle to the operation
1439 */
1440static void
1441filter_tickets_error_cb (void *cls)
1442{
1443 struct TicketIssueHandle *tih = cls;
1444
1445 tih->ns_it = NULL;
1446 tih->cb (tih->cb_cls,
1447 &tih->ticket,
1448 NULL,
1449 GNUNET_SYSERR,
1450 "Error storing AuthZ ticket in GNS");
1451 cleanup_issue_handle (tih);
1452}
1453
1454
1455/**
1456 * Iterator over records.
1457 * Check if any previously issued ticket already
1458 * matches what we need to prevent duplicates and
1459 * improve resolution synergy.
1460 *
1461 * @param cls handle to the operation
1462 * @param zone issuer identity
1463 * @param label ticket rnd
1464 * @param rd_count size of record set
1465 * @param rd record set
1466 */
1467static void
1468filter_tickets_cb (void *cls,
1469 const struct GNUNET_CRYPTO_PrivateKey *zone,
1470 const char *label,
1471 unsigned int rd_count,
1472 const struct GNUNET_GNSRECORD_Data *rd)
1473{
1474 struct TicketIssueHandle *tih = cls;
1475 struct GNUNET_RECLAIM_Ticket ticket;
1476 struct GNUNET_RECLAIM_Presentation *presentation;
1477 struct GNUNET_RECLAIM_PresentationList *ticket_presentations;
1478 struct GNUNET_RECLAIM_Credential *cred;
1479 struct GNUNET_RECLAIM_PresentationListEntry *ple;
1480 struct GNUNET_RECLAIM_AttributeListEntry *le;
1481 unsigned int attr_cnt = 0;
1482 unsigned int pres_cnt = 0;
1483 int ticket_found = GNUNET_NO;
1484
1485 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1486 {
1487 attr_cnt++;
1488 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
1489 pres_cnt++;
1490 }
1491
1492 // ticket search
1493 unsigned int found_attrs_cnt = 0;
1494 unsigned int found_pres_cnt = 0;
1495 size_t read;
1496 ticket_presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1497
1498 for (int i = 0; i < rd_count; i++)
1499 {
1500 // found ticket
1501 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET == rd[i].record_type)
1502 {
1503 if ((GNUNET_SYSERR ==
1504 GNUNET_RECLAIM_read_ticket_from_buffer (rd[i].data,
1505 rd[i].data_size,
1506 &ticket,
1507 &read)) ||
1508 (read != rd[i].data_size))
1509 {
1510 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1511 "Failed to deserialize ticket from record\n");
1512 continue;
1513 }
1514 // cmp audience
1515 // FIXME this is ugly, GNUNET_CRYPTO_PublicKey cannot be compared
1516 // like this
1517 if (0 == memcmp (&tih->ticket.audience,
1518 &ticket.audience,
1519 sizeof(struct GNUNET_CRYPTO_PublicKey)))
1520 {
1521 tih->ticket = ticket;
1522 ticket_found = GNUNET_YES;
1523 continue;
1524 }
1525 }
1526
1527 // cmp requested attributes with ticket attributes
1528 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1529 {
1530 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1531 {
1532 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1533 &le->attribute->id))
1534 found_attrs_cnt++;
1535 }
1536 }
1537 if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
1538 {
1539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1540 "Found credential...\n");
1541
1542 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1543 {
1544 cred = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
1545 rd[i].data_size);
1546 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (&cred->id,
1547 &le->attribute->credential))
1548 {
1549 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1550 "No match.\n");
1551 GNUNET_free (cred);
1552 continue;
1553 }
1554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1555 "Match, creating presentation...\n");
1556 if (GNUNET_OK != GNUNET_RECLAIM_credential_get_presentation (
1557 cred,
1558 tih->attrs,
1559 &presentation))
1560 {
1561 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1562 "Unable to retrieve presentation from credential\n");
1563 GNUNET_free (cred);
1564 continue;
1565 }
1566 ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1567 ple->presentation = presentation;
1568 GNUNET_CONTAINER_DLL_insert (tih->presentations->list_head,
1569 tih->presentations->list_tail,
1570 ple);
1571 GNUNET_free (cred);
1572 break;
1573 }
1574 }
1575 if (GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION == rd[i].record_type)
1576 {
1577 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1578 {
1579 presentation = GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1580 rd[i].data_size);
1581 if (NULL == presentation)
1582 {
1583 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1584 "Failed to deserialize presentation\n");
1585 continue;
1586 }
1587 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (
1588 &presentation->credential_id,
1589 &le->attribute->credential))
1590 {
1591 found_pres_cnt++;
1592 ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1593 ple->presentation = presentation;
1594 GNUNET_CONTAINER_DLL_insert (ticket_presentations->list_head,
1595 ticket_presentations->list_tail,
1596 ple);
1597 }
1598 }
1599 }
1600 }
1601
1602 /**
1603 * If we found a matching ticket, return that to the caller and
1604 * we are done.
1605 */
1606 if ((attr_cnt == found_attrs_cnt) &&
1607 (pres_cnt == found_pres_cnt) &&
1608 (GNUNET_YES == ticket_found))
1609 {
1610 GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it);
1611 tih->cb (tih->cb_cls, &tih->ticket, ticket_presentations, GNUNET_OK, NULL);
1612 GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
1613 cleanup_issue_handle (tih);
1614 return;
1615 }
1616 GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
1617 // ticket not found in current record, checking next record set
1618 GNUNET_NAMESTORE_zone_iterator_next (tih->ns_it, 1);
1619}
1620
1621
1622/**
1623 * Done iterating over tickets and we apparently did
1624 * not find an existing, matching ticket.
1625 * Continue by issuing a new ticket.
1626 *
1627 * @param cls handle to the operation
1628 */
1629static void
1630filter_tickets_finished_cb (void *cls)
1631{
1632 struct TicketIssueHandle *tih = cls;
1633
1634 GNUNET_CRYPTO_key_get_public (&tih->identity, &tih->ticket.identity);
1635 GNUNET_RECLAIM_id_generate (&tih->ticket.rnd);
1636 issue_ticket (tih);
1637}
1638
1639
1640/**
1641 * Issue a new reclaim ticket, thereby authorizing
1642 * the audience to access the set of provided attributes.
1643 *
1644 * @param identity the issuer
1645 * @param attrs the attributes to share
1646 * @param audience the audience to share the attributes with
1647 * @param cb the callback to call with the ticket result
1648 * @param cb_cls the callback closure
1649 * FIXME: Return handle??
1650 */
1651void
1652RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_PrivateKey *identity,
1653 const struct GNUNET_RECLAIM_AttributeList *attrs,
1654 const struct GNUNET_CRYPTO_PublicKey *audience,
1655 RECLAIM_TICKETS_TicketResult cb,
1656 void *cb_cls)
1657{
1658 struct TicketIssueHandle *tih;
1659
1660 tih = GNUNET_new (struct TicketIssueHandle);
1661 tih->cb = cb;
1662 tih->cb_cls = cb_cls;
1663 tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs);
1664 tih->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1665 tih->identity = *identity;
1666 tih->ticket.audience = *audience;
1667
1668 // First check whether the ticket has already been issued
1669 tih->ns_it =
1670 GNUNET_NAMESTORE_zone_iteration_start (nsh,
1671 &tih->identity,
1672 &filter_tickets_error_cb,
1673 tih,
1674 &filter_tickets_cb,
1675 tih,
1676 &filter_tickets_finished_cb,
1677 tih);
1678}
1679
1680
1681/************************************
1682 * Ticket iteration
1683 ************************************/
1684
1685/**
1686 * Cleanup ticket iterator
1687 *
1688 * @param iter handle to the iteration
1689 */
1690static void
1691cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter)
1692{
1693 if (NULL != iter->ns_it)
1694 GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it);
1695 GNUNET_free (iter);
1696}
1697
1698
1699/**
1700 * Return each record of type #GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET
1701 * to the caller and proceed with the iteration.
1702 * FIXME: Should we _not_ proceed automatically here?
1703 *
1704 * @param cls handle to the iteration
1705 * @param zone the ticket issuer
1706 * @param label the ticket rnd
1707 * @param rd_count number of records in record set
1708 * @param rd record set containing a ticket
1709 */
1710static void
1711collect_tickets_cb (void *cls,
1712 const struct GNUNET_CRYPTO_PrivateKey *zone,
1713 const char *label,
1714 unsigned int rd_count,
1715 const struct GNUNET_GNSRECORD_Data *rd)
1716{
1717 struct RECLAIM_TICKETS_Iterator *iter = cls;
1718 struct GNUNET_RECLAIM_Ticket ticket;
1719 size_t read;
1720
1721 for (int i = 0; i < rd_count; i++)
1722 {
1723 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET != rd[i].record_type)
1724 continue;
1725 if ((GNUNET_SYSERR ==
1726 GNUNET_RECLAIM_read_ticket_from_buffer (rd[i].data,
1727 rd[i].data_size,
1728 &ticket,
1729 &read)) ||
1730 (read != rd[i].data_size))
1731 {
1732 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1733 "Failed to deserialize ticket from record\n");
1734 continue;
1735 }
1736 iter->cb (iter->cb_cls, &ticket);
1737 return;
1738 }
1739 GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1);
1740}
1741
1742
1743/**
1744 * Signal ticket iteration has finished
1745 *
1746 * @param cls handle to the iteration
1747 */
1748static void
1749collect_tickets_finished_cb (void *cls)
1750{
1751 struct RECLAIM_TICKETS_Iterator *iter = cls;
1752
1753 iter->ns_it = NULL;
1754 iter->cb (iter->cb_cls, NULL);
1755 cleanup_iter (iter);
1756}
1757
1758
1759/**
1760 * Cancel ticket iteration on namestore error
1761 *
1762 * @param cls the iteration handle
1763 */
1764static void
1765collect_tickets_error_cb (void *cls)
1766{
1767 struct RECLAIM_TICKETS_Iterator *iter = cls;
1768
1769 iter->ns_it = NULL;
1770 iter->cb (iter->cb_cls, NULL);
1771 cleanup_iter (iter);
1772}
1773
1774
1775/**
1776 * Continue ticket iteration
1777 *
1778 * @param iter the iteration to continue
1779 */
1780void
1781RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter)
1782{
1783 GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1);
1784}
1785
1786
1787/**
1788 * Stop a running ticket iteration
1789 *
1790 * @param iter iteration to cancel
1791 */
1792void
1793RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter)
1794{
1795 GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it);
1796 cleanup_iter (iter);
1797}
1798
1799
1800/**
1801 * Iterate over all tickets issued by an identity
1802 *
1803 * @param identity the issuing identity
1804 * @param cb ticket callback function
1805 * @param cb_cls callback closure
1806 * @return a handle to the iteration
1807 */
1808struct RECLAIM_TICKETS_Iterator *
1809RECLAIM_TICKETS_iteration_start (
1810 const struct GNUNET_CRYPTO_PrivateKey *identity,
1811 RECLAIM_TICKETS_TicketIter cb,
1812 void *cb_cls)
1813{
1814 struct RECLAIM_TICKETS_Iterator *iter;
1815
1816 iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator);
1817 iter->cb = cb;
1818 iter->cb_cls = cb_cls;
1819 iter->ns_it =
1820 GNUNET_NAMESTORE_zone_iteration_start (nsh,
1821 identity,
1822 &collect_tickets_error_cb,
1823 iter,
1824 &collect_tickets_cb,
1825 iter,
1826 &collect_tickets_finished_cb,
1827 iter);
1828 return iter;
1829}
1830
1831
1832/**
1833 * Initialize tickets component
1834 *
1835 * @param c the configuration
1836 * @return GNUNET_SYSERR on error
1837 */
1838int
1839RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
1840{
1841 // Get ticket expiration time (relative) from config
1842 if (GNUNET_OK ==
1843 GNUNET_CONFIGURATION_get_value_time (c,
1844 "reclaim",
1845 "TICKET_REFRESH_INTERVAL",
1846 &ticket_refresh_interval))
1847 {
1848 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1849 "Configured refresh interval for tickets: %s\n",
1850 GNUNET_STRINGS_relative_time_to_string (ticket_refresh_interval,
1851 GNUNET_YES));
1852 }
1853 else
1854 {
1855 ticket_refresh_interval = DEFAULT_TICKET_REFRESH_INTERVAL;
1856 }
1857 // Connect to identity and namestore services
1858 nsh = GNUNET_NAMESTORE_connect (c);
1859 if (NULL == nsh)
1860 {
1861 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1862 "error connecting to namestore");
1863 return GNUNET_SYSERR;
1864 }
1865 gns = GNUNET_GNS_connect (c);
1866 if (NULL == gns)
1867 {
1868 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1869 return GNUNET_SYSERR;
1870 }
1871 stats = GNUNET_STATISTICS_create ("reclaim", c);
1872 return GNUNET_OK;
1873}
1874
1875
1876/**
1877 * Close handles and clean up.
1878 * FIXME: cancel all pending operations (gns, ns etc)
1879 */
1880void
1881RECLAIM_TICKETS_deinit (void)
1882{
1883 if (NULL != nsh)
1884 GNUNET_NAMESTORE_disconnect (nsh);
1885 nsh = NULL;
1886 if (NULL != gns)
1887 GNUNET_GNS_disconnect (gns);
1888 gns = NULL;
1889 if (NULL != stats)
1890 {
1891 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
1892 stats = NULL;
1893 }
1894}
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.h b/src/reclaim/gnunet-service-reclaim_tickets.h
deleted file mode 100644
index 0ec232f49..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_CRYPTO_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_CRYPTO_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_CRYPTO_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_CRYPTO_PrivateKey *identity,
224 const struct GNUNET_RECLAIM_AttributeList *attrs,
225 const struct GNUNET_CRYPTO_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_CRYPTO_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 b1ca7a4a5..000000000
--- a/src/reclaim/json_reclaim.c
+++ /dev/null
@@ -1,398 +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 GNUNET_free (data);
99 if ((NULL != cred_str) && (0 != strlen (cred_str)))
100 {
101 GNUNET_STRINGS_string_to_data (cred_str,
102 strlen (cred_str),
103 &attr->credential,
104 sizeof(attr->credential));
105 }
106 if ((NULL == id_str) || (0 == strlen (id_str)))
107 memset (&attr->id, 0, sizeof (attr->id));
108 else
109 GNUNET_STRINGS_string_to_data (id_str,
110 strlen (id_str),
111 &attr->id,
112 sizeof(attr->id));
113
114 *(struct GNUNET_RECLAIM_Attribute **) spec->ptr = attr;
115 return GNUNET_OK;
116}
117
118
119/**
120 * Cleanup data left from parsing RSA public key.
121 *
122 * @param cls closure, NULL
123 * @param[out] spec where to free the data
124 */
125static void
126clean_attr (void *cls, struct GNUNET_JSON_Specification *spec)
127{
128 struct GNUNET_RECLAIM_Attribute **attr;
129
130 attr = (struct GNUNET_RECLAIM_Attribute **) spec->ptr;
131 if (NULL != *attr)
132 {
133 GNUNET_free (*attr);
134 *attr = NULL;
135 }
136}
137
138
139/**
140 * JSON Specification for Reclaim claims.
141 *
142 * @param ticket struct of GNUNET_RECLAIM_Attribute to fill
143 * @return JSON Specification
144 */
145struct GNUNET_JSON_Specification
146GNUNET_RECLAIM_JSON_spec_attribute (struct GNUNET_RECLAIM_Attribute **attr)
147{
148 struct GNUNET_JSON_Specification ret = { .parser = &parse_attr,
149 .cleaner = &clean_attr,
150 .cls = NULL,
151 .field = NULL,
152 .ptr = attr,
153 .ptr_size = 0,
154 .size_ptr = NULL };
155
156 *attr = NULL;
157 return ret;
158}
159
160
161/**
162 * Parse given JSON object to a ticket
163 *
164 * @param cls closure, NULL
165 * @param root the json object representing data
166 * @param spec where to write the data
167 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
168 */
169static int
170parse_ticket (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
171{
172 struct GNUNET_RECLAIM_Ticket *ticket;
173 const char *rnd_str;
174 const char *aud_str;
175 const char *id_str;
176 int unpack_state;
177
178 GNUNET_assert (NULL != root);
179
180 if (! json_is_object (root))
181 {
182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
183 "Error json is not array nor object!\n");
184 return GNUNET_SYSERR;
185 }
186 // interpret single ticket
187 unpack_state = json_unpack (root,
188 "{s:s, s:s, s:s!}",
189 "rnd",
190 &rnd_str,
191 "audience",
192 &aud_str,
193 "issuer",
194 &id_str);
195 if (0 != unpack_state)
196 {
197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
198 "Error json object has a wrong format!\n");
199 return GNUNET_SYSERR;
200 }
201 ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
202 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (rnd_str,
203 strlen (rnd_str),
204 &ticket->rnd,
205 sizeof(ticket->rnd)))
206 {
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Rnd invalid\n");
208 GNUNET_free (ticket);
209 return GNUNET_SYSERR;
210 }
211 if (GNUNET_OK !=
212 GNUNET_STRINGS_string_to_data (id_str,
213 strlen (id_str),
214 &ticket->identity,
215 sizeof(ticket->identity)))
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(ticket->audience)))
227 {
228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audience invalid\n");
229 GNUNET_free (ticket);
230 return GNUNET_SYSERR;
231 }
232
233 *(struct GNUNET_RECLAIM_Ticket **) spec->ptr = ticket;
234 return GNUNET_OK;
235}
236
237
238/**
239 * Cleanup data left from parsing RSA public key.
240 *
241 * @param cls closure, NULL
242 * @param[out] spec where to free the data
243 */
244static void
245clean_ticket (void *cls, struct GNUNET_JSON_Specification *spec)
246{
247 struct GNUNET_RECLAIM_Ticket **ticket;
248
249 ticket = (struct GNUNET_RECLAIM_Ticket **) spec->ptr;
250 if (NULL != *ticket)
251 {
252 GNUNET_free (*ticket);
253 *ticket = NULL;
254 }
255}
256
257
258/**
259 * JSON Specification for Reclaim tickets.
260 *
261 * @param ticket struct of GNUNET_RECLAIM_Ticket to fill
262 * @return JSON Specification
263 */
264struct GNUNET_JSON_Specification
265GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket)
266{
267 struct GNUNET_JSON_Specification ret = { .parser = &parse_ticket,
268 .cleaner = &clean_ticket,
269 .cls = NULL,
270 .field = NULL,
271 .ptr = ticket,
272 .ptr_size = 0,
273 .size_ptr = NULL };
274
275 *ticket = NULL;
276 return ret;
277}
278
279
280/**
281 * Parse given JSON object to a credential claim
282 *
283 * @param cls closure, NULL
284 * @param root the json object representing data
285 * @param spec where to write the data
286 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
287 */
288static int
289parse_credential (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
290{
291 struct GNUNET_RECLAIM_Credential *cred;
292 const char *name_str = NULL;
293 const char *type_str = NULL;
294 const char *id_str = NULL;
295 json_t *val_json;
296 char *data = NULL;
297 char *val_str = NULL;
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:o!}",
313 "name",
314 &name_str,
315 "id",
316 &id_str,
317 "type",
318 &type_str,
319 "value",
320 &val_json);
321 if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_json) ||
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 if (json_is_string (val_json)) {
329 val_str = GNUNET_strdup (json_string_value (val_json));
330 } else {
331 val_str = json_dumps (val_json, JSON_COMPACT);
332 }
333 type = GNUNET_RECLAIM_credential_typename_to_number (type_str);
334 if (GNUNET_SYSERR ==
335 (GNUNET_RECLAIM_credential_string_to_value (type,
336 val_str,
337 (void **) &data,
338 &data_size)))
339 {
340 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Credential value invalid!\n");
341 return GNUNET_SYSERR;
342 }
343 cred = GNUNET_RECLAIM_credential_new (name_str, type, data, data_size);
344 GNUNET_free (data);
345 if ((NULL == id_str) || (0 == strlen (id_str)))
346 memset (&cred->id, 0, sizeof (cred->id));
347 else
348 GNUNET_STRINGS_string_to_data (id_str,
349 strlen (id_str),
350 &cred->id,
351 sizeof(cred->id));
352
353 *(struct GNUNET_RECLAIM_Credential **) spec->ptr = cred;
354 return GNUNET_OK;
355}
356
357
358/**
359 * Cleanup data left from parsing RSA public key.
360 *
361 * @param cls closure, NULL
362 * @param[out] spec where to free the data
363 */
364static void
365clean_credential (void *cls, struct GNUNET_JSON_Specification *spec)
366{
367 struct GNUNET_RECLAIM_Credential **attr;
368
369 attr = (struct GNUNET_RECLAIM_Credential **) spec->ptr;
370 if (NULL != *attr)
371 {
372 GNUNET_free (*attr);
373 *attr = NULL;
374 }
375}
376
377
378/**
379 * JSON Specification for credential claims.
380 *
381 * @param attr struct of GNUNET_RECLAIM_Credential to fill
382 * @return JSON Specification
383 */
384struct GNUNET_JSON_Specification
385GNUNET_RECLAIM_JSON_spec_credential (struct
386 GNUNET_RECLAIM_Credential **cred)
387{
388 struct GNUNET_JSON_Specification ret = { .parser = &parse_credential,
389 .cleaner = &clean_credential,
390 .cls = NULL,
391 .field = NULL,
392 .ptr = cred,
393 .ptr_size = 0,
394 .size_ptr = NULL };
395
396 *cred = NULL;
397 return ret;
398}
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/meson.build b/src/reclaim/meson.build
deleted file mode 100644
index fafc68a92..000000000
--- a/src/reclaim/meson.build
+++ /dev/null
@@ -1,144 +0,0 @@
1libgnunetreclaim_src = ['reclaim_api.c',
2 'reclaim_attribute.c',
3 'reclaim_credential.c']
4libgnunetdid_src = ['did_helper.c',
5 'did_core.c']
6
7gnunetservicereclaim_src = ['gnunet-service-reclaim.c',
8 'gnunet-service-reclaim_tickets.c']
9
10configure_file(input : 'reclaim.conf',
11 output : 'reclaim.conf',
12 configuration : cdata,
13 install: true,
14 install_dir: pkgcfgdir)
15
16
17if get_option('monolith')
18 foreach p : libgnunetreclaim_src + gnunetservicereclaim_src
19 gnunet_src += 'reclaim/' + p
20 endforeach
21 subdir_done()
22endif
23
24libgnunetreclaim = library('gnunetreclaim',
25 libgnunetreclaim_src,
26 soversion: '0',
27 version: '0.0.0',
28 dependencies: [libgnunetutil_dep,
29 libgnunetidentity_dep],
30 include_directories: [incdir, configuration_inc],
31 install: true,
32 install_dir: get_option('libdir'))
33libgnunetreclaim_dep = declare_dependency(link_with : libgnunetreclaim)
34pkg.generate(libgnunetreclaim, url: 'https://www.gnunet.org',
35 description : 'Provides API to access reclaimID')
36
37shared_module('gnunet_plugin_gnsrecord_reclaim',
38 ['plugin_gnsrecord_reclaim.c'],
39 dependencies: [libgnunetutil_dep, libgnunetgnsrecord_dep],
40 include_directories: [incdir, configuration_inc],
41 install: true,
42 install_dir: get_option('libdir')/'gnunet')
43
44libgnunetdid = library('gnunetdid',
45 libgnunetdid_src,
46 soversion: '0',
47 version: '0.0.0',
48 dependencies: [libgnunetutil_dep,
49 libgnunetnamestore_dep,
50 libgnunetgnsrecord_dep,
51 libgnunetgns_dep,
52 json_dep,
53 libgnunetidentity_dep],
54 include_directories: [incdir, configuration_inc],
55 install: true,
56 install_dir: get_option('libdir'))
57libgnunetdid_dep = declare_dependency(link_with : libgnunetdid)
58pkg.generate(libgnunetdid, url: 'https://www.gnunet.org',
59 description : 'Provides API to manipulate DID')
60
61shared_module('gnunet_plugin_rest_reclaim',
62 ['plugin_rest_reclaim.c', 'json_reclaim.c'],
63 dependencies: [libgnunetrest_dep,
64 libgnunetidentity_dep,
65 libgnunetreclaim_dep,
66 libgnunetjson_dep,
67 libgnunetutil_dep,
68 json_dep,
69 mhd_dep],
70 include_directories: [incdir, configuration_inc],
71 install: true,
72 install_dir: get_option('libdir') / 'gnunet')
73shared_module('gnunet_plugin_reclaim_attribute_basic',
74 ['plugin_reclaim_attribute_basic.c'],
75 dependencies: [libgnunetrest_dep,
76 libgnunetidentity_dep,
77 libgnunetreclaim_dep,
78 libgnunetjson_dep,
79 libgnunetutil_dep,
80 json_dep],
81 include_directories: [incdir, configuration_inc],
82 install: true,
83 install_dir: get_option('libdir') / 'gnunet')
84shared_module('gnunet_plugin_reclaim_credential_jwt',
85 ['plugin_reclaim_credential_jwt.c'],
86 dependencies: [libgnunetrest_dep,
87 libgnunetidentity_dep,
88 libgnunetreclaim_dep,
89 libgnunetjson_dep,
90 libgnunetutil_dep,
91 json_dep],
92 include_directories: [incdir, configuration_inc],
93 install: true,
94 install_dir: get_option('libdir') / 'gnunet')
95
96
97shared_module('gnunet_plugin_rest_openid_connect',
98 ['plugin_rest_openid_connect.c', 'oidc_helper.c'],
99 dependencies: [libgnunetrest_dep,
100 libgnunetreclaim_dep,
101 libgnunetidentity_dep,
102 libgnunetgns_dep,
103 libgnunetutil_dep,
104 jose_dep,
105 gcrypt_dep,
106 json_dep,
107 mhd_dep],
108 include_directories: [incdir, configuration_inc],
109 install: true,
110 install_dir: get_option('libdir') / 'gnunet')
111
112
113executable ('gnunet-reclaim',
114 'gnunet-reclaim.c',
115 dependencies: [libgnunetreclaim_dep,
116 libgnunetidentity_dep,
117 libgnunetutil_dep],
118 include_directories: [incdir, configuration_inc],
119 install: true,
120 install_dir: get_option('bindir'))
121executable ('gnunet-did',
122 'gnunet-did.c',
123 dependencies: [libgnunetreclaim_dep,
124 libgnunetdid_dep,
125 libgnunetgns_dep,
126 libgnunetnamestore_dep,
127 libgnunetidentity_dep,
128 libgnunetutil_dep],
129 include_directories: [incdir, configuration_inc],
130 install: true,
131 install_dir: get_option('bindir'))
132executable ('gnunet-service-reclaim',
133 gnunetservicereclaim_src,
134 dependencies: [libgnunetreclaim_dep,
135 libgnunetutil_dep,
136 libgnunetstatistics_dep,
137 libgnunetgnsrecord_dep,
138 libgnunetgns_dep,
139 libgnunetidentity_dep,
140 libgnunetnamestore_dep],
141 include_directories: [incdir, configuration_inc],
142 install: true,
143 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
144
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
deleted file mode 100644
index a2da7312b..000000000
--- a/src/reclaim/oidc_helper.c
+++ /dev/null
@@ -1,1026 +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 * @author Tristan Schwieren
26 */
27#include "platform.h"
28#include <inttypes.h>
29#include <jansson.h>
30#include <jose/jose.h>
31#include "gnunet_util_lib.h"
32#include "gnunet_reclaim_lib.h"
33#include "gnunet_reclaim_service.h"
34#include "gnunet_signatures.h"
35#include "oidc_helper.h"
36// #include "benchmark.h"
37#include <gcrypt.h>
38
39GNUNET_NETWORK_STRUCT_BEGIN
40
41/**
42 * The signature used to generate the authorization code
43 */
44struct OIDC_Parameters
45{
46 /**
47 * The reclaim ticket
48 */
49 struct GNUNET_RECLAIM_Ticket ticket;
50
51 /**
52 * The nonce length
53 */
54 uint32_t nonce_len GNUNET_PACKED;
55
56 /**
57 * The length of the PKCE code_challenge
58 */
59 uint32_t code_challenge_len GNUNET_PACKED;
60
61 /**
62 * The length of the attributes list
63 */
64 uint32_t attr_list_len GNUNET_PACKED;
65
66 /**
67 * The length of the presentation list
68 */
69 uint32_t pres_list_len GNUNET_PACKED;
70};
71
72GNUNET_NETWORK_STRUCT_END
73
74/**
75 * Standard claims represented by the "profile" scope in OIDC
76 */
77static char OIDC_profile_claims[14][32] = {
78 "name", "family_name", "given_name", "middle_name", "nickname",
79 "preferred_username", "profile", "picture", "website", "gender", "birthdate",
80 "zoneinfo", "locale", "updated_at"
81};
82
83/**
84 * Standard claims represented by the "email" scope in OIDC
85 */
86static char OIDC_email_claims[2][16] = {
87 "email", "email_verified"
88};
89
90/**
91 * Standard claims represented by the "phone" scope in OIDC
92 */
93static char OIDC_phone_claims[2][32] = {
94 "phone_number", "phone_number_verified"
95};
96
97/**
98 * Standard claims represented by the "address" scope in OIDC
99 */
100static char OIDC_address_claims[5][32] = {
101 "street_address", "locality", "region", "postal_code", "country"
102};
103
104static enum GNUNET_GenericReturnValue
105is_claim_in_address_scope (const char *claim)
106{
107 int i;
108 for (i = 0; i < 5; i++)
109 {
110 if (0 == strcmp (claim, OIDC_address_claims[i]))
111 {
112 return GNUNET_YES;
113 }
114 }
115 return GNUNET_NO;
116}
117
118
119static char *
120create_jwt_hmac_header (void)
121{
122 json_t *root;
123 char *json_str;
124
125 root = json_object ();
126 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE_HMAC));
127 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
128
129 json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
130 json_decref (root);
131 return json_str;
132}
133
134
135static void
136replace_char (char *str, char find, char replace)
137{
138 char *current_pos = strchr (str, find);
139
140 while (current_pos)
141 {
142 *current_pos = replace;
143 current_pos = strchr (current_pos, find);
144 }
145}
146
147
148// RFC4648
149static void
150fix_base64 (char *str)
151{
152 // Replace + with -
153 replace_char (str, '+', '-');
154
155 // Replace / with _
156 replace_char (str, '/', '_');
157}
158
159
160static json_t*
161generate_userinfo_json (const struct GNUNET_CRYPTO_PublicKey *sub_key,
162 const struct GNUNET_RECLAIM_AttributeList *attrs,
163 const struct
164 GNUNET_RECLAIM_PresentationList *presentations)
165{
166 struct GNUNET_RECLAIM_AttributeListEntry *le;
167 struct GNUNET_RECLAIM_PresentationListEntry *ple;
168 char *subject;
169 char *source_name;
170 char *attr_val_str;
171 char *pres_val_str;
172 json_t *body;
173 json_t *aggr_names;
174 json_t *aggr_sources;
175 json_t *aggr_sources_jwt;
176 json_t *addr_claim = NULL;
177 int num_presentations = 0;
178 for (le = attrs->list_head; NULL != le; le = le->next)
179 {
180 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
181 num_presentations++;
182 }
183
184 subject =
185 GNUNET_STRINGS_data_to_string_alloc (sub_key,
186 sizeof(struct
187 GNUNET_CRYPTO_PublicKey));
188 body = json_object ();
189 aggr_names = json_object ();
190 aggr_sources = json_object ();
191
192 // iss REQUIRED case sensitive server uri with https
193 // The issuer is the local reclaim instance (e.g.
194 // https://reclaim.id/api/openid)
195 json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
196 // sub REQUIRED public key identity, not exceed 255 ASCII length
197 json_object_set_new (body, "sub", json_string (subject));
198 GNUNET_free (subject);
199 pres_val_str = NULL;
200 source_name = NULL;
201 int i = 0;
202 for (ple = presentations->list_head; NULL != ple; ple = ple->next)
203 {
204 // New presentation
205 GNUNET_asprintf (&source_name,
206 "src%d",
207 i);
208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
209 "Adding new presentation source #%d\n", i);
210 aggr_sources_jwt = json_object ();
211 pres_val_str =
212 GNUNET_RECLAIM_presentation_value_to_string (ple->presentation->type,
213 ple->presentation->data,
214 ple->presentation->data_size);
215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
216 "Presentation is: %s\n", pres_val_str);
217 json_object_set_new (aggr_sources_jwt,
218 GNUNET_RECLAIM_presentation_number_to_typename (
219 ple->presentation->type),
220 json_string (pres_val_str) );
221 json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
222 GNUNET_free (pres_val_str);
223 GNUNET_free (source_name);
224 source_name = NULL;
225 i++;
226 }
227
228 int addr_is_aggregated = GNUNET_NO;
229 int addr_is_normal = GNUNET_NO;
230 for (le = attrs->list_head; NULL != le; le = le->next)
231 {
232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
233 "Processing %s for userinfo body\n",
234 le->attribute->name);
235 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
236 {
237 attr_val_str =
238 GNUNET_RECLAIM_attribute_value_to_string (le->attribute->type,
239 le->attribute->data,
240 le->attribute->data_size);
241 /**
242 * There is this weird quirk that the individual address claim(s) must be
243 * inside a JSON object of the "address" claim.
244 */
245 if (GNUNET_YES == is_claim_in_address_scope (le->attribute->name))
246 {
247 if (GNUNET_YES == addr_is_aggregated)
248 {
249 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
250 "Address is set as aggregated claim. Skipping self-issued value...\n");
251 GNUNET_free (attr_val_str);
252 continue;
253 }
254 addr_is_normal = GNUNET_YES;
255
256 if (NULL == addr_claim)
257 {
258 addr_claim = json_object ();
259 json_object_set_new (body, "address", addr_claim);
260 }
261 json_object_set_new (addr_claim, le->attribute->name,
262 json_string (attr_val_str));
263
264 }
265 else
266 {
267 json_object_set_new (body, le->attribute->name,
268 json_string (attr_val_str));
269 }
270 GNUNET_free (attr_val_str);
271 }
272 else
273 {
274 // Check if presentation is there
275 int j = 0;
276 for (ple = presentations->list_head; NULL != ple; ple = ple->next)
277 {
278 if (GNUNET_YES ==
279 GNUNET_RECLAIM_id_is_equal (&ple->presentation->credential_id,
280 &le->attribute->credential))
281 break;
282 j++;
283 }
284 if (NULL == ple)
285 {
286 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
287 "Presentation for `%s' missing...\n",
288 le->attribute->name);
289 continue;
290 }
291 /**
292 * There is this weird quirk that the individual address claim(s) must be
293 * inside a JSON object of the "address" claim.
294 */
295 if (GNUNET_YES == is_claim_in_address_scope (le->attribute->name))
296 {
297 if (GNUNET_YES == addr_is_normal)
298 {
299 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
300 "Address is already set as normal claim. Skipping attested value...\n");
301 continue;
302 }
303 addr_is_aggregated = GNUNET_YES;
304 /** This is/can only be set once! **/
305 if (NULL != addr_claim)
306 continue;
307 addr_claim = json_object ();
308 GNUNET_asprintf (&source_name,
309 "src%d",
310 j);
311 json_object_set_new (aggr_names, "address",
312 json_string (source_name));
313 GNUNET_free (source_name);
314 }
315 else
316 {
317 // Presentation exists, hence take the respective source str
318 GNUNET_asprintf (&source_name,
319 "src%d",
320 j);
321 json_object_set_new (aggr_names, le->attribute->name,
322 json_string (source_name));
323 GNUNET_free (source_name);
324 }
325 }
326 }
327 if (0 != i)
328 {
329 json_object_set_new (body, "_claim_names", aggr_names);
330 json_object_set_new (body, "_claim_sources", aggr_sources);
331 }
332
333 return body;
334}
335
336
337/**
338 * Generate userinfo JSON as string
339 *
340 * @param sub_key the subject (user)
341 * @param attrs user attribute list
342 * @param presentations credential presentation list (may be empty)
343 * @return Userinfo JSON
344 */
345char *
346OIDC_generate_userinfo (const struct GNUNET_CRYPTO_PublicKey *sub_key,
347 const struct GNUNET_RECLAIM_AttributeList *attrs,
348 const struct
349 GNUNET_RECLAIM_PresentationList *presentations)
350{
351 char *body_str;
352 json_t*body = generate_userinfo_json (sub_key,
353 attrs,
354 presentations);
355 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
356 json_decref (body);
357 return body_str;
358}
359
360
361char *
362generate_id_token_body (const struct GNUNET_CRYPTO_PublicKey *aud_key,
363 const struct GNUNET_CRYPTO_PublicKey *sub_key,
364 const struct GNUNET_RECLAIM_AttributeList *attrs,
365 const struct
366 GNUNET_RECLAIM_PresentationList *presentations,
367 const struct GNUNET_TIME_Relative *expiration_time,
368 const char *nonce)
369{
370 struct GNUNET_TIME_Absolute exp_time;
371 struct GNUNET_TIME_Absolute time_now;
372 json_t *body;
373 char *audience;
374 char *subject;
375 char *body_str;
376
377 body = generate_userinfo_json (sub_key,
378 attrs,
379 presentations);
380 // iat REQUIRED time now
381 time_now = GNUNET_TIME_absolute_get ();
382 // exp REQUIRED time expired from config
383 exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
384 // auth_time only if max_age
385 // nonce only if nonce
386 // OPTIONAL acr,amr,azp
387 subject =
388 GNUNET_STRINGS_data_to_string_alloc (sub_key,
389 sizeof(struct
390 GNUNET_CRYPTO_PublicKey));
391 audience =
392 GNUNET_STRINGS_data_to_string_alloc (aud_key,
393 sizeof(struct
394 GNUNET_CRYPTO_PublicKey));
395
396 // aud REQUIRED public key client_id must be there
397 json_object_set_new (body, "aud", json_string (audience));
398 // iat
399 json_object_set_new (body,
400 "iat",
401 json_integer (time_now.abs_value_us / (1000 * 1000)));
402 // exp
403 json_object_set_new (body,
404 "exp",
405 json_integer (exp_time.abs_value_us / (1000 * 1000)));
406 // nbf
407 json_object_set_new (body,
408 "nbf",
409 json_integer (time_now.abs_value_us / (1000 * 1000)));
410 // nonce
411 if (NULL != nonce)
412 json_object_set_new (body, "nonce", json_string (nonce));
413
414 // Error checking
415 body_str = json_dumps (body, JSON_INDENT (2) | JSON_COMPACT);
416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
417
418 json_decref (body);
419 GNUNET_free (subject);
420 GNUNET_free (audience);
421
422 return body_str;
423}
424
425
426char *
427OIDC_generate_id_token_rsa (const struct GNUNET_CRYPTO_PublicKey *aud_key,
428 const struct GNUNET_CRYPTO_PublicKey *sub_key,
429 const struct GNUNET_RECLAIM_AttributeList *attrs,
430 const struct
431 GNUNET_RECLAIM_PresentationList *presentations,
432 const struct GNUNET_TIME_Relative *expiration_time,
433 const char *nonce,
434 const json_t *secret_rsa_key)
435{
436 json_t *jws;
437 char *body_str;
438 char *result;
439
440 // Generate the body of the JSON Web Signature
441 body_str = generate_id_token_body (aud_key,
442 sub_key,
443 attrs,
444 presentations,
445 expiration_time,
446 nonce);
447
448 if (NULL == body_str)
449 {
450 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
451 "Body for the JWS could not be generated\n");
452 return NULL;
453 }
454
455 // Creating the JSON Web Signature.
456 jws = json_pack ("{s:o}", "payload",
457 jose_b64_enc (body_str, strlen (body_str)));
458 GNUNET_free (body_str);
459
460 if (! jose_jws_sig (NULL, jws, NULL, secret_rsa_key))
461 {
462 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
463 "Signature generation failed\n");
464 return NULL;
465 }
466
467 // Encoding JSON as compact JSON Web Signature
468 GNUNET_asprintf (&result, "%s.%s.%s",
469 json_string_value (json_object_get (jws, "protected")),
470 json_string_value (json_object_get (jws, "payload")),
471 json_string_value (json_object_get (jws, "signature")) );
472
473 json_decref (jws);
474 return result;
475}
476
477/**
478 * Create a JWT using HMAC (HS256) from attributes
479 *
480 * @param aud_key the public of the audience
481 * @param sub_key the public key of the subject
482 * @param attrs the attribute list
483 * @param presentations credential presentation list (may be empty)
484 * @param expiration_time the validity of the token
485 * @param secret_key the key used to sign the JWT
486 * @return a new base64-encoded JWT string.
487 */
488char *
489OIDC_generate_id_token_hmac (const struct GNUNET_CRYPTO_PublicKey *aud_key,
490 const struct GNUNET_CRYPTO_PublicKey *sub_key,
491 const struct GNUNET_RECLAIM_AttributeList *attrs,
492 const struct
493 GNUNET_RECLAIM_PresentationList *presentations,
494 const struct GNUNET_TIME_Relative *expiration_time,
495 const char *nonce,
496 const char *secret_key)
497{
498 struct GNUNET_HashCode signature;
499 char *header;
500 char *header_base64;
501 char *body_str;
502 char *body_base64;
503 char *signature_target;
504 char *signature_base64;
505 char *result;
506
507 // Generate and encode Header
508 header = create_jwt_hmac_header ();
509 if (NULL == header)
510 {
511 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
512 "Header for the JWS could not be generated\n");
513 return NULL;
514 }
515 GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
516 GNUNET_free (header);
517 fix_base64 (header_base64);
518
519 // Generate and encode the body of the JSON Web Signature
520 body_str = generate_id_token_body (aud_key,
521 sub_key,
522 attrs,
523 presentations,
524 expiration_time,
525 nonce);
526
527 if (NULL == body_str)
528 {
529 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
530 "Body for the JWS could not be generated\n");
531 GNUNET_free (header_base64);
532 return NULL;
533 }
534
535 GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
536 fix_base64 (body_base64);
537
538 /**
539 * Creating the JWT signature. This might not be
540 * standards compliant, check.
541 */
542 GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
543 GNUNET_CRYPTO_hmac_raw (secret_key,
544 strlen (secret_key),
545 signature_target,
546 strlen (signature_target),
547 &signature);
548 GNUNET_STRINGS_base64url_encode ((const char *) &signature,
549 sizeof(struct GNUNET_HashCode),
550 &signature_base64);
551 fix_base64 (signature_base64);
552
553 GNUNET_asprintf (&result,
554 "%s.%s.%s",
555 header_base64,
556 body_base64,
557 signature_base64);
558
559 GNUNET_free (header_base64);
560 GNUNET_free (body_str);
561 GNUNET_free (body_base64);
562 GNUNET_free (signature_target);
563 GNUNET_free (signature_base64);
564 return result;
565}
566
567
568/**
569 * Builds an OIDC authorization code including
570 * a reclaim ticket and nonce
571 *
572 * @param issuer the issuer of the ticket, used to sign the ticket and nonce
573 * @param ticket the ticket to include in the code
574 * @param attrs list of attributes which are shared
575 * @param presentations credential presentation list (may be empty)
576 * @param nonce the nonce to include in the code
577 * @param code_challenge PKCE code challenge
578 * @return a new authorization code (caller must free)
579 */
580char *
581OIDC_build_authz_code (const struct GNUNET_CRYPTO_PrivateKey *issuer,
582 const struct GNUNET_RECLAIM_Ticket *ticket,
583 const struct GNUNET_RECLAIM_AttributeList *attrs,
584 const struct
585 GNUNET_RECLAIM_PresentationList *presentations,
586 const char *nonce_str,
587 const char *code_challenge)
588{
589 struct OIDC_Parameters params;
590 char *code_payload;
591 char *payload;
592 char *tmp;
593 char *code_str;
594 char *buf_ptr = NULL;
595 size_t payload_len;
596 size_t code_payload_len;
597 size_t attr_list_len = 0;
598 size_t pres_list_len = 0;
599 size_t code_challenge_len = 0;
600 uint32_t nonce_len = 0;
601 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
602
603 /** PLAINTEXT **/
604 // Assign ticket
605 memset (&params, 0, sizeof(params));
606 params.ticket = *ticket;
607 // Assign nonce
608 payload_len = sizeof(struct OIDC_Parameters);
609 if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
610 {
611 nonce_len = strlen (nonce_str);
612 payload_len += nonce_len;
613 }
614 params.nonce_len = htonl (nonce_len);
615 // Assign code challenge
616 if (NULL != code_challenge)
617 code_challenge_len = strlen (code_challenge);
618 payload_len += code_challenge_len;
619 params.code_challenge_len = htonl (code_challenge_len);
620 // Assign attributes
621 if (NULL != attrs)
622 {
623 // Get length
624 attr_list_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
625 params.attr_list_len = htonl (attr_list_len);
626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
627 "Length of serialized attributes: %lu\n",
628 attr_list_len);
629 // Get serialized attributes
630 payload_len += attr_list_len;
631 }
632 if (NULL != presentations)
633 {
634 // Get length
635 // FIXME only add presentations relevant for attribute list!!!
636 // This is important because of the distinction between id_token and
637 // userinfo in OIDC
638 pres_list_len =
639 GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
640 params.pres_list_len = htonl (pres_list_len);
641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
642 "Length of serialized presentations: %lu\n",
643 pres_list_len);
644 // Get serialized attributes
645 payload_len += pres_list_len;
646 }
647
648 // Get plaintext length
649 payload = GNUNET_malloc (payload_len);
650 memcpy (payload, &params, sizeof(params));
651 tmp = payload + sizeof(params);
652 if (0 < code_challenge_len)
653 {
654 memcpy (tmp, code_challenge, code_challenge_len);
655 tmp += code_challenge_len;
656 }
657 if (0 < nonce_len)
658 {
659 memcpy (tmp, nonce_str, nonce_len);
660 tmp += nonce_len;
661 }
662 if (0 < attr_list_len)
663 GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp);
664 tmp += attr_list_len;
665 if (0 < pres_list_len)
666 GNUNET_RECLAIM_presentation_list_serialize (presentations, tmp);
667 tmp += pres_list_len;
668
669 /** END **/
670
671 // Get length
672 code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
673 + payload_len + sizeof(struct
674 GNUNET_CRYPTO_Signature);
675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
676 "Length of data to encode: %lu\n",
677 code_payload_len);
678
679 // Initialize code payload
680 code_payload = GNUNET_malloc (code_payload_len);
681 GNUNET_assert (NULL != code_payload);
682 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
683 purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
684 + payload_len);
685 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
686 // Store pubkey
687 buf_ptr = (char *) &purpose[1];
688 memcpy (buf_ptr, payload, payload_len);
689 GNUNET_free (payload);
690 buf_ptr += payload_len;
691 // Sign and store signature
692 if (GNUNET_SYSERR ==
693 GNUNET_CRYPTO_sign_ (issuer,
694 purpose,
695 (struct GNUNET_CRYPTO_Signature *)
696 buf_ptr))
697 {
698 GNUNET_break (0);
699 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
700 GNUNET_free (code_payload);
701 return NULL;
702 }
703 GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
704 GNUNET_free (code_payload);
705 return code_str;
706}
707
708
709enum GNUNET_GenericReturnValue
710check_code_challenge (const char *code_challenge,
711 uint32_t code_challenge_len,
712 const char *code_verifier)
713{
714 char *code_verifier_hash;
715 char *expected_code_challenge;
716
717 if (0 == code_challenge_len) /* Only check if this code requires a CV */
718 return GNUNET_OK;
719 if (NULL == code_verifier)
720 {
721 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
722 "Expected code verifier!\n");
723 return GNUNET_SYSERR;
724 }
725 code_verifier_hash = GNUNET_malloc (256 / 8);
726 // hash code verifier
727 gcry_md_hash_buffer (GCRY_MD_SHA256,
728 code_verifier_hash,
729 code_verifier,
730 strlen (code_verifier));
731 // encode code verifier
732 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
733 &expected_code_challenge);
734 GNUNET_free (code_verifier_hash);
735 if (0 !=
736 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
737 {
738 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
739 "Invalid code verifier! Expected: %s, Got: %.*s\n",
740 expected_code_challenge,
741 code_challenge_len,
742 code_challenge);
743 GNUNET_free (expected_code_challenge);
744 return GNUNET_SYSERR;
745 }
746 GNUNET_free (expected_code_challenge);
747 return GNUNET_OK;
748}
749
750
751/**
752 * Parse reclaim ticket and nonce from
753 * authorization code.
754 * This also verifies the signature in the code.
755 *
756 * @param audience the expected audience of the code
757 * @param code the string representation of the code
758 * @param code_verfier PKCE code verifier. Optional, must be provided
759 * if used in request.
760 * @param ticket where to store the ticket
761 * @param attrs the attributes in the code
762 * @param presentations credential presentation list
763 * @param nonce_str where to store the nonce (if contained)
764 * @return GNUNET_OK if successful, else GNUNET_SYSERR
765 */
766int
767OIDC_parse_authz_code (const struct GNUNET_CRYPTO_PublicKey *audience,
768 const char *code,
769 const char *code_verifier,
770 struct GNUNET_RECLAIM_Ticket *ticket,
771 struct GNUNET_RECLAIM_AttributeList **attrs,
772 struct GNUNET_RECLAIM_PresentationList **presentations,
773 char **nonce_str,
774 enum OIDC_VerificationOptions opts)
775{
776 char *code_payload;
777 char *ptr;
778 char *plaintext;
779 char *attrs_ser;
780 char *presentations_ser;
781 char *code_challenge;
782 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
783 struct GNUNET_CRYPTO_Signature *signature;
784 uint32_t code_challenge_len;
785 uint32_t attrs_ser_len;
786 uint32_t pres_ser_len;
787 size_t plaintext_len;
788 size_t code_payload_len;
789 uint32_t nonce_len = 0;
790 struct OIDC_Parameters *params;
791
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
793 code_payload = NULL;
794 code_payload_len =
795 GNUNET_STRINGS_base64url_decode (code, strlen (code),
796 (void **) &code_payload);
797 if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
798 + sizeof(struct OIDC_Parameters)
799 + sizeof(struct GNUNET_CRYPTO_Signature))
800 {
801 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
802 GNUNET_free (code_payload);
803 return GNUNET_SYSERR;
804 }
805
806 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
807 plaintext_len = code_payload_len;
808 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
809 ptr = (char *) &purpose[1];
810 plaintext_len -= sizeof(struct GNUNET_CRYPTO_Signature);
811 plaintext = ptr;
812 ptr += plaintext_len;
813 signature = (struct GNUNET_CRYPTO_Signature *) ptr;
814 params = (struct OIDC_Parameters *) plaintext;
815
816 // cmp code_challenge code_verifier
817 code_challenge_len = ntohl (params->code_challenge_len);
818 code_challenge = ((char *) &params[1]);
819 if (! (opts & OIDC_VERIFICATION_NO_CODE_VERIFIER))
820 {
821 if (GNUNET_OK != check_code_challenge (code_challenge,
822 code_challenge_len,
823 code_verifier))
824 {
825 GNUNET_free (code_payload);
826 return GNUNET_SYSERR;
827 }
828 }
829 nonce_len = ntohl (params->nonce_len);
830 if (0 != nonce_len)
831 {
832 *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
833 nonce_len);
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
835 }
836
837 // Ticket
838 memcpy (ticket, &params->ticket, sizeof(params->ticket));
839 // Signature
840 // GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
841 if (0 != GNUNET_memcmp (audience, &ticket->audience))
842 {
843 GNUNET_free (code_payload);
844 if (NULL != *nonce_str)
845 GNUNET_free (*nonce_str);
846 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
847 "Audience in ticket does not match client!\n");
848 return GNUNET_SYSERR;
849 }
850 if (GNUNET_OK !=
851 GNUNET_CRYPTO_signature_verify_ (
852 GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN,
853 purpose,
854 signature,
855 &(ticket->identity)))
856 {
857 GNUNET_free (code_payload);
858 if (NULL != *nonce_str)
859 GNUNET_free (*nonce_str);
860 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
861 return GNUNET_SYSERR;
862 }
863 // Attributes
864 attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
865 attrs_ser_len = ntohl (params->attr_list_len);
866 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
867 presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
868 pres_ser_len = ntohl (params->pres_list_len);
869 *presentations =
870 GNUNET_RECLAIM_presentation_list_deserialize (presentations_ser,
871 pres_ser_len);
872
873 GNUNET_free (code_payload);
874 return GNUNET_OK;
875}
876
877
878/**
879 * Build a token response for a token request
880 * TODO: Maybe we should add the scope here?
881 *
882 * @param access_token the access token to include
883 * @param id_token the id_token to include
884 * @param expiration_time the expiration time of the token(s)
885 * @param token_response where to store the response
886 */
887void
888OIDC_build_token_response (const char *access_token,
889 const char *id_token,
890 const struct GNUNET_TIME_Relative *expiration_time,
891 char **token_response)
892{
893 json_t *root_json;
894
895 root_json = json_object ();
896
897 GNUNET_assert (NULL != access_token);
898 GNUNET_assert (NULL != id_token);
899 GNUNET_assert (NULL != expiration_time);
900 json_object_set_new (root_json, "access_token", json_string (access_token));
901 json_object_set_new (root_json, "token_type", json_string ("Bearer"));
902 json_object_set_new (root_json,
903 "expires_in",
904 json_integer (expiration_time->rel_value_us
905 / (1000 * 1000)));
906 json_object_set_new (root_json, "id_token", json_string (id_token));
907 *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
908 json_decref (root_json);
909}
910
911
912/**
913 * Generate a new access token
914 */
915char *
916OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket)
917{
918 char *access_token;
919
920 GNUNET_STRINGS_base64_encode (ticket,
921 sizeof(*ticket),
922 &access_token);
923 return access_token;
924}
925
926
927/**
928 * Parse an access token
929 */
930int
931OIDC_access_token_parse (const char *token,
932 struct GNUNET_RECLAIM_Ticket **ticket)
933{
934 size_t sret;
935 char *decoded;
936 sret = GNUNET_STRINGS_base64_decode (token,
937 strlen (token),
938 (void**) &decoded);
939 if (sizeof (struct GNUNET_RECLAIM_Ticket) != sret)
940 {
941 GNUNET_free (decoded);
942 return GNUNET_SYSERR;
943 }
944 *ticket = (struct GNUNET_RECLAIM_Ticket *) decoded;
945 return GNUNET_OK;
946}
947
948
949/**
950 * Checks if a claim is implicitly requested through standard
951 * scope(s) or explicitly through non-standard scope.
952 *
953 * @param scopes the scopes which have been requested
954 * @param attr the attribute name to check
955 * @return GNUNET_YES if attribute is implcitly requested
956 */
957enum GNUNET_GenericReturnValue
958OIDC_check_scopes_for_claim_request (const char*scopes,
959 const char*attr)
960{
961 char *scope_variables;
962 char *scope_variable;
963 char delimiter[] = " ";
964 int i;
965
966 scope_variables = GNUNET_strdup (scopes);
967 scope_variable = strtok (scope_variables, delimiter);
968 while (NULL != scope_variable)
969 {
970 if (0 == strcmp ("profile", scope_variable))
971 {
972 for (i = 0; i < 14; i++)
973 {
974 if (0 == strcmp (attr, OIDC_profile_claims[i]))
975 {
976 GNUNET_free (scope_variables);
977 return GNUNET_YES;
978 }
979 }
980 }
981 else if (0 == strcmp ("address", scope_variable))
982 {
983 for (i = 0; i < 5; i++)
984 {
985 if (0 == strcmp (attr, OIDC_address_claims[i]))
986 {
987 GNUNET_free (scope_variables);
988 return GNUNET_YES;
989 }
990 }
991 }
992 else if (0 == strcmp ("email", scope_variable))
993 {
994 for (i = 0; i < 2; i++)
995 {
996 if (0 == strcmp (attr, OIDC_email_claims[i]))
997 {
998 GNUNET_free (scope_variables);
999 return GNUNET_YES;
1000 }
1001 }
1002 }
1003 else if (0 == strcmp ("phone", scope_variable))
1004 {
1005 for (i = 0; i < 2; i++)
1006 {
1007 if (0 == strcmp (attr, OIDC_phone_claims[i]))
1008 {
1009 GNUNET_free (scope_variables);
1010 return GNUNET_YES;
1011 }
1012 }
1013
1014 }
1015 else if (0 == strcmp (attr, scope_variable))
1016 {
1017 /** attribute matches requested scope **/
1018 GNUNET_free (scope_variables);
1019 return GNUNET_YES;
1020 }
1021 scope_variable = strtok (NULL, delimiter);
1022 }
1023 GNUNET_free (scope_variables);
1024 return GNUNET_NO;
1025
1026}
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
deleted file mode 100644
index de788fbdb..000000000
--- a/src/reclaim/oidc_helper.h
+++ /dev/null
@@ -1,196 +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#define JWT_TYP "typ"
32#define JWT_TYP_VALUE "jwt"
33
34#define JWT_ALG_VALUE_HMAC "HS512"
35#define JWT_ALG_VALUE_RSA "RS256"
36
37#define SERVER_ADDRESS "http://localhost:7776"
38
39enum OIDC_VerificationOptions
40{
41 /**
42 * Strict verification
43 */
44 OIDC_VERIFICATION_DEFAULT = 0,
45
46 /**
47 * Do not check code verifier even if expected
48 */
49 OIDC_VERIFICATION_NO_CODE_VERIFIER = 1
50};
51
52/**
53 * Create a JWT using RSA256 algorithm from attributes
54 *
55 * @param aud_key the public of the audience
56 * @param sub_key the public key of the subject
57 * @param attrs the attribute list
58 * @param presentations credential presentation list (may be empty)
59 * @param expiration_time the validity of the token
60 * @param secret_rsa_key the key used to sign the JWT
61 * @return a new base64-encoded JWT string.
62 */
63char *
64OIDC_generate_id_token_rsa (const struct GNUNET_CRYPTO_PublicKey *aud_key,
65 const struct GNUNET_CRYPTO_PublicKey *sub_key,
66 const struct GNUNET_RECLAIM_AttributeList *attrs,
67 const struct
68 GNUNET_RECLAIM_PresentationList *presentations,
69 const struct GNUNET_TIME_Relative *expiration_time,
70 const char *nonce,
71 const json_t *secret_rsa_key);
72
73/**
74 * Create a JWT using HMAC (HS256) from attributes
75 *
76 * @param aud_key the public of the audience
77 * @param sub_key the public key of the subject
78 * @param attrs the attribute list
79 * @param presentations credential presentation list (may be empty)
80 * @param expiration_time the validity of the token
81 * @param secret_key the key used to sign the JWT
82 * @return a new base64-encoded JWT string.
83 */
84char*
85OIDC_generate_id_token_hmac (const struct GNUNET_CRYPTO_PublicKey *aud_key,
86 const struct GNUNET_CRYPTO_PublicKey *sub_key,
87 const struct GNUNET_RECLAIM_AttributeList *attrs,
88 const struct
89 GNUNET_RECLAIM_PresentationList *presentations,
90 const struct GNUNET_TIME_Relative *expiration_time,
91 const char *nonce,
92 const char *secret_key);
93
94/**
95 * Builds an OIDC authorization code including
96 * a reclaim ticket and nonce
97 *
98 * @param issuer the issuer of the ticket, used to sign the ticket and nonce
99 * @param ticket the ticket to include in the code
100 * @param attrs list of attributes to share
101 * @param presentations credential presentation list
102 * @param nonce the nonce to include in the code
103 * @param code_challenge PKCE code challenge
104 * @param opts verification options
105 * @return a new authorization code (caller must free)
106 */
107char*
108OIDC_build_authz_code (const struct GNUNET_CRYPTO_PrivateKey *issuer,
109 const struct GNUNET_RECLAIM_Ticket *ticket,
110 const struct GNUNET_RECLAIM_AttributeList *attrs,
111 const struct
112 GNUNET_RECLAIM_PresentationList *presentations,
113 const char *nonce,
114 const char *code_challenge);
115
116/**
117 * Parse reclaim ticket and nonce from
118 * authorization code.
119 * This also verifies the signature in the code.
120 *
121 * @param ecdsa_priv the audience of the ticket
122 * @param code the string representation of the code
123 * @param code_verfier PKCE code verifier
124 * @param ticket where to store the ticket
125 * @param attrs the attributes found in the code
126 * @param presentations credential presentation list
127 * @param nonce where to store the nonce
128 * @return GNUNET_OK if successful, else GNUNET_SYSERR
129 */
130int
131OIDC_parse_authz_code (const struct GNUNET_CRYPTO_PublicKey *ecdsa_pub,
132 const char *code,
133 const char *code_verifier,
134 struct GNUNET_RECLAIM_Ticket *ticket,
135 struct GNUNET_RECLAIM_AttributeList **attrs,
136 struct GNUNET_RECLAIM_PresentationList **presentations,
137 char **nonce,
138 enum OIDC_VerificationOptions opts);
139
140/**
141 * Build a token response for a token request
142 * TODO: Maybe we should add the scope here?
143 *
144 * @param access_token the access token to include
145 * @param id_token the id_token to include
146 * @param expiration_time the expiration time of the token(s)
147 * @param token_response where to store the response
148 */
149void
150OIDC_build_token_response (const char *access_token,
151 const char *id_token,
152 const struct GNUNET_TIME_Relative *expiration_time,
153 char **token_response);
154
155/**
156 * Generate a new access token
157 */
158char*
159OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket);
160
161/**
162 * Parse an access token
163 */
164int
165OIDC_access_token_parse (const char *token,
166 struct GNUNET_RECLAIM_Ticket **ticket);
167
168
169/**
170 * Checks if a claim is implicitly requested through standard
171 * scope(s)
172 *
173 * @param scopes the scopes which have been requested
174 * @param attr the attribute name to check
175 * @return GNUNET_YES if attribute is implcitly requested
176 */
177enum GNUNET_GenericReturnValue
178OIDC_check_scopes_for_claim_request (const char *scopes,
179 const char *attr);
180
181
182/**
183 * Generate userinfo JSON as string
184 *
185 * @param sub_key the subject (user)
186 * @param attrs user attribute list
187 * @param presentations credential presentation list
188 * @return Userinfo JSON
189 */
190char *
191OIDC_generate_userinfo (const struct GNUNET_CRYPTO_PublicKey *sub_key,
192 const struct GNUNET_RECLAIM_AttributeList *attrs,
193 const struct
194 GNUNET_RECLAIM_PresentationList *presentations);
195
196#endif
diff --git a/src/reclaim/pabc_helper.c b/src/reclaim/pabc_helper.c
deleted file mode 100644
index 65a633f7b..000000000
--- a/src/reclaim/pabc_helper.c
+++ /dev/null
@@ -1,366 +0,0 @@
1// maximilian.kaul@aisec.fraunhofer.de
2
3// WIP implementation of
4// https://github.com/ontio/ontology-crypto/wiki/Anonymous-Credential
5// using the relic library https://github.com/relic-toolkit/relic/
6
7#include "platform.h"
8#include "pabc_helper.h"
9#include <pwd.h>
10#include <stdlib.h>
11#include <unistd.h>
12
13static char pabc_dir[PATH_MAX + 1];
14
15static const char *
16get_homedir ()
17{
18 const char *homedir;
19 if ((homedir = getenv ("HOME")) == NULL)
20 {
21 homedir = getpwuid (getuid ())->pw_dir;
22 }
23 return homedir;
24}
25
26
27static enum GNUNET_GenericReturnValue
28write_file (char const *const filename, const char *buffer)
29{
30 struct GNUNET_DISK_FileHandle *fh;
31 fh = GNUNET_DISK_file_open (filename,
32 GNUNET_DISK_OPEN_WRITE
33 | GNUNET_DISK_OPEN_TRUNCATE
34 | GNUNET_DISK_OPEN_CREATE,
35 GNUNET_DISK_PERM_USER_WRITE
36 | GNUNET_DISK_PERM_USER_READ);
37 if (fh == NULL)
38 return GNUNET_SYSERR;
39 if (GNUNET_SYSERR == GNUNET_DISK_file_write (fh,
40 buffer, strlen (buffer) + 1))
41 goto fail;
42 GNUNET_DISK_file_close (fh);
43 return GNUNET_OK;
44
45fail:
46 GNUNET_DISK_file_close (fh);
47 return GNUNET_SYSERR;
48}
49
50
51static enum GNUNET_GenericReturnValue
52init_pabc_dir ()
53{
54 size_t filename_size = strlen (get_homedir ()) + 1 + strlen (".local") + 1
55 + strlen ("pabc-reclaim") + 1;
56 snprintf (pabc_dir, filename_size, "%s/%s/%s",
57 get_homedir (), ".local", "pabc-reclaim");
58 return GNUNET_DISK_directory_create (pabc_dir);
59}
60
61
62static const char *
63get_pabcdir ()
64{
65 init_pabc_dir ();
66 return pabc_dir;
67}
68
69
70enum GNUNET_GenericReturnValue
71read_file (char const *const filename, char **buffer)
72{
73 struct GNUNET_DISK_FileHandle *fh;
74 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
75 return GNUNET_SYSERR;
76
77 fh = GNUNET_DISK_file_open (filename,
78 GNUNET_DISK_OPEN_READ,
79 GNUNET_DISK_PERM_USER_READ);
80 if (fh == NULL)
81 return GNUNET_SYSERR;
82 long lSize = GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_END);
83 if (lSize < 0)
84 goto fail;
85 GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_SET);
86 *buffer = calloc ((size_t) lSize + 1, sizeof(char));
87 if (*buffer == NULL)
88 goto fail;
89
90 // copy the file into the buffer:
91 size_t r = GNUNET_DISK_file_read (fh, *buffer, (size_t) lSize);
92 if (r != (size_t) lSize)
93 goto fail;
94
95 GNUNET_DISK_file_close (fh);
96 return GNUNET_OK;
97
98fail:
99 GNUNET_DISK_file_close (fh);
100 GNUNET_free (*buffer);
101 return GNUNET_SYSERR;
102}
103
104
105struct pabc_public_parameters *
106PABC_read_issuer_ppfile (const char *f, struct pabc_context *const ctx)
107{
108 if (NULL == ctx)
109 {
110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No global context provided\n");
111 return NULL;
112 }
113 struct pabc_public_parameters *pp;
114 char *buffer;
115 int r;
116 r = read_file (f, &buffer);
117 if (GNUNET_OK != r)
118 {
119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading file\n");
120 return NULL;
121 }
122 if (PABC_OK != pabc_decode_and_new_public_parameters (ctx, &pp, buffer))
123 {
124 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
125 "Failed to decode public parameters\n");
126 PABC_FREE_NULL (buffer);
127 return NULL;
128 }
129 PABC_FREE_NULL (buffer);
130 return pp;
131}
132
133
134enum GNUNET_GenericReturnValue
135PABC_load_public_parameters (struct pabc_context *const ctx,
136 char const *const pp_name,
137 struct pabc_public_parameters **pp)
138{
139 char fname[PATH_MAX];
140 char *pp_filename;
141 const char *pdir = get_pabcdir ();
142
143 if (ctx == NULL)
144 return GNUNET_SYSERR;
145 if (pp_name == NULL)
146 return GNUNET_SYSERR;
147
148 GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
149 if (GNUNET_YES != GNUNET_DISK_directory_test (pdir, GNUNET_YES))
150 {
151 GNUNET_free (pp_filename);
152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading %s\n", pdir);
153 return GNUNET_SYSERR;
154 }
155 snprintf (fname, PATH_MAX, "%s/%s%s", pdir, pp_filename, PABC_PP_EXT);
156 if (GNUNET_YES != GNUNET_DISK_file_test (fname))
157 {
158 GNUNET_free (pp_filename);
159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error testing %s\n", fname);
160 return GNUNET_SYSERR;
161 }
162 *pp = PABC_read_issuer_ppfile (fname, ctx);
163 if (*pp)
164 return GNUNET_OK;
165 else
166 return GNUNET_SYSERR;
167}
168
169
170enum GNUNET_GenericReturnValue
171PABC_write_public_parameters (char const *const pp_name,
172 struct pabc_public_parameters *const pp)
173{
174 char *json;
175 char *filename;
176 char *pp_filename;
177 enum pabc_status status;
178 struct pabc_context *ctx = NULL;
179
180 GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
181 PABC_ASSERT (pabc_new_ctx (&ctx));
182 // store in json file
183 status = pabc_encode_public_parameters (ctx, pp, &json);
184 if (status != PABC_OK)
185 {
186 GNUNET_free (pp_filename);
187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
188 "Failed to encode public parameters.\n");
189 pabc_free_ctx (&ctx);
190 return GNUNET_SYSERR;
191 }
192
193 size_t filename_size =
194 strlen (get_pabcdir ()) + 1 + strlen (pp_filename) + strlen (PABC_PP_EXT)
195 + 1;
196 filename = GNUNET_malloc (filename_size);
197 if (! filename)
198 {
199 GNUNET_free (pp_filename);
200 PABC_FREE_NULL (json);
201 pabc_free_ctx (&ctx);
202 return GNUNET_SYSERR;
203 }
204 snprintf (filename, filename_size, "%s/%s%s", get_pabcdir (), pp_filename,
205 PABC_PP_EXT);
206
207 GNUNET_free (pp_filename);
208 if (GNUNET_OK != write_file (filename, json))
209 {
210 PABC_FREE_NULL (filename);
211 PABC_FREE_NULL (json);
212 pabc_free_ctx (&ctx);
213 return GNUNET_SYSERR;
214 }
215 PABC_FREE_NULL (filename);
216 PABC_FREE_NULL (json);
217 pabc_free_ctx (&ctx);
218 return GNUNET_OK;
219}
220
221
222enum GNUNET_GenericReturnValue
223PABC_write_usr_ctx (char const *const usr_name,
224 char const *const pp_name,
225 struct pabc_context const *const ctx,
226 struct pabc_public_parameters const *const pp,
227 struct pabc_user_context *const usr_ctx)
228{
229
230 char *pp_filename;
231 char *json = NULL;
232 enum pabc_status status;
233 char *fname = NULL;
234
235 if (NULL == usr_name)
236 {
237 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n");
238 return GNUNET_SYSERR;
239 }
240 if (NULL == pp_name)
241 {
242 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n");
243 return GNUNET_SYSERR;
244 }
245 if (NULL == ctx)
246 {
247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n");
248 return GNUNET_SYSERR;
249 }
250 if (NULL == pp)
251 {
252 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n");
253 return GNUNET_SYSERR;
254 }
255 if (NULL == usr_ctx)
256 {
257 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n");
258 return GNUNET_SYSERR;
259 }
260
261 GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
262 status = pabc_encode_user_ctx (ctx, pp, usr_ctx, &json);
263 if (PABC_OK != status)
264 {
265 GNUNET_free (pp_filename);
266 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n");
267 return status;
268 }
269
270 size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1
271 + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1;
272 fname = GNUNET_malloc (fname_size);
273
274 snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name,
275 pp_filename,
276 PABC_USR_EXT);
277
278 GNUNET_free (pp_filename);
279 if (GNUNET_OK == write_file (fname, json))
280 {
281 GNUNET_free (fname);
282 GNUNET_free (json);
283 return GNUNET_OK;
284 }
285 else
286 {
287 GNUNET_free (fname);
288 GNUNET_free (json);
289 return GNUNET_SYSERR;
290 }
291}
292
293
294enum GNUNET_GenericReturnValue
295PABC_read_usr_ctx (char const *const usr_name,
296 char const *const pp_name,
297 struct pabc_context const *const ctx,
298 struct pabc_public_parameters const *const pp,
299 struct pabc_user_context **usr_ctx)
300{
301 char *json = NULL;
302 char *pp_filename;
303 enum pabc_status status;
304
305 char *fname = NULL;
306
307 if (NULL == usr_name)
308 {
309 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n");
310 return GNUNET_SYSERR;
311 }
312 if (NULL == pp_name)
313 {
314 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n");
315 return GNUNET_SYSERR;
316 }
317 if (NULL == ctx)
318 {
319 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n");
320 return GNUNET_SYSERR;
321 }
322 if (NULL == pp)
323 {
324 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n");
325 return GNUNET_SYSERR;
326 }
327 if (NULL == usr_ctx)
328 {
329 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n");
330 return GNUNET_SYSERR;
331 }
332 GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
333
334 size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1
335 + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1;
336 fname = GNUNET_malloc (fname_size);
337 snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name,
338 pp_filename,
339 PABC_USR_EXT);
340 GNUNET_free (pp_filename);
341 if (GNUNET_OK != read_file (fname, &json))
342 {
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344 "Failed to read `%s'\n", fname);
345 PABC_FREE_NULL (fname);
346 return GNUNET_SYSERR;
347 }
348 GNUNET_free (fname);
349
350 status = pabc_new_user_context (ctx, pp, usr_ctx);
351 if (PABC_OK != status)
352 {
353 GNUNET_free (json);
354 return GNUNET_SYSERR;
355 }
356 status = pabc_decode_user_ctx (ctx, pp, *usr_ctx, json);
357 GNUNET_free (json);
358 if (PABC_OK != status)
359 {
360 pabc_free_user_context (ctx, pp, usr_ctx);
361 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n");
362 return GNUNET_SYSERR;
363 }
364
365 return GNUNET_OK;
366}
diff --git a/src/reclaim/pabc_helper.h b/src/reclaim/pabc_helper.h
deleted file mode 100644
index 045ad5dda..000000000
--- a/src/reclaim/pabc_helper.h
+++ /dev/null
@@ -1,41 +0,0 @@
1#include "platform.h"
2#include "gnunet_util_lib.h"
3#include <pabc/pabc.h>
4
5#ifndef PATH_MAX
6#define PATH_MAX 4096
7#endif
8
9#define PABC_ISK_EXT ".isk"
10
11#define PABC_PP_EXT ".pp"
12
13#define PABC_USR_EXT ".usr"
14
15#define PABC_ATTR_DELIM "="
16
17enum GNUNET_GenericReturnValue
18PABC_write_public_parameters (char const *const pp_name,
19 struct pabc_public_parameters *const pp);
20
21
22enum GNUNET_GenericReturnValue
23PABC_load_public_parameters (struct pabc_context *const ctx,
24 char const *const pp_name,
25 struct pabc_public_parameters **pp);
26
27enum GNUNET_GenericReturnValue
28PABC_write_usr_ctx (char const *const user_name,
29 char const *const pp_name,
30 struct pabc_context const *const ctx,
31 struct pabc_public_parameters const *const
32 pp,
33 struct pabc_user_context *const usr_ctx);
34
35enum GNUNET_GenericReturnValue
36PABC_read_usr_ctx (char const *const user_name,
37 char const *const pp_name,
38 struct pabc_context const *const ctx,
39 struct pabc_public_parameters const *const
40 pp,
41 struct pabc_user_context **usr_ctx);
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c
deleted file mode 100644
index ce6fe483d..000000000
--- a/src/reclaim/plugin_gnsrecord_reclaim.c
+++ /dev/null
@@ -1,195 +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_CREDENTIAL:
54 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
55 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
56
57 default:
58 return NULL;
59 }
60}
61
62
63/**
64 * Convert human-readable version of a 'value' of a record to the binary
65 * representation.
66 *
67 * @param cls closure, unused
68 * @param type type of the record
69 * @param s human-readable string
70 * @param data set to value in binary encoding (will be allocated)
71 * @param data_size set to number of bytes in @a data
72 * @return #GNUNET_OK on success
73 */
74static int
75string_to_value (void *cls, uint32_t type, const char *s, void **data,
76 size_t *data_size)
77{
78 if (NULL == s)
79 return GNUNET_SYSERR;
80 switch (type)
81 {
82 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT:
83 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT:
84 *data = GNUNET_strdup (s);
85 *data_size = strlen (s);
86 return GNUNET_OK;
87 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
88 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
89 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
90 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
91 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
92 return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
93
94 default:
95 return GNUNET_SYSERR;
96 }
97}
98
99
100/**
101 * Mapping of record type numbers to human-readable
102 * record type names.
103 */
104static struct
105{
106 const char *name;
107 uint32_t number;
108} name_map[] = {
109 { "RECLAIM_ATTRIBUTE", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE },
110 { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF },
111 { "RECLAIM_CREDENTIAL", GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL },
112 { "RECLAIM_PRESENTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION },
113 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
114 { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT },
115 { "RECLAIM_TICKET", GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET },
116 { NULL, UINT32_MAX }
117};
118
119
120/**
121 * Convert a type name (e.g. "AAAA") to the corresponding number.
122 *
123 * @param cls closure, unused
124 * @param dns_typename name to convert
125 * @return corresponding number, UINT32_MAX on error
126 */
127static uint32_t
128typename_to_number (void *cls, const char *dns_typename)
129{
130 unsigned int i;
131
132 i = 0;
133 while ((NULL != name_map[i].name) &&
134 (0 != strcasecmp (dns_typename, name_map[i].name)))
135 i++;
136 return name_map[i].number;
137}
138
139
140/**
141 * Convert a type number to the corresponding type string (e.g. 1 to "A")
142 *
143 * @param cls closure, unused
144 * @param type number of a type to convert
145 * @return corresponding typestring, NULL on error
146 */
147static const char *
148number_to_typename (void *cls, uint32_t type)
149{
150 unsigned int i;
151
152 i = 0;
153 while ((NULL != name_map[i].name) && (type != name_map[i].number))
154 i++;
155 return name_map[i].name;
156}
157
158
159/**
160 * Entry point for the plugin.
161 *
162 * @param cls NULL
163 * @return the exported block API
164 */
165void *
166libgnunet_plugin_gnsrecord_reclaim_init (void *cls)
167{
168 struct GNUNET_GNSRECORD_PluginFunctions *api;
169
170 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
171 api->value_to_string = &value_to_string;
172 api->string_to_value = &string_to_value;
173 api->typename_to_number = &typename_to_number;
174 api->number_to_typename = &number_to_typename;
175 return api;
176}
177
178
179/**
180 * Exit point from the plugin.
181 *
182 * @param cls the return value from #libgnunet_plugin_block_test_init
183 * @return NULL
184 */
185void *
186libgnunet_plugin_gnsrecord_reclaim_done (void *cls)
187{
188 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
189
190 GNUNET_free (api);
191 return NULL;
192}
193
194
195/* 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 66f59998a..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) + 1;
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 to the corresponding type string (e.g. 1 to "A")
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 3eb4bfebf..000000000
--- a/src/reclaim/plugin_reclaim_credential_jwt.c
+++ /dev/null
@@ -1,512 +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) + 1;
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 to the corresponding type string (e.g. 1 to "A")
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 size_t data_size)
156{
157 char *jwt_string;
158 struct GNUNET_RECLAIM_AttributeList *attrs;
159 char delim[] = ".";
160 char *val_str = NULL;
161 char *decoded_jwt;
162 char *tmp;
163 json_t *json_val;
164 json_error_t json_err;
165
166 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
167
168 jwt_string = GNUNET_strndup (data, data_size);
169 const char *jwt_body = strtok (jwt_string, delim);
170 if (NULL == jwt_body)
171 {
172 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
173 "Failed to parse JSON %s\n", jwt_string);
174 return attrs;
175 }
176 jwt_body = strtok (NULL, delim);
177 if (NULL == jwt_body)
178 {
179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
180 "Failed to parse JSON %s\n", jwt_string);
181 GNUNET_free (jwt_string);
182 return attrs;
183 }
184 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
185 (void **) &decoded_jwt);
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded JWT: %s\n", decoded_jwt);
187 GNUNET_assert (NULL != decoded_jwt);
188 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err);
189 GNUNET_free (decoded_jwt);
190 const char *key;
191 const char *addr_key;
192 json_t *value;
193 json_t *addr_value;
194
195 json_object_foreach (json_val, key, value) {
196 if (0 == strcmp ("iss", key))
197 continue;
198 if (0 == strcmp ("jti", key))
199 continue;
200 if (0 == strcmp ("exp", key))
201 continue;
202 if (0 == strcmp ("iat", key))
203 continue;
204 if (0 == strcmp ("nbf", key))
205 continue;
206 if (0 == strcmp ("aud", key))
207 continue;
208 if (0 == strcmp ("address", key))
209 {
210 if (! json_is_object (value))
211 {
212 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
213 "address claim in wrong format!");
214 continue;
215 }
216 json_object_foreach (value, addr_key, addr_value) {
217 val_str = json_dumps (addr_value, JSON_ENCODE_ANY);
218 tmp = val_str;
219 // Remove leading " from jasson conversion
220 if (tmp[0] == '"')
221 tmp++;
222 // Remove trailing " from jansson conversion
223 if (tmp[strlen (tmp) - 1] == '"')
224 tmp[strlen (tmp) - 1] = '\0';
225 GNUNET_RECLAIM_attribute_list_add (attrs,
226 addr_key,
227 NULL,
228 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
229 tmp,
230 strlen (val_str));
231 GNUNET_free (val_str);
232 }
233 continue;
234 }
235 val_str = json_dumps (value, JSON_ENCODE_ANY);
236 tmp = val_str;
237 // Remove leading " from jasson conversion
238 if (tmp[0] == '"')
239 tmp++;
240 // Remove trailing " from jansson conversion
241 if (tmp[strlen (tmp) - 1] == '"')
242 tmp[strlen (tmp) - 1] = '\0';
243 GNUNET_RECLAIM_attribute_list_add (attrs,
244 key,
245 NULL,
246 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,// FIXME
247 tmp,
248 strlen (val_str));
249 GNUNET_free (val_str);
250 }
251 json_decref (json_val);
252 GNUNET_free (jwt_string);
253 return attrs;
254}
255
256
257/**
258 * Parse a JWT and return the respective claim value as Attribute
259 *
260 * @param cls the plugin
261 * @param cred the jwt credential
262 * @return a GNUNET_RECLAIM_Attribute, containing the new value
263 */
264struct GNUNET_RECLAIM_AttributeList *
265jwt_parse_attributes_c (void *cls,
266 const struct GNUNET_RECLAIM_Credential *cred)
267{
268 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT)
269 return NULL;
270 return jwt_parse_attributes (cls, cred->data, cred->data_size);
271}
272
273
274/**
275 * Parse a JWT and return the respective claim value as Attribute
276 *
277 * @param cls the plugin
278 * @param cred the jwt credential
279 * @return a GNUNET_RECLAIM_Attribute, containing the new value
280 */
281struct GNUNET_RECLAIM_AttributeList *
282jwt_parse_attributes_p (void *cls,
283 const struct GNUNET_RECLAIM_Presentation *cred)
284{
285 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT)
286 return NULL;
287 return jwt_parse_attributes (cls, cred->data, cred->data_size);
288}
289
290
291/**
292 * Parse a JWT and return the issuer
293 *
294 * @param cls the plugin
295 * @param cred the jwt credential
296 * @return a string, containing the isser
297 */
298char *
299jwt_get_issuer (void *cls,
300 const char *data,
301 size_t data_size)
302{
303 const char *jwt_body;
304 char *jwt_string;
305 char delim[] = ".";
306 char *issuer = NULL;
307 char *decoded_jwt;
308 json_t *issuer_json;
309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
310 json_t *json_val;
311 json_error_t json_err;
312
313 jwt_string = GNUNET_strndup (data, data_size);
314 jwt_body = strtok (jwt_string, delim);
315 jwt_body = strtok (NULL, delim);
316 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
317 (void **) &decoded_jwt);
318 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err);
319 GNUNET_free (decoded_jwt);
320 GNUNET_free (jwt_string);
321 if (NULL == json_val)
322 return NULL;
323 issuer_json = json_object_get (json_val, "iss");
324 if ((NULL == issuer_json) || (! json_is_string (issuer_json)))
325 {
326 json_decref (json_val);
327 return NULL;
328 }
329 issuer = GNUNET_strdup (json_string_value (issuer_json));
330 json_decref (json_val);
331 return issuer;
332}
333
334
335/**
336 * Parse a JWT and return the issuer
337 *
338 * @param cls the plugin
339 * @param cred the jwt credential
340 * @return a string, containing the isser
341 */
342char *
343jwt_get_issuer_c (void *cls,
344 const struct GNUNET_RECLAIM_Credential *cred)
345{
346 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
347 return NULL;
348 return jwt_get_issuer (cls, cred->data, cred->data_size);
349}
350
351
352/**
353 * Parse a JWT and return the issuer
354 *
355 * @param cls the plugin
356 * @param cred the jwt credential
357 * @return a string, containing the isser
358 */
359char *
360jwt_get_issuer_p (void *cls,
361 const struct GNUNET_RECLAIM_Presentation *cred)
362{
363 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
364 return NULL;
365 return jwt_get_issuer (cls, cred->data, cred->data_size);
366}
367
368
369/**
370 * Parse a JWT and return the expiration
371 *
372 * @param cls the plugin
373 * @param cred the jwt credential
374 * @return a string, containing the isser
375 */
376enum GNUNET_GenericReturnValue
377jwt_get_expiration (void *cls,
378 const char *data,
379 size_t data_size,
380 struct GNUNET_TIME_Absolute *exp)
381{
382 const char *jwt_body;
383 char *jwt_string;
384 char delim[] = ".";
385 char *decoded_jwt;
386 json_t *exp_json;
387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
388 json_t *json_val;
389 json_error_t json_err;
390
391 jwt_string = GNUNET_strndup (data, data_size);
392 jwt_body = strtok (jwt_string, delim);
393 jwt_body = strtok (NULL, delim);
394 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
395 (void **) &decoded_jwt);
396 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err);
397 GNUNET_free (decoded_jwt);
398 GNUNET_free (jwt_string);
399 if (NULL == json_val)
400 return GNUNET_SYSERR;
401 exp_json = json_object_get (json_val, "exp");
402 if ((NULL == exp_json) || (! json_is_integer (exp_json)))
403 {
404 json_decref (json_val);
405 return GNUNET_SYSERR;
406 }
407 exp->abs_value_us = json_integer_value (exp_json) * 1000 * 1000;
408 json_decref (json_val);
409 return GNUNET_OK;
410}
411
412
413/**
414 * Parse a JWT and return the expiration
415 *
416 * @param cls the plugin
417 * @param cred the jwt credential
418 * @return the expirati
419 */
420enum GNUNET_GenericReturnValue
421jwt_get_expiration_c (void *cls,
422 const struct GNUNET_RECLAIM_Credential *cred,
423 struct GNUNET_TIME_Absolute *exp)
424{
425 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
426 return GNUNET_NO;
427 return jwt_get_expiration (cls, cred->data, cred->data_size, exp);
428}
429
430
431/**
432 * Parse a JWT and return the expiration
433 *
434 * @param cls the plugin
435 * @param cred the jwt credential
436 * @return a string, containing the isser
437 */
438enum GNUNET_GenericReturnValue
439jwt_get_expiration_p (void *cls,
440 const struct GNUNET_RECLAIM_Presentation *cred,
441 struct GNUNET_TIME_Absolute *exp)
442{
443 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
444 return GNUNET_NO;
445 return jwt_get_expiration (cls, cred->data, cred->data_size, exp);
446}
447
448
449enum GNUNET_GenericReturnValue
450jwt_create_presentation (void *cls,
451 const struct GNUNET_RECLAIM_Credential *cred,
452 const struct GNUNET_RECLAIM_AttributeList *attrs,
453 struct GNUNET_RECLAIM_Presentation **presentation)
454{
455 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
456 return GNUNET_NO;
457 *presentation = GNUNET_RECLAIM_presentation_new (
458 GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT,
459 cred->data,
460 cred->data_size);
461 return GNUNET_OK;
462}
463
464
465/**
466 * Entry point for the plugin.
467 *
468 * @param cls NULL
469 * @return the exported block API
470 */
471void *
472libgnunet_plugin_reclaim_credential_jwt_init (void *cls)
473{
474 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
475
476 api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions);
477 api->value_to_string = &jwt_value_to_string;
478 api->string_to_value = &jwt_string_to_value;
479 api->typename_to_number = &jwt_typename_to_number;
480 api->number_to_typename = &jwt_number_to_typename;
481 api->get_attributes = &jwt_parse_attributes_c;
482 api->get_issuer = &jwt_get_issuer_c;
483 api->get_expiration = &jwt_get_expiration_c;
484 api->value_to_string_p = &jwt_value_to_string;
485 api->string_to_value_p = &jwt_string_to_value;
486 api->typename_to_number_p = &jwt_typename_to_number;
487 api->number_to_typename_p = &jwt_number_to_typename;
488 api->get_attributes_p = &jwt_parse_attributes_p;
489 api->get_issuer_p = &jwt_get_issuer_p;
490 api->get_expiration_p = &jwt_get_expiration_p;
491 api->create_presentation = &jwt_create_presentation;
492 return api;
493}
494
495
496/**
497 * Exit point from the plugin.
498 *
499 * @param cls the return value from #libgnunet_plugin_block_test_init()
500 * @return NULL
501 */
502void *
503libgnunet_plugin_reclaim_credential_jwt_done (void *cls)
504{
505 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
506
507 GNUNET_free (api);
508 return NULL;
509}
510
511
512/* end of plugin_reclaim_credential_type_jwt.c */
diff --git a/src/reclaim/plugin_reclaim_credential_pabc.c b/src/reclaim/plugin_reclaim_credential_pabc.c
deleted file mode 100644
index a906805fb..000000000
--- a/src/reclaim/plugin_reclaim_credential_pabc.c
+++ /dev/null
@@ -1,572 +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_pabc.c
23 * @brief reclaim-credential-plugin-pabc attribute plugin to provide the API for
24 * pabc 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#include <pabc/pabc.h>
34#include "pabc_helper.h"
35
36/**
37 * Convert the 'value' of an credential to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the credential
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46pabc_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51 switch (type)
52 {
53 case GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC:
54 return GNUNET_strndup (data, data_size);
55
56 default:
57 return NULL;
58 }
59}
60
61
62/**
63 * Convert human-readable version of a 'value' of an credential to the binary
64 * representation.
65 *
66 * @param cls closure, unused
67 * @param type type of the credential
68 * @param s human-readable string
69 * @param data set to value in binary encoding (will be allocated)
70 * @param data_size set to number of bytes in @a data
71 * @return #GNUNET_OK on success
72 */
73static int
74pabc_string_to_value (void *cls,
75 uint32_t type,
76 const char *s,
77 void **data,
78 size_t *data_size)
79{
80 if (NULL == s)
81 return GNUNET_SYSERR;
82 switch (type)
83 {
84 case GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC:
85 *data = GNUNET_strdup (s);
86 *data_size = strlen (s) + 1;
87 return GNUNET_OK;
88
89 default:
90 return GNUNET_SYSERR;
91 }
92}
93
94
95/**
96 * Mapping of credential type numbers to human-readable
97 * credential type names.
98 */
99static struct
100{
101 const char *name;
102 uint32_t number;
103} pabc_cred_name_map[] = { { "PABC", GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC },
104 { NULL, UINT32_MAX } };
105
106/**
107 * Convert a type name to the corresponding number.
108 *
109 * @param cls closure, unused
110 * @param pabc_typename name to convert
111 * @return corresponding number, UINT32_MAX on error
112 */
113static uint32_t
114pabc_typename_to_number (void *cls, const char *pabc_typename)
115{
116 unsigned int i;
117
118 i = 0;
119 while ((NULL != pabc_cred_name_map[i].name) &&
120 (0 != strcasecmp (pabc_typename, pabc_cred_name_map[i].name)))
121 i++;
122 return pabc_cred_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 *
134pabc_number_to_typename (void *cls, uint32_t type)
135{
136 unsigned int i;
137
138 i = 0;
139 while ((NULL != pabc_cred_name_map[i].name) && (type !=
140 pabc_cred_name_map[i].
141 number))
142 i++;
143 return pabc_cred_name_map[i].name;
144}
145
146
147static void
148inspect_attrs (char const *const key,
149 char const *const value,
150 void *ctx)
151{
152 struct GNUNET_RECLAIM_AttributeList *attrs = ctx;
153
154 if (NULL == value)
155 return;
156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
157 "Found attribute in PABC credential: `%s': `%s'\n",
158 key, value);
159 if (0 == strcmp (key, "expiration"))
160 return;
161 if (0 == strcmp (key, "issuer"))
162 return;
163 if (0 == strcmp (key, "subject"))
164 return;
165 GNUNET_RECLAIM_attribute_list_add (attrs,
166 key,
167 NULL,
168 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
169 value,
170 strlen (value));
171}
172
173
174/**
175 * Parse a pabc and return the respective claim value as Attribute
176 *
177 * @param cls the plugin
178 * @param cred the pabc credential
179 * @return a GNUNET_RECLAIM_Attribute, containing the new value
180 */
181struct GNUNET_RECLAIM_AttributeList *
182pabc_parse_attributes (void *cls,
183 const char *data,
184 size_t data_size)
185{
186 struct GNUNET_RECLAIM_AttributeList *attrs;
187
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189 "Collecting PABC attributes...\n");
190 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
191 GNUNET_assert (PABC_OK ==
192 pabc_cred_inspect_credential (data,
193 &inspect_attrs, attrs));
194 return attrs;
195}
196
197
198/**
199 * Parse a pabc and return the respective claim value as Attribute
200 *
201 * @param cls the plugin
202 * @param cred the pabc credential
203 * @return a GNUNET_RECLAIM_Attribute, containing the new value
204 */
205struct GNUNET_RECLAIM_AttributeList *
206pabc_parse_attributes_c (void *cls,
207 const struct GNUNET_RECLAIM_Credential *cred)
208{
209 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
210 return NULL;
211 return pabc_parse_attributes (cls, cred->data, cred->data_size);
212}
213
214
215/**
216 * Parse a pabc and return the respective claim value as Attribute
217 *
218 * @param cls the plugin
219 * @param cred the pabc credential
220 * @return a GNUNET_RECLAIM_Attribute, containing the new value
221 */
222struct GNUNET_RECLAIM_AttributeList *
223pabc_parse_attributes_p (void *cls,
224 const struct GNUNET_RECLAIM_Presentation *cred)
225{
226 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
227 return NULL;
228 return pabc_parse_attributes (cls, cred->data, cred->data_size);
229}
230
231
232/**
233 * Parse a pabc and return the issuer
234 *
235 * @param cls the plugin
236 * @param cred the pabc credential
237 * @return a string, containing the isser
238 */
239char*
240pabc_get_issuer (void *cls,
241 const char *data,
242 size_t data_size)
243{
244 char *res;
245 if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (data,
246 "issuer",
247 &res))
248 return NULL;
249 return res;
250}
251
252
253/**
254 * Parse a pabc and return the issuer
255 *
256 * @param cls the plugin
257 * @param cred the pabc credential
258 * @return a string, containing the isser
259 */
260char *
261pabc_get_issuer_c (void *cls,
262 const struct GNUNET_RECLAIM_Credential *cred)
263{
264 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type)
265 return NULL;
266 return pabc_get_issuer (cls, cred->data, cred->data_size);
267}
268
269
270/**
271 * Parse a pabc and return the issuer
272 *
273 * @param cls the plugin
274 * @param cred the pabc credential
275 * @return a string, containing the isser
276 */
277char *
278pabc_get_issuer_p (void *cls,
279 const struct GNUNET_RECLAIM_Presentation *cred)
280{
281 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type)
282 return NULL;
283 return pabc_get_issuer (cls, cred->data, cred->data_size);
284}
285
286
287/**
288 * Parse a pabc and return the expiration
289 *
290 * @param cls the plugin
291 * @param cred the pabc credential
292 * @return a string, containing the isser
293 */
294enum GNUNET_GenericReturnValue
295pabc_get_expiration (void *cls,
296 const char *data,
297 size_t data_size,
298 struct GNUNET_TIME_Absolute *exp)
299{
300 char *exp_str;
301 uint64_t exp_i;
302
303 if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (data,
304 "expiration",
305 &exp_str))
306 return GNUNET_SYSERR;
307
308 if (1 != sscanf (exp_str, "%llu", &exp_i))
309 {
310 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
311 "Invalid expiration `%s'\n", exp_str);
312 GNUNET_free (exp_str);
313 return GNUNET_SYSERR;
314 }
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 "Converted expiration string `%s' to %llu",
317 exp_str, exp_i);
318
319 GNUNET_free (exp_str);
320 exp->abs_value_us = exp_i * 1000 * 1000;
321 return GNUNET_OK;
322}
323
324
325/**
326 * Parse a pabc and return the expiration
327 *
328 * @param cls the plugin
329 * @param cred the pabc credential
330 * @return a string, containing the isser
331 */
332enum GNUNET_GenericReturnValue
333pabc_get_expiration_c (void *cls,
334 const struct GNUNET_RECLAIM_Credential *cred,
335 struct GNUNET_TIME_Absolute *exp)
336{
337 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
338 return GNUNET_NO;
339 return pabc_get_expiration (cls, cred->data, cred->data_size, exp);
340}
341
342
343/**
344 * Parse a pabc and return the expiration
345 *
346 * @param cls the plugin
347 * @param cred the pabc credential
348 * @return a string, containing the isser
349 */
350enum GNUNET_GenericReturnValue
351pabc_get_expiration_p (void *cls,
352 const struct GNUNET_RECLAIM_Presentation *cred,
353 struct GNUNET_TIME_Absolute *exp)
354{
355 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
356 return GNUNET_NO;
357 return pabc_get_expiration (cls, cred->data, cred->data_size, exp);
358}
359
360
361int
362pabc_create_presentation (void *cls,
363 const struct GNUNET_RECLAIM_Credential *credential,
364 const struct GNUNET_RECLAIM_AttributeList *attrs,
365 struct GNUNET_RECLAIM_Presentation **presentation)
366{
367 struct pabc_context *ctx = NULL;
368 struct pabc_user_context *usr_ctx = NULL;
369 struct pabc_public_parameters *pp = NULL;
370 struct pabc_credential *cred = NULL;
371 struct pabc_blinded_proof *proof = NULL;
372 struct GNUNET_RECLAIM_AttributeListEntry *ale;
373 char *issuer;
374 char *subject;
375 enum pabc_status status;
376
377 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != credential->type)
378 return GNUNET_NO;
379
380
381 PABC_ASSERT (pabc_new_ctx (&ctx));
382 issuer = pabc_get_issuer_c (cls, credential);
383 if (NULL == issuer)
384 {
385 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
386 "No issuer found in credential\n");
387 pabc_free_ctx (&ctx);
388 return GNUNET_SYSERR;
389 }
390 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
391 "Got issuer for credential: %s\n", issuer);
392 status = PABC_load_public_parameters (ctx, issuer, &pp);
393 if (status != PABC_OK)
394 {
395 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
396 "Failed to read public parameters.\n");
397 pabc_free_ctx (&ctx);
398 GNUNET_free (issuer);
399 return GNUNET_SYSERR;
400 }
401 if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (credential->data,
402 "subject",
403 &subject))
404 {
405 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
406 "Failed to get subject.\n");
407 pabc_free_ctx (&ctx);
408 GNUNET_free (issuer);
409 return GNUNET_SYSERR;
410 }
411 status = PABC_read_usr_ctx (subject, issuer, ctx, pp, &usr_ctx);
412 GNUNET_free (issuer);
413 GNUNET_free (subject);
414 if (PABC_OK != status)
415 {
416 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
417 "Failed to read user context.\n");
418 pabc_free_public_parameters (ctx, &pp);
419 return GNUNET_SYSERR;
420 }
421
422 status = pabc_new_credential (ctx, pp, &cred);
423 if (status != PABC_OK)
424 {
425 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
426 "Failed to allocate credential.\n");
427 pabc_free_user_context (ctx, pp, &usr_ctx);
428 pabc_free_public_parameters (ctx, &pp);
429 return GNUNET_SYSERR;
430 }
431
432 status = pabc_decode_credential (ctx, pp, cred, credential->data);
433 if (status != PABC_OK)
434 {
435 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
436 "Failed to decode credential.\n");
437 pabc_free_credential (ctx, pp, &cred);
438 pabc_free_user_context (ctx, pp, &usr_ctx);
439 pabc_free_public_parameters (ctx, &pp);
440 return GNUNET_SYSERR;
441 }
442
443 status = pabc_new_proof (ctx, pp, &proof);
444 if (status != PABC_OK)
445 {
446 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
447 "Failed to allocate proof.\n");
448 pabc_free_credential (ctx, pp, &cred);
449 pabc_free_user_context (ctx, pp, &usr_ctx);
450 pabc_free_public_parameters (ctx, &pp);
451 return GNUNET_SYSERR;
452 }
453
454 // now we can parse the attributes to disclose and configure the proof
455 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
456 {
457 status = pabc_set_disclosure_by_attribute_name (ctx, pp, proof,
458 ale->attribute->name,
459 PABC_DISCLOSED, cred);
460 if (status != PABC_OK)
461 {
462 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
463 "Failed to configure proof.\n");
464 pabc_free_credential (ctx, pp, &cred);
465 pabc_free_user_context (ctx, pp, &usr_ctx);
466 pabc_free_public_parameters (ctx, &pp);
467 return GNUNET_SYSERR;
468 }
469 }
470
471 // and finally -> sign the proof
472 status = pabc_gen_proof (ctx, usr_ctx, pp, proof, cred);
473 if (status != PABC_OK)
474 {
475 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
476 "Failed to sign proof.\n");
477 pabc_free_proof (ctx, pp, &proof);
478 pabc_free_credential (ctx, pp, &cred);
479 pabc_free_user_context (ctx, pp, &usr_ctx);
480 pabc_free_public_parameters (ctx, &pp);
481 return GNUNET_SYSERR;
482 }
483 // print the result
484 char *json = NULL;
485 char *ppid = NULL;
486 char *userid = NULL;
487 GNUNET_assert (PABC_OK == pabc_cred_get_userid_from_cred (credential->data,
488 &userid));
489 GNUNET_assert (PABC_OK == pabc_cred_get_ppid_from_cred (credential->data,
490 &ppid));
491 pabc_cred_encode_proof (ctx, pp, proof, userid, ppid, &json);
492 GNUNET_free (ppid);
493 GNUNET_free (userid);
494 if (PABC_OK != status)
495 {
496 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
497 "Failed to serialize proof.\n");
498 pabc_free_proof (ctx, pp, &proof);
499 pabc_free_credential (ctx, pp, &cred);
500 pabc_free_user_context (ctx, pp, &usr_ctx);
501 pabc_free_public_parameters (ctx, &pp);
502 return GNUNET_SYSERR;
503 }
504 char *json_enc;
505 GNUNET_STRINGS_base64_encode (json,
506 strlen (json) + 1,
507 &json_enc);
508 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
509 "Presentation: %s\n", json_enc);
510 // clean up
511 *presentation = GNUNET_RECLAIM_presentation_new (
512 GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC,
513 json_enc,
514 strlen (json_enc) + 1);
515 GNUNET_free (json_enc);
516 PABC_FREE_NULL (json);
517 pabc_free_proof (ctx, pp, &proof);
518 pabc_free_credential (ctx, pp, &cred);
519 pabc_free_user_context (ctx, pp, &usr_ctx);
520 pabc_free_public_parameters (ctx, &pp);
521 return GNUNET_OK;
522}
523
524
525/**
526 * Entry point for the plugin.
527 *
528 * @param cls NULL
529 * @return the exported block API
530 */
531void *
532libgnunet_plugin_reclaim_credential_pabc_init (void *cls)
533{
534 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
535
536 api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions);
537 api->value_to_string = &pabc_value_to_string;
538 api->string_to_value = &pabc_string_to_value;
539 api->typename_to_number = &pabc_typename_to_number;
540 api->number_to_typename = &pabc_number_to_typename;
541 api->get_attributes = &pabc_parse_attributes_c;
542 api->get_issuer = &pabc_get_issuer_c;
543 api->get_expiration = &pabc_get_expiration_c;
544 api->value_to_string_p = &pabc_value_to_string;
545 api->string_to_value_p = &pabc_string_to_value;
546 api->typename_to_number_p = &pabc_typename_to_number;
547 api->number_to_typename_p = &pabc_number_to_typename;
548 api->get_attributes_p = &pabc_parse_attributes_p;
549 api->get_issuer_p = &pabc_get_issuer_p;
550 api->get_expiration_p = &pabc_get_expiration_p;
551 api->create_presentation = &pabc_create_presentation;
552 return api;
553}
554
555
556/**
557 * Exit point from the plugin.
558 *
559 * @param cls the return value from #libgnunet_plugin_block_test_init()
560 * @return NULL
561 */
562void *
563libgnunet_plugin_reclaim_credential_pabc_done (void *cls)
564{
565 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
566
567 GNUNET_free (api);
568 return NULL;
569}
570
571
572/* end of plugin_reclaim_credential_type_pabc.c */
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
deleted file mode 100644
index d0aee043e..000000000
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ /dev/null
@@ -1,3162 +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 * @author Tristan Schwieren
24 * @file identity/plugin_rest_openid_connect.c
25 * @brief GNUnet Namestore REST plugin
26 *
27 */
28#include "platform.h"
29#include <inttypes.h>
30#include <jansson.h>
31#include <jose/jose.h>
32
33#include "gnunet_util_lib.h"
34#include "gnunet_gns_service.h"
35#include "gnunet_gnsrecord_lib.h"
36#include "gnunet_identity_service.h"
37#include "gnunet_namestore_service.h"
38#include "gnunet_reclaim_lib.h"
39#include "gnunet_reclaim_service.h"
40#include "gnunet_rest_lib.h"
41#include "gnunet_rest_plugin.h"
42#include "gnunet_signatures.h"
43#include "microhttpd.h"
44#include "oidc_helper.h"
45
46/**
47 * REST root namespace
48 */
49#define GNUNET_REST_API_NS_OIDC "/openid"
50
51/**
52 * OIDC config
53 */
54#define GNUNET_REST_API_NS_OIDC_CONFIG "/.well-known/openid-configuration"
55
56/**
57 * Authorize endpoint
58 */
59#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
60
61/**
62 * Token endpoint
63 */
64#define GNUNET_REST_API_NS_TOKEN "/openid/token"
65
66/**
67 * JSON Web Keys endpoint
68 */
69#define GNUNET_REST_API_JWKS "/jwks.json"
70
71/**
72 * UserInfo endpoint
73 */
74#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
75
76/**
77 * Login namespace
78 */
79#define GNUNET_REST_API_NS_LOGIN "/openid/login"
80
81/**
82 * State while collecting all egos
83 */
84#define ID_REST_STATE_INIT 0
85
86/**
87 * Done collecting egos
88 */
89#define ID_REST_STATE_POST_INIT 1
90
91/**
92 * OIDC grant_type key
93 */
94#define OIDC_GRANT_TYPE_KEY "grant_type"
95
96/**
97 * OIDC grant_type key
98 */
99#define OIDC_GRANT_TYPE_VALUE "authorization_code"
100
101/**
102 * OIDC code key
103 */
104#define OIDC_CODE_KEY "code"
105
106/**
107 * OIDC response_type key
108 */
109#define OIDC_RESPONSE_TYPE_KEY "response_type"
110
111/**
112 * OIDC client_id key
113 */
114#define OIDC_CLIENT_ID_KEY "client_id"
115
116/**
117 * OIDC scope key
118 */
119#define OIDC_SCOPE_KEY "scope"
120
121/**
122 * OIDC redirect_uri key
123 */
124#define OIDC_REDIRECT_URI_KEY "redirect_uri"
125
126/**
127 * OIDC state key
128 */
129#define OIDC_STATE_KEY "state"
130
131/**
132 * OIDC nonce key
133 */
134#define OIDC_NONCE_KEY "nonce"
135
136/**
137 * OIDC claims key
138 */
139#define OIDC_CLAIMS_KEY "claims"
140
141/**
142 * OIDC PKCE code challenge
143 */
144#define OIDC_CODE_CHALLENGE_KEY "code_challenge"
145
146/**
147 * OIDC PKCE code verifier
148 */
149#define OIDC_CODE_VERIFIER_KEY "code_verifier"
150
151/**
152 * OIDC cookie expiration (in seconds)
153 */
154#define OIDC_COOKIE_EXPIRATION 3
155
156/**
157 * OIDC cookie header key
158 */
159#define OIDC_COOKIE_HEADER_KEY "cookie"
160
161/**
162 * OIDC cookie header information key
163 */
164#define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
165
166/**
167 * OIDC cookie header information key
168 */
169#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
170
171/**
172 * OIDC cookie header if user cancelled
173 */
174#define OIDC_COOKIE_HEADER_ACCESS_DENIED "Identity=Denied"
175
176/**
177 * OIDC expected response_type while authorizing
178 */
179#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
180
181/**
182 * OIDC expected scope part while authorizing
183 */
184#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
185
186/**
187 * OIDC error key for invalid client
188 */
189#define OIDC_ERROR_KEY_INVALID_CLIENT "invalid_client"
190
191/**
192 * OIDC error key for invalid scopes
193 */
194#define OIDC_ERROR_KEY_INVALID_SCOPE "invalid_scope"
195
196/**
197 * OIDC error key for invalid requests
198 */
199#define OIDC_ERROR_KEY_INVALID_REQUEST "invalid_request"
200
201/**
202 * OIDC error key for invalid tokens
203 */
204#define OIDC_ERROR_KEY_INVALID_TOKEN "invalid_token"
205
206/**
207 * OIDC error key for invalid cookies
208 */
209#define OIDC_ERROR_KEY_INVALID_COOKIE "invalid_cookie"
210
211/**
212 * OIDC error key for generic server errors
213 */
214#define OIDC_ERROR_KEY_SERVER_ERROR "server_error"
215
216/**
217 * OIDC error key for unsupported grants
218 */
219#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE "unsupported_grant_type"
220
221/**
222 * OIDC error key for unsupported response types
223 */
224#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE "unsupported_response_type"
225
226/**
227 * OIDC error key for unauthorized clients
228 */
229#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT "unauthorized_client"
230
231/**
232 * OIDC error key for denied access
233 */
234#define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
235
236/**
237 * OIDC key store file name
238 */
239#define OIDC_JWK_RSA_FILENAME "jwk_rsa.json"
240
241/**
242 * How long to wait for a consume in userinfo endpoint
243 */
244#define CONSUME_TIMEOUT GNUNET_TIME_relative_multiply ( \
245 GNUNET_TIME_UNIT_SECONDS,2)
246
247/**
248 * OIDC ignored parameter array
249 */
250static char *OIDC_ignored_parameter_array[] = { "display",
251 "prompt",
252 "ui_locales",
253 "response_mode",
254 "id_token_hint",
255 "login_hint",
256 "acr_values" };
257
258/**
259 * OIDC hashmap for cached access tokens and codes
260 */
261struct GNUNET_CONTAINER_MultiHashMap *oidc_code_cache;
262
263/**
264 * OIDC hashmap that keeps track of issued cookies
265 */
266struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map;
267
268/**
269 * The configuration handle
270 */
271const struct GNUNET_CONFIGURATION_Handle *cfg;
272
273/**
274 * HTTP methods allows for this plugin
275 */
276static char *allow_methods;
277
278/**
279 * Ego list
280 */
281static struct EgoEntry *ego_head;
282
283/**
284 * Ego list
285 */
286static struct EgoEntry *ego_tail;
287
288/**
289 * The processing state
290 */
291static int state;
292
293/**
294 * Handle to Identity service.
295 */
296static struct GNUNET_IDENTITY_Handle *identity_handle;
297
298/**
299 * GNS handle
300 */
301static struct GNUNET_GNS_Handle *gns_handle;
302
303/**
304 * Identity Provider
305 */
306static struct GNUNET_RECLAIM_Handle *idp;
307
308/**
309 * Timeout for consume call on userinfo
310 */
311static struct GNUNET_TIME_Relative consume_timeout;
312
313/**
314 * @brief struct returned by the initialization function of the plugin
315 */
316struct Plugin
317{
318 const struct GNUNET_CONFIGURATION_Handle *cfg;
319};
320
321/**
322 * @brief The RSA key used by the oidc enpoint
323 */
324json_t *oidc_jwk;
325
326/**
327 * OIDC needed variables
328 */
329struct OIDC_Variables
330{
331 /**
332 * The RP client public key
333 */
334 struct GNUNET_CRYPTO_PublicKey client_pkey;
335
336 /**
337 * The OIDC client id of the RP
338 */
339 char *client_id;
340
341 /**
342 * The OIDC redirect uri
343 */
344 char *redirect_uri;
345
346 /**
347 * The list of oidc scopes
348 */
349 char *scope;
350
351 /**
352 * The OIDC state
353 */
354 char *state;
355
356 /**
357 * The OIDC nonce
358 */
359 char *nonce;
360
361 /**
362 * The OIDC claims
363 */
364 char *claims;
365
366 /**
367 * The OIDC response type
368 */
369 char *response_type;
370
371 /**
372 * The identity chosen by the user to login
373 */
374 char *login_identity;
375
376 /**
377 * User cancelled authorization/login
378 */
379 int user_cancelled;
380
381 /**
382 * The PKCE code_challenge
383 */
384 char *code_challenge;
385
386 /**
387 * The PKCE code_verifier
388 */
389 char *code_verifier;
390
391};
392
393/**
394 * The ego list
395 */
396struct EgoEntry
397{
398 /**
399 * DLL
400 */
401 struct EgoEntry *next;
402
403 /**
404 * DLL
405 */
406 struct EgoEntry *prev;
407
408 /**
409 * Ego Identifier
410 */
411 char *identifier;
412
413 /**
414 * Public key string
415 */
416 char *keystring;
417
418 /**
419 * The Ego
420 */
421 struct GNUNET_IDENTITY_Ego *ego;
422};
423
424
425struct RequestHandle
426{
427 /**
428 * DLL
429 */
430 struct RequestHandle *next;
431
432 /**
433 * DLL
434 */
435 struct RequestHandle *prev;
436
437 /**
438 * Selected ego
439 */
440 struct EgoEntry *ego_entry;
441
442 /**
443 * Pointer to ego private key
444 */
445 struct GNUNET_CRYPTO_PrivateKey priv_key;
446
447 /**
448 * OIDC variables
449 */
450 struct OIDC_Variables *oidc;
451
452 /**
453 * GNS lookup op
454 */
455 struct GNUNET_GNS_LookupRequest *gns_op;
456
457 /**
458 * Rest connection
459 */
460 struct GNUNET_REST_RequestHandle *rest_handle;
461
462 /**
463 * Attribute claim list for id_token
464 */
465 struct GNUNET_RECLAIM_AttributeList *attr_idtoken_list;
466
467 /**
468 * Attribute claim list for userinfo
469 */
470 struct GNUNET_RECLAIM_AttributeList *attr_userinfo_list;
471
472 /**
473 * Credentials
474 */
475 struct GNUNET_RECLAIM_CredentialList *credentials;
476
477 /**
478 * Presentations
479 */
480 struct GNUNET_RECLAIM_PresentationList *presentations;
481
482 /**
483 * IDENTITY Operation
484 */
485 struct GNUNET_IDENTITY_Operation *op;
486
487
488 /**
489 * Idp Operation
490 */
491 struct GNUNET_RECLAIM_Operation *idp_op;
492
493 /**
494 * Timeout task for consume
495 */
496 struct GNUNET_SCHEDULER_Task *consume_timeout_op;
497
498 /**
499 * Attribute iterator
500 */
501 struct GNUNET_RECLAIM_AttributeIterator *attr_it;
502
503 /**
504 * Credential iterator
505 */
506 struct GNUNET_RECLAIM_CredentialIterator *cred_it;
507
508
509 /**
510 * Ticket iterator
511 */
512 struct GNUNET_RECLAIM_TicketIterator *ticket_it;
513
514 /**
515 * A ticket
516 */
517 struct GNUNET_RECLAIM_Ticket ticket;
518
519 /**
520 * Desired timeout for the lookup (default is no timeout).
521 */
522 struct GNUNET_TIME_Relative timeout;
523
524 /**
525 * ID of a task associated with the resolution process.
526 */
527 struct GNUNET_SCHEDULER_Task *timeout_task;
528
529 /**
530 * The plugin result processor
531 */
532 GNUNET_REST_ResultProcessor proc;
533
534 /**
535 * The closure of the result processor
536 */
537 void *proc_cls;
538
539 /**
540 * The url
541 */
542 char *url;
543
544 /**
545 * The passed access token
546 */
547 char *access_token;
548
549 /**
550 * The tld for redirect
551 */
552 char *tld;
553
554 /**
555 * The redirect prefix
556 */
557 char *redirect_prefix;
558
559 /**
560 * The redirect suffix
561 */
562 char *redirect_suffix;
563
564 /**
565 * Error response message
566 */
567 char *emsg;
568
569 /**
570 * Error response description
571 */
572 char *edesc;
573
574 /**
575 * Response code
576 */
577 int response_code;
578
579 /**
580 * Public client
581 */
582 int public_client;
583};
584
585/**
586 * DLL
587 */
588static struct RequestHandle *requests_head;
589
590/**
591 * DLL
592 */
593static struct RequestHandle *requests_tail;
594
595
596/**
597 * Cleanup lookup handle
598 * @param handle Handle to clean up
599 */
600static void
601cleanup_handle (struct RequestHandle *handle)
602{
603
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
605 if (NULL != handle->timeout_task)
606 GNUNET_SCHEDULER_cancel (handle->timeout_task);
607 if (NULL != handle->attr_it)
608 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
609 if (NULL != handle->cred_it)
610 GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
611 if (NULL != handle->ticket_it)
612 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
613 if (NULL != handle->idp_op)
614 GNUNET_RECLAIM_cancel (handle->idp_op);
615 if (NULL != handle->consume_timeout_op)
616 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
617 GNUNET_free (handle->url);
618 GNUNET_free (handle->tld);
619 GNUNET_free (handle->redirect_prefix);
620 GNUNET_free (handle->redirect_suffix);
621 GNUNET_free (handle->emsg);
622 GNUNET_free (handle->edesc);
623 if (NULL != handle->gns_op)
624 GNUNET_GNS_lookup_cancel (handle->gns_op);
625 if (NULL != handle->oidc)
626 {
627 GNUNET_free (handle->oidc->client_id);
628 GNUNET_free (handle->oidc->login_identity);
629 GNUNET_free (handle->oidc->nonce);
630 GNUNET_free (handle->oidc->redirect_uri);
631 GNUNET_free (handle->oidc->response_type);
632 GNUNET_free (handle->oidc->scope);
633 GNUNET_free (handle->oidc->state);
634 if (NULL != handle->oidc->claims)
635 GNUNET_free (handle->oidc->claims);
636 if (NULL != handle->oidc->code_challenge)
637 GNUNET_free (handle->oidc->code_challenge);
638 GNUNET_free (handle->oidc);
639 }
640 if (NULL!=handle->attr_idtoken_list)
641 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list);
642 if (NULL!=handle->attr_userinfo_list)
643 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
644 if (NULL!=handle->credentials)
645 GNUNET_RECLAIM_credential_list_destroy (handle->credentials);
646 if (NULL!=handle->presentations)
647 GNUNET_RECLAIM_presentation_list_destroy (handle->presentations);
648 GNUNET_CONTAINER_DLL_remove (requests_head,
649 requests_tail,
650 handle);
651 if (NULL != handle->access_token)
652 GNUNET_free (handle->access_token);
653 GNUNET_free (handle);
654}
655
656
657/**
658 * Task run on error, sends error message. Cleans up everything.
659 *
660 * @param cls the `struct RequestHandle`
661 */
662static void
663do_error (void *cls)
664{
665 struct RequestHandle *handle = cls;
666 struct MHD_Response *resp;
667 char *json_error;
668
669 GNUNET_asprintf (&json_error,
670 "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
671 handle->emsg,
672 (NULL != handle->edesc) ? handle->edesc : "",
673 (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
674 (NULL != handle->oidc->state) ? handle->oidc->state : "",
675 (NULL != handle->oidc->state) ? "\"" : "");
676 if (0 == handle->response_code)
677 handle->response_code = MHD_HTTP_BAD_REQUEST;
678 resp = GNUNET_REST_create_response (json_error);
679 if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
680 GNUNET_assert (MHD_NO !=
681 MHD_add_response_header (resp,
682 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
683 "Basic"));
684 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
685 MHD_HTTP_HEADER_CONTENT_TYPE,
686 "application/json"));
687 handle->proc (handle->proc_cls, resp, handle->response_code);
688 cleanup_handle (handle);
689 GNUNET_free (json_error);
690}
691
692
693/**
694 * Task run on error in userinfo endpoint, sends error header. Cleans up
695 * everything
696 *
697 * @param cls the `struct RequestHandle`
698 */
699static void
700do_userinfo_error (void *cls)
701{
702 struct RequestHandle *handle = cls;
703 struct MHD_Response *resp;
704 char *error;
705
706 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
707 "Error: %s\n", handle->edesc);
708 GNUNET_asprintf (&error,
709 "error=\"%s\", error_description=\"%s\"",
710 handle->emsg,
711 (NULL != handle->edesc) ? handle->edesc : "");
712 resp = GNUNET_REST_create_response ("");
713 GNUNET_assert (MHD_NO !=
714 MHD_add_response_header (resp,
715 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
716 "Bearer"));
717 handle->proc (handle->proc_cls, resp, handle->response_code);
718 cleanup_handle (handle);
719 GNUNET_free (error);
720}
721
722
723/**
724 * Task run on error, sends error message and redirects. Cleans up everything.
725 *
726 * @param cls the `struct RequestHandle`
727 */
728static void
729do_redirect_error (void *cls)
730{
731 struct RequestHandle *handle = cls;
732 struct MHD_Response *resp;
733 char *redirect;
734
735 GNUNET_asprintf (&redirect,
736 "%s?error=%s&error_description=%s%s%s",
737 handle->oidc->redirect_uri,
738 handle->emsg,
739 handle->edesc,
740 (NULL != handle->oidc->state) ? "&state=" : "",
741 (NULL != handle->oidc->state) ? handle->oidc->state : "");
742 resp = GNUNET_REST_create_response ("");
743 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
744 "Location", redirect));
745 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
746 cleanup_handle (handle);
747 GNUNET_free (redirect);
748}
749
750
751/**
752 * Task run on timeout, sends error message. Cleans up everything.
753 *
754 * @param cls the `struct RequestHandle`
755 */
756static void
757do_timeout (void *cls)
758{
759 struct RequestHandle *handle = cls;
760
761 handle->timeout_task = NULL;
762 do_error (handle);
763}
764
765
766/**
767 * Respond to OPTIONS request
768 *
769 * @param con_handle the connection handle
770 * @param url the url
771 * @param cls the RequestHandle
772 */
773static void
774options_cont (struct GNUNET_REST_RequestHandle *con_handle,
775 const char *url,
776 void *cls)
777{
778 struct MHD_Response *resp;
779 struct RequestHandle *handle = cls;
780
781 // For now, independent of path return all options
782 resp = GNUNET_REST_create_response (NULL);
783 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
784 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
785 cleanup_handle (handle);
786 return;
787}
788
789
790/**
791 * Interprets cookie header and pass its identity keystring to handle
792 */
793static void
794cookie_identity_interpretation (struct RequestHandle *handle)
795{
796 struct GNUNET_HashCode cache_key;
797 char *cookies;
798 struct GNUNET_TIME_Absolute current_time, *relog_time;
799 char delimiter[] = "; ";
800 char *tmp_cookies;
801 char *token;
802 char *value;
803
804 // gets identity of login try with cookie
805 GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY,
806 strlen (OIDC_COOKIE_HEADER_KEY),
807 &cache_key);
808 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
809 ->header_param_map,
810 &cache_key))
811 {
812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
813 return;
814 }
815 // splits cookies and find 'Identity' cookie
816 tmp_cookies =
817 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
818 &cache_key);
819 cookies = GNUNET_strdup (tmp_cookies);
820 token = strtok (cookies, delimiter);
821 handle->oidc->user_cancelled = GNUNET_NO;
822 handle->oidc->login_identity = NULL;
823 if (NULL == token)
824 {
825 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
826 "Unable to parse cookie: %s\n",
827 cookies);
828 GNUNET_free (cookies);
829 return;
830 }
831
832 while (NULL != token)
833 {
834 if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
835 {
836 handle->oidc->user_cancelled = GNUNET_YES;
837 GNUNET_free (cookies);
838 return;
839 }
840 if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
841 break;
842 token = strtok (NULL, delimiter);
843 }
844 if (NULL == token)
845 {
846 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
847 "No cookie value to process: %s\n",
848 cookies);
849 GNUNET_free (cookies);
850 return;
851 }
852 GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
853 if (GNUNET_NO ==
854 GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
855 {
856 GNUNET_log (
857 GNUNET_ERROR_TYPE_WARNING,
858 "Found cookie `%s', but no corresponding expiration entry present...\n",
859 token);
860 GNUNET_free (cookies);
861 return;
862 }
863 relog_time =
864 GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
865 current_time = GNUNET_TIME_absolute_get ();
866 // 30 min after old login -> redirect to login
867 if (current_time.abs_value_us > relog_time->abs_value_us)
868 {
869 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
870 "Found cookie `%s', but it is expired.\n",
871 token);
872 GNUNET_free (cookies);
873 return;
874 }
875 value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
876 GNUNET_assert (NULL != value);
877 handle->oidc->login_identity = GNUNET_strdup (value);
878 GNUNET_free (cookies);
879}
880
881
882/**
883 * @brief Read the the JSON Web Key in the given file and return it.
884 * Return NULL and emit warning if JSON can not be decoded or the key is
885 * invalid
886 *
887 * @param filename the file to read the JWK from
888 * @return json_t* the reed JWK
889 */
890json_t *
891read_jwk_from_file (const char *filename)
892{
893 json_t *jwk;
894 json_error_t error;
895
896 jwk = json_load_file (filename, JSON_DECODE_ANY, &error);
897
898 if (! jwk)
899 {
900 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
901 ("Could not read OIDC RSA key from config file; %s\n"),
902 error.text);
903 }
904
905 return jwk;
906}
907
908/**
909 * @brief Write the JWK to file. If unsuccessful emit warning
910 *
911 * @param filename the name of the file the JWK is writen to
912 * @param jwk the JWK that is going to be written
913 * @return int Return GNUNET_OK if write is sucessfull
914 */
915static int
916write_jwk_to_file (const char *filename,
917 json_t *jwk)
918{
919 if (json_dump_file (jwk, filename, JSON_INDENT (2)))
920 {
921 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
922 ("Could not write OIDC RSA key to file %s\n"),
923 filename);
924 return GNUNET_ERROR_TYPE_WARNING;
925 }
926 else
927 return GNUNET_OK;
928}
929
930/**
931 * @brief Generate a new RSA JSON Web Key
932 *
933 * @return json_t* the generated JWK
934 */
935json_t *
936generate_jwk ()
937{
938 json_t *jwk;
939 jwk = json_pack ("{s:s,s:i}", "kty", "RSA", "bits", 2048);
940 jose_jwk_gen (NULL, jwk);
941 json_incref (jwk);
942 return jwk;
943}
944
945/**
946 * Return the path to the oidc directory path
947 *
948 * @param cls the RequestHandle
949 */
950char *
951get_oidc_dir_path (void *cls)
952{
953 char *oidc_directory;
954 struct RequestHandle *handle = cls;
955
956 // Read OIDC directory from config
957 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
958 "reclaim-rest-plugin",
959 "oidc_dir",
960 &oidc_directory))
961 {
962 // Could not read Config file
963 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
964 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
965 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
966 GNUNET_SCHEDULER_add_now (&do_error, handle);
967 return NULL;
968 }
969
970 return oidc_directory;
971}
972
973/**
974 * Return the path to the RSA JWK key file
975 *
976 * @param cls the RequestHandle
977 */
978char *
979get_oidc_jwk_path (void *cls)
980{
981 char *oidc_directory;
982 char *oidc_jwk_path;
983
984 oidc_directory = get_oidc_dir_path (cls);
985
986 // Create path to file
987 GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory,
988 OIDC_JWK_RSA_FILENAME);
989
990 return oidc_jwk_path;
991}
992
993
994/**
995 * Redirects to login page stored in configuration file
996 */
997static void
998login_redirect (void *cls)
999{
1000 char *login_base_url;
1001 char *new_redirect;
1002 char *tmp;
1003 struct MHD_Response *resp;
1004 struct GNUNET_Buffer buf = { 0 };
1005 struct RequestHandle *handle = cls;
1006
1007 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
1008 "reclaim-rest-plugin",
1009 "address",
1010 &login_base_url))
1011 {
1012 GNUNET_buffer_write_str (&buf, login_base_url);
1013 GNUNET_buffer_write_fstr (&buf,
1014 "?%s=%s",
1015 OIDC_RESPONSE_TYPE_KEY,
1016 handle->oidc->response_type);
1017 GNUNET_buffer_write_fstr (&buf,
1018 "&%s=%s",
1019 OIDC_CLIENT_ID_KEY,
1020 handle->oidc->client_id);
1021 GNUNET_STRINGS_urlencode (handle->oidc->redirect_uri,
1022 strlen (handle->oidc->redirect_uri),
1023 &tmp);
1024 GNUNET_buffer_write_fstr (&buf,
1025 "&%s=%s",
1026 OIDC_REDIRECT_URI_KEY,
1027 tmp);
1028 GNUNET_free (tmp);
1029 GNUNET_STRINGS_urlencode (handle->oidc->scope,
1030 strlen (handle->oidc->scope),
1031 &tmp);
1032 GNUNET_buffer_write_fstr (&buf,
1033 "&%s=%s",
1034 OIDC_SCOPE_KEY,
1035 tmp);
1036 GNUNET_free (tmp);
1037 if (NULL != handle->oidc->state)
1038 {
1039 GNUNET_STRINGS_urlencode (handle->oidc->state,
1040 strlen (handle->oidc->state),
1041 &tmp);
1042 GNUNET_buffer_write_fstr (&buf,
1043 "&%s=%s",
1044 OIDC_STATE_KEY,
1045 handle->oidc->state);
1046 GNUNET_free (tmp);
1047 }
1048 if (NULL != handle->oidc->code_challenge)
1049 {
1050 GNUNET_buffer_write_fstr (&buf,
1051 "&%s=%s",
1052 OIDC_CODE_CHALLENGE_KEY,
1053 handle->oidc->code_challenge);
1054 }
1055 if (NULL != handle->oidc->nonce)
1056 {
1057 GNUNET_buffer_write_fstr (&buf,
1058 "&%s=%s",
1059 OIDC_NONCE_KEY,
1060 handle->oidc->nonce);
1061 }
1062 if (NULL != handle->oidc->claims)
1063 {
1064 GNUNET_STRINGS_urlencode (handle->oidc->claims,
1065 strlen (handle->oidc->claims),
1066 &tmp);
1067 GNUNET_buffer_write_fstr (&buf,
1068 "&%s=%s",
1069 OIDC_CLAIMS_KEY,
1070 tmp);
1071 GNUNET_free (tmp);
1072 }
1073 new_redirect = GNUNET_buffer_reap_str (&buf);
1074 resp = GNUNET_REST_create_response ("");
1075 MHD_add_response_header (resp, "Location", new_redirect);
1076 GNUNET_free (login_base_url);
1077 }
1078 else
1079 {
1080 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1081 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1082 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1083 GNUNET_SCHEDULER_add_now (&do_error, handle);
1084 return;
1085 }
1086 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1087 GNUNET_free (new_redirect);
1088 cleanup_handle (handle);
1089}
1090
1091
1092/**
1093 * Does internal server error when iteration failed.
1094 */
1095static void
1096oidc_iteration_error (void *cls)
1097{
1098 struct RequestHandle *handle = cls;
1099
1100 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1101 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1102 GNUNET_SCHEDULER_add_now (&do_error, handle);
1103}
1104
1105
1106/**
1107 * Issues ticket and redirects to relying party with the authorization code as
1108 * parameter. Otherwise redirects with error
1109 */
1110static void
1111oidc_ticket_issue_cb (void *cls,
1112 const struct GNUNET_RECLAIM_Ticket *ticket,
1113 const struct
1114 GNUNET_RECLAIM_PresentationList *presentation)
1115{
1116 struct RequestHandle *handle = cls;
1117 struct MHD_Response *resp;
1118 char *ticket_str;
1119 char *redirect_uri;
1120 char *code_string;
1121
1122 handle->idp_op = NULL;
1123 if (NULL == ticket)
1124 {
1125 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1126 handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
1127 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1128 return;
1129 }
1130 handle->ticket = *ticket;
1131 ticket_str =
1132 GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
1133 sizeof(struct GNUNET_RECLAIM_Ticket));
1134 code_string = OIDC_build_authz_code (&handle->priv_key,
1135 &handle->ticket,
1136 handle->attr_idtoken_list,
1137 presentation,
1138 handle->oidc->nonce,
1139 handle->oidc->code_challenge);
1140 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1141 (NULL != handle->tld))
1142 {
1143 GNUNET_asprintf (&redirect_uri,
1144 "%s.%s/%s%s%s=%s&state=%s",
1145 handle->redirect_prefix,
1146 handle->tld,
1147 handle->redirect_suffix,
1148 (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1149 "&"),
1150 handle->oidc->response_type,
1151 code_string,
1152 handle->oidc->state);
1153 }
1154 else
1155 {
1156 GNUNET_asprintf (&redirect_uri,
1157 "%s%s%s=%s&state=%s",
1158 handle->oidc->redirect_uri,
1159 (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1160 "&"),
1161 handle->oidc->response_type,
1162 code_string,
1163 handle->oidc->state);
1164 }
1165 resp = GNUNET_REST_create_response ("");
1166 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1167 "Location", redirect_uri));
1168 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1169 cleanup_handle (handle);
1170 GNUNET_free (redirect_uri);
1171 GNUNET_free (ticket_str);
1172 GNUNET_free (code_string);
1173}
1174
1175
1176static struct GNUNET_RECLAIM_AttributeList*
1177attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a,
1178 struct GNUNET_RECLAIM_AttributeList *list_b)
1179{
1180 struct GNUNET_RECLAIM_AttributeList *merged_list;
1181 struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1182 struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1183 struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1184
1185 merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1186 for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1187 {
1188 le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1189 le_m->attribute = GNUNET_RECLAIM_attribute_new (le_a->attribute->name,
1190 &le_a->attribute->
1191 credential,
1192 le_a->attribute->type,
1193 le_a->attribute->data,
1194 le_a->attribute->data_size);
1195 le_m->attribute->id = le_a->attribute->id;
1196 le_m->attribute->flag = le_a->attribute->flag;
1197 le_m->attribute->credential = le_a->attribute->credential;
1198 GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1199 merged_list->list_tail,
1200 le_m);
1201 }
1202 le_m = NULL;
1203 for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1204 {
1205 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1206 {
1207 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&le_m->attribute->id,
1208 &le_b->attribute->id))
1209 break; /** Attribute already in list **/
1210 }
1211 if (NULL != le_m)
1212 continue; /** Attribute already in list **/
1213 le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1214 le_m->attribute = GNUNET_RECLAIM_attribute_new (le_b->attribute->name,
1215 &le_b->attribute->
1216 credential,
1217 le_b->attribute->type,
1218 le_b->attribute->data,
1219 le_b->attribute->data_size);
1220 le_m->attribute->id = le_b->attribute->id;
1221 le_m->attribute->flag = le_b->attribute->flag;
1222 le_m->attribute->credential = le_b->attribute->credential;
1223 GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1224 merged_list->list_tail,
1225 le_m);
1226 }
1227 return merged_list;
1228}
1229
1230
1231static void
1232oidc_cred_collect_finished_cb (void *cls)
1233{
1234 struct RequestHandle *handle = cls;
1235 struct GNUNET_RECLAIM_AttributeList *merged_list;
1236 struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1237
1238 handle->cred_it = NULL;
1239 merged_list = attribute_list_merge (handle->attr_idtoken_list,
1240 handle->attr_userinfo_list);
1241 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1243 "List Attribute in ticket to issue: %s\n",
1244 le_m->attribute->name);
1245 handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
1246 &handle->priv_key,
1247 &handle->oidc->client_pkey,
1248 merged_list,
1249 &oidc_ticket_issue_cb,
1250 handle);
1251 GNUNET_RECLAIM_attribute_list_destroy (merged_list);
1252}
1253
1254
1255/**
1256 * Collects all attributes for an ego if in scope parameter
1257 */
1258static void
1259oidc_cred_collect (void *cls,
1260 const struct GNUNET_CRYPTO_PublicKey *identity,
1261 const struct GNUNET_RECLAIM_Credential *cred)
1262{
1263 struct RequestHandle *handle = cls;
1264 struct GNUNET_RECLAIM_AttributeListEntry *le;
1265 struct GNUNET_RECLAIM_CredentialListEntry *ale;
1266
1267 for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1268 {
1269 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&ale->credential->id,
1270 &cred->id))
1271 continue;
1272 /** Credential already in list **/
1273 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
1274 return;
1275 }
1276
1277 for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1278 {
1279 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
1280 &cred->id))
1281 continue;
1282 /** Credential matches for attribute, add **/
1283 ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
1284 ale->credential = GNUNET_RECLAIM_credential_new (cred->name,
1285 cred->type,
1286 cred->data,
1287 cred->data_size);
1288 GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1289 handle->credentials->list_tail,
1290 ale);
1291 }
1292 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
1293}
1294
1295
1296static void
1297oidc_attr_collect_finished_cb (void *cls)
1298{
1299 struct RequestHandle *handle = cls;
1300
1301 handle->attr_it = NULL;
1302 handle->ticket_it = NULL;
1303 if (NULL == handle->attr_idtoken_list->list_head)
1304 {
1305 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_SCOPE);
1306 handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1307 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1308 return;
1309 }
1310 handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1311 handle->cred_it =
1312 GNUNET_RECLAIM_get_credentials_start (idp,
1313 &handle->priv_key,
1314 &oidc_iteration_error,
1315 handle,
1316 &oidc_cred_collect,
1317 handle,
1318 &oidc_cred_collect_finished_cb,
1319 handle);
1320
1321}
1322
1323
1324static int
1325attr_in_claims_request (struct RequestHandle *handle,
1326 const char *attr_name,
1327 const char *claims_parameter)
1328{
1329 int ret = GNUNET_NO;
1330 json_t *root;
1331 json_error_t error;
1332 json_t *claims_j;
1333 const char *key;
1334 json_t *value;
1335
1336 /** Check if attribute is requested through a scope **/
1337 if (GNUNET_YES == OIDC_check_scopes_for_claim_request (handle->oidc->scope,
1338 attr_name))
1339 return GNUNET_YES;
1340
1341 /** Try claims parameter if not in scope */
1342 if (NULL != handle->oidc->claims)
1343 {
1344 root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1345 claims_j = json_object_get (root, claims_parameter);
1346 /* obj is a JSON object */
1347 if (NULL != claims_j)
1348 {
1349 json_object_foreach (claims_j, key, value) {
1350 if (0 != strcmp (attr_name, key))
1351 continue;
1352 ret = GNUNET_YES;
1353 break;
1354 }
1355 }
1356 json_decref (root);
1357 }
1358 return ret;
1359}
1360
1361
1362static int
1363attr_in_idtoken_request (struct RequestHandle *handle,
1364 const char *attr_name)
1365{
1366 return attr_in_claims_request (handle, attr_name, "id_token");
1367}
1368
1369
1370static int
1371attr_in_userinfo_request (struct RequestHandle *handle,
1372 const char *attr_name)
1373{
1374 return attr_in_claims_request (handle, attr_name, "userinfo");
1375}
1376
1377
1378/**
1379 * Collects all attributes for an ego if in scope parameter
1380 */
1381static void
1382oidc_attr_collect (void *cls,
1383 const struct GNUNET_CRYPTO_PublicKey *identity,
1384 const struct GNUNET_RECLAIM_Attribute *attr)
1385{
1386 struct RequestHandle *handle = cls;
1387 struct GNUNET_RECLAIM_AttributeListEntry *le;
1388 if (GNUNET_YES == attr_in_idtoken_request (handle, attr->name))
1389 {
1390 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1391 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
1392 &attr->credential,
1393 attr->type,
1394 attr->data,
1395 attr->data_size);
1396 le->attribute->id = attr->id;
1397 le->attribute->flag = attr->flag;
1398 le->attribute->credential = attr->credential;
1399 GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1400 handle->attr_idtoken_list->list_tail,
1401 le);
1402 }
1403 if (GNUNET_YES == attr_in_userinfo_request (handle, attr->name))
1404 {
1405 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1406 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
1407 &attr->credential,
1408 attr->type,
1409 attr->data,
1410 attr->data_size);
1411 le->attribute->id = attr->id;
1412 le->attribute->flag = attr->flag;
1413 le->attribute->credential = attr->credential;
1414 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1415 handle->attr_userinfo_list->list_tail,
1416 le);
1417 }
1418
1419 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1420}
1421
1422
1423/**
1424 * Checks time and cookie and redirects accordingly
1425 */
1426static void
1427code_redirect (void *cls)
1428{
1429 struct RequestHandle *handle = cls;
1430 struct GNUNET_TIME_Absolute current_time;
1431 struct GNUNET_TIME_Absolute *relog_time;
1432 struct GNUNET_CRYPTO_PublicKey pubkey;
1433 struct GNUNET_CRYPTO_PublicKey ego_pkey;
1434 struct GNUNET_HashCode cache_key;
1435 char *identity_cookie;
1436
1437 GNUNET_asprintf (&identity_cookie,
1438 "Identity=%s",
1439 handle->oidc->login_identity);
1440 GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1441 GNUNET_free (identity_cookie);
1442 // No login time for identity -> redirect to login
1443 if (GNUNET_YES ==
1444 GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
1445 {
1446 relog_time =
1447 GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1448 current_time = GNUNET_TIME_absolute_get ();
1449 // 30 min after old login -> redirect to login
1450 if (current_time.abs_value_us <= relog_time->abs_value_us)
1451 {
1452 if (GNUNET_OK !=
1453 GNUNET_CRYPTO_public_key_from_string (handle->oidc
1454 ->login_identity,
1455 &pubkey))
1456 {
1457 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_COOKIE);
1458 handle->edesc =
1459 GNUNET_strdup ("The cookie of a login identity is not valid");
1460 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1461 return;
1462 }
1463 // iterate over egos and compare their public key
1464 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1465 handle->ego_entry = handle->ego_entry->next)
1466 {
1467 GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1468 if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1469 {
1470 handle->priv_key =
1471 *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
1472 handle->attr_idtoken_list =
1473 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1474 handle->attr_userinfo_list =
1475 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1476 handle->attr_it =
1477 GNUNET_RECLAIM_get_attributes_start (idp,
1478 &handle->priv_key,
1479 &oidc_iteration_error,
1480 handle,
1481 &oidc_attr_collect,
1482 handle,
1483 &oidc_attr_collect_finished_cb,
1484 handle);
1485 return;
1486 }
1487 }
1488 GNUNET_SCHEDULER_add_now (&login_redirect, handle);
1489 return;
1490 }
1491 }
1492}
1493
1494
1495static void
1496build_redirect (void *cls)
1497{
1498 struct RequestHandle *handle = cls;
1499 struct MHD_Response *resp;
1500 char *redirect_uri;
1501
1502 if (GNUNET_YES == handle->oidc->user_cancelled)
1503 {
1504 if ((NULL != handle->redirect_prefix) &&
1505 (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1506 {
1507 GNUNET_asprintf (&redirect_uri,
1508 "%s.%s/%s?error=%s&error_description=%s&state=%s",
1509 handle->redirect_prefix,
1510 handle->tld,
1511 handle->redirect_suffix,
1512 "access_denied",
1513 "User denied access",
1514 handle->oidc->state);
1515 }
1516 else
1517 {
1518 GNUNET_asprintf (&redirect_uri,
1519 "%s?error=%s&error_description=%s&state=%s",
1520 handle->oidc->redirect_uri,
1521 "access_denied",
1522 "User denied access",
1523 handle->oidc->state);
1524 }
1525 resp = GNUNET_REST_create_response ("");
1526 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1527 "Location",
1528 redirect_uri));
1529 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1530 cleanup_handle (handle);
1531 GNUNET_free (redirect_uri);
1532 return;
1533 }
1534 GNUNET_SCHEDULER_add_now (&code_redirect, handle);
1535}
1536
1537
1538static void
1539lookup_redirect_uri_result (void *cls,
1540 uint32_t rd_count,
1541 const struct GNUNET_GNSRECORD_Data *rd)
1542{
1543 struct RequestHandle *handle = cls;
1544 char *tmp;
1545 char *tmp_key_str;
1546 char *pos;
1547 struct GNUNET_CRYPTO_PublicKey redirect_zone;
1548
1549 handle->gns_op = NULL;
1550 if (0 == rd_count)
1551 {
1552 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1553 handle->edesc =
1554 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1555 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1556 return;
1557 }
1558 for (int i = 0; i < rd_count; i++)
1559 {
1560 if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1561 continue;
1562 if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1563 continue;
1564 tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1565 if (NULL == strstr (tmp, handle->oidc->client_id))
1566 {
1567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1568 "Redirect uri %s does not contain client_id %s\n",
1569 tmp,
1570 handle->oidc->client_id);
1571 }
1572 else
1573 {
1574 pos = strrchr (tmp, (unsigned char) '.');
1575 if (NULL == pos)
1576 {
1577 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1578 "Redirect uri %s contains client_id but is malformed\n",
1579 tmp);
1580 GNUNET_free (tmp);
1581 continue;
1582 }
1583 *pos = '\0';
1584 handle->redirect_prefix = GNUNET_strdup (tmp);
1585 tmp_key_str = pos + 1;
1586 pos = strchr (tmp_key_str, (unsigned char) '/');
1587 if (NULL == pos)
1588 {
1589 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1590 "Redirect uri %s contains client_id but is malformed\n",
1591 tmp);
1592 GNUNET_free (tmp);
1593 continue;
1594 }
1595 *pos = '\0';
1596 handle->redirect_suffix = GNUNET_strdup (pos + 1);
1597
1598 GNUNET_STRINGS_string_to_data (tmp_key_str,
1599 strlen (tmp_key_str),
1600 &redirect_zone,
1601 sizeof(redirect_zone));
1602 }
1603 GNUNET_SCHEDULER_add_now (&build_redirect, handle);
1604 GNUNET_free (tmp);
1605 return;
1606 }
1607 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1608 handle->edesc =
1609 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1610 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1611}
1612
1613
1614/**
1615 * Initiate redirect back to client.
1616 */
1617static void
1618client_redirect (void *cls)
1619{
1620 struct RequestHandle *handle = cls;
1621
1622 /* Lookup client redirect uri to verify request */
1623 handle->gns_op =
1624 GNUNET_GNS_lookup (gns_handle,
1625 GNUNET_GNS_EMPTY_LABEL_AT,
1626 &handle->oidc->client_pkey,
1627 GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT,
1628 GNUNET_GNS_LO_DEFAULT,
1629 &lookup_redirect_uri_result,
1630 handle);
1631}
1632
1633
1634static char *
1635get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1636{
1637 struct GNUNET_HashCode hc;
1638 char *value;
1639 char *res;
1640
1641 GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1642 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1643 ->url_param_map,
1644 &hc))
1645 return NULL;
1646 value =
1647 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1648 if (NULL == value)
1649 return NULL;
1650 GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1651 return res;
1652}
1653
1654
1655/**
1656 * Iteration over all results finished, build final
1657 * response.
1658 *
1659 * @param cls the `struct RequestHandle`
1660 */
1661static void
1662build_authz_response (void *cls)
1663{
1664 struct RequestHandle *handle = cls;
1665 struct GNUNET_HashCode cache_key;
1666
1667 char *expected_scope;
1668 char delimiter[] = " ";
1669 int number_of_ignored_parameter, iterator;
1670
1671
1672 // REQUIRED value: redirect_uri
1673 handle->oidc->redirect_uri =
1674 get_url_parameter_copy (handle, OIDC_REDIRECT_URI_KEY);
1675 if (NULL == handle->oidc->redirect_uri)
1676 {
1677 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
1678 handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1679 GNUNET_SCHEDULER_add_now (&do_error, handle);
1680 return;
1681 }
1682
1683 // REQUIRED value: response_type
1684 handle->oidc->response_type =
1685 get_url_parameter_copy (handle, OIDC_RESPONSE_TYPE_KEY);
1686 if (NULL == handle->oidc->response_type)
1687 {
1688 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
1689 handle->edesc = GNUNET_strdup ("missing parameter response_type");
1690 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1691 return;
1692 }
1693
1694 // REQUIRED value: scope
1695 handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1696 if (NULL == handle->oidc->scope)
1697 {
1698 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_SCOPE);
1699 handle->edesc = GNUNET_strdup ("missing parameter scope");
1700 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1701 return;
1702 }
1703
1704 // OPTIONAL value: nonce
1705 handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
1706
1707 // OPTIONAL value: claims
1708 handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY);
1709
1710 // TODO check other values if needed
1711 number_of_ignored_parameter =
1712 sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1713 for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1714 {
1715 GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator],
1716 strlen (OIDC_ignored_parameter_array[iterator]),
1717 &cache_key);
1718 if (GNUNET_YES ==
1719 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1720 ->url_param_map,
1721 &cache_key))
1722 {
1723 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_ACCESS_DENIED);
1724 GNUNET_asprintf (&handle->edesc,
1725 "Server will not handle parameter: %s",
1726 OIDC_ignored_parameter_array[iterator]);
1727 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1728 return;
1729 }
1730 }
1731
1732 // We only support authorization code flows.
1733 if (0 != strcmp (handle->oidc->response_type,
1734 OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE))
1735 {
1736 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE);
1737 handle->edesc = GNUNET_strdup ("The authorization server does not support "
1738 "obtaining this authorization code.");
1739 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1740 return;
1741 }
1742
1743 // Checks if scope contains 'openid'
1744 expected_scope = GNUNET_strdup (handle->oidc->scope);
1745 char *test;
1746 test = strtok (expected_scope, delimiter);
1747 while (NULL != test)
1748 {
1749 if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1750 break;
1751 test = strtok (NULL, delimiter);
1752 }
1753 if (NULL == test)
1754 {
1755 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_SCOPE);
1756 handle->edesc =
1757 GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1758 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1759 GNUNET_free (expected_scope);
1760 return;
1761 }
1762
1763 GNUNET_free (expected_scope);
1764 if ((NULL == handle->oidc->login_identity) &&
1765 (GNUNET_NO == handle->oidc->user_cancelled))
1766 GNUNET_SCHEDULER_add_now (&login_redirect, handle);
1767 else
1768 GNUNET_SCHEDULER_add_now (&client_redirect, handle);
1769}
1770
1771
1772/**
1773 * Iterate over tlds in config
1774 */
1775static void
1776tld_iter (void *cls, const char *section, const char *option, const char *value)
1777{
1778 struct RequestHandle *handle = cls;
1779 struct GNUNET_CRYPTO_PublicKey pkey;
1780
1781 if (GNUNET_OK !=
1782 GNUNET_CRYPTO_public_key_from_string (value, &pkey))
1783 {
1784 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1785 return;
1786 }
1787 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1788 handle->tld = GNUNET_strdup (option + 1);
1789}
1790
1791
1792/**
1793 * Responds to authorization GET and url-encoded POST request
1794 *
1795 * @param con_handle the connection handle
1796 * @param url the url
1797 * @param cls the RequestHandle
1798 */
1799static void
1800authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1801 const char *url,
1802 void *cls)
1803{
1804 struct RequestHandle *handle = cls;
1805 struct EgoEntry *tmp_ego;
1806 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1807 struct GNUNET_CRYPTO_PublicKey pkey;
1808
1809 cookie_identity_interpretation (handle);
1810
1811 // RECOMMENDED value: state - REQUIRED for answers
1812 handle->oidc->state = get_url_parameter_copy (handle, OIDC_STATE_KEY);
1813
1814 // REQUIRED value: client_id
1815 handle->oidc->client_id = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
1816 if (NULL == handle->oidc->client_id)
1817 {
1818 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
1819 handle->edesc = GNUNET_strdup ("missing parameter client_id");
1820 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1821 GNUNET_SCHEDULER_add_now (&do_error, handle);
1822 return;
1823 }
1824
1825 // OPTIONAL value: code_challenge
1826 handle->oidc->code_challenge = get_url_parameter_copy (handle,
1827 OIDC_CODE_CHALLENGE_KEY);
1828 if (NULL == handle->oidc->code_challenge)
1829 {
1830 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1831 "OAuth authorization request does not contain PKCE parameters!\n");
1832 }
1833
1834 if (GNUNET_OK !=
1835 GNUNET_CRYPTO_public_key_from_string (handle->oidc->client_id,
1836 &handle->oidc->client_pkey))
1837 {
1838 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT);
1839 handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1840 "authorization code using this method.");
1841 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1842 GNUNET_SCHEDULER_add_now (&do_error, handle);
1843 return;
1844 }
1845
1846 // If we know this identity, translated the corresponding TLD
1847 // TODO: We might want to have a reverse lookup functionality for TLDs?
1848 for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1849 {
1850 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1851 GNUNET_CRYPTO_key_get_public (priv_key, &pkey);
1852 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1853 {
1854 handle->tld = GNUNET_strdup (tmp_ego->identifier);
1855 handle->ego_entry = ego_tail;
1856 }
1857 }
1858 if (NULL == handle->tld)
1859 GNUNET_CONFIGURATION_iterate_section_values (cfg, "gns", tld_iter, handle);
1860 if (NULL == handle->tld)
1861 handle->tld = GNUNET_strdup (handle->oidc->client_id);
1862 GNUNET_SCHEDULER_add_now (&build_authz_response, handle);
1863}
1864
1865
1866/**
1867 * Combines an identity with a login time and responds OK to login request
1868 *
1869 * @param con_handle the connection handle
1870 * @param url the url
1871 * @param cls the RequestHandle
1872 */
1873static void
1874login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1875 const char *url,
1876 void *cls)
1877{
1878 struct MHD_Response *resp = GNUNET_REST_create_response ("");
1879 struct RequestHandle *handle = cls;
1880 struct GNUNET_HashCode cache_key;
1881 struct GNUNET_TIME_Absolute *current_time;
1882 struct GNUNET_TIME_Absolute *last_time;
1883 char *cookie;
1884 char *header_val;
1885 json_t *root;
1886 json_error_t error;
1887 json_t *identity;
1888 char term_data[handle->rest_handle->data_size + 1];
1889
1890 term_data[handle->rest_handle->data_size] = '\0';
1891 GNUNET_memcpy (term_data,
1892 handle->rest_handle->data,
1893 handle->rest_handle->data_size);
1894 root = json_loads (term_data, JSON_DECODE_ANY, &error);
1895 identity = json_object_get (root, "identity");
1896 if (! json_is_string (identity))
1897 {
1898 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1899 "Error parsing json string from %s\n",
1900 term_data);
1901 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1902 json_decref (root);
1903 cleanup_handle (handle);
1904 return;
1905 }
1906 GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1907 GNUNET_asprintf (&header_val,
1908 "%s;Max-Age=%d",
1909 cookie,
1910 OIDC_COOKIE_EXPIRATION);
1911 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1912 "Set-Cookie", header_val));
1913 GNUNET_assert (MHD_NO !=
1914 MHD_add_response_header (resp,
1915 "Access-Control-Allow-Methods",
1916 "POST"));
1917 GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1918
1919 if (0 != strcmp (json_string_value (identity), "Denied"))
1920 {
1921 current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1922 *current_time = GNUNET_TIME_relative_to_absolute (
1923 GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
1924 OIDC_COOKIE_EXPIRATION));
1925 last_time =
1926 GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1927 GNUNET_free (last_time);
1928 GNUNET_CONTAINER_multihashmap_put (OIDC_cookie_jar_map,
1929 &cache_key,
1930 current_time,
1931 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1932 }
1933 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1934 GNUNET_free (cookie);
1935 GNUNET_free (header_val);
1936 json_decref (root);
1937 cleanup_handle (handle);
1938}
1939
1940
1941static int
1942parse_credentials_basic_auth (struct RequestHandle *handle,
1943 char **client_id,
1944 char **client_secret)
1945{
1946 struct GNUNET_HashCode cache_key;
1947 char *authorization;
1948 char *credentials;
1949 char *basic_authorization;
1950 char *client_id_tmp;
1951 char *pass;
1952
1953 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
1954 strlen (OIDC_AUTHORIZATION_HEADER_KEY),
1955 &cache_key);
1956 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1957 ->header_param_map,
1958 &cache_key))
1959 return GNUNET_SYSERR;
1960 authorization =
1961 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1962 &cache_key);
1963
1964 // split header in "Basic" and [content]
1965 credentials = strtok (authorization, " ");
1966 if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1967 return GNUNET_SYSERR;
1968 credentials = strtok (NULL, " ");
1969 if (NULL == credentials)
1970 return GNUNET_SYSERR;
1971 GNUNET_STRINGS_base64_decode (credentials,
1972 strlen (credentials),
1973 (void **) &basic_authorization);
1974
1975 if (NULL == basic_authorization)
1976 return GNUNET_SYSERR;
1977 client_id_tmp = strtok (basic_authorization, ":");
1978 if (NULL == client_id_tmp)
1979 {
1980 GNUNET_free (basic_authorization);
1981 return GNUNET_SYSERR;
1982 }
1983 pass = strtok (NULL, ":");
1984 if (NULL == pass)
1985 {
1986 GNUNET_free (basic_authorization);
1987 return GNUNET_SYSERR;
1988 }
1989 *client_id = strdup (client_id_tmp);
1990 *client_secret = strdup (pass);
1991 GNUNET_free (basic_authorization);
1992 return GNUNET_OK;
1993}
1994
1995
1996static int
1997parse_credentials_post_body (struct RequestHandle *handle,
1998 char **client_id,
1999 char **client_secret)
2000{
2001 struct GNUNET_HashCode cache_key;
2002 char *client_id_tmp;
2003 char *pass;
2004
2005 GNUNET_CRYPTO_hash ("client_id",
2006 strlen ("client_id"),
2007 &cache_key);
2008 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
2009 ->url_param_map,
2010 &cache_key))
2011 return GNUNET_SYSERR;
2012 client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
2013 handle->rest_handle->url_param_map,
2014 &cache_key);
2015 if (NULL == client_id_tmp)
2016 return GNUNET_SYSERR;
2017 *client_id = strdup (client_id_tmp);
2018 GNUNET_CRYPTO_hash ("client_secret",
2019 strlen ("client_secret"),
2020 &cache_key);
2021 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
2022 ->url_param_map,
2023 &cache_key))
2024 {
2025 GNUNET_free (*client_id);
2026 *client_id = NULL;
2027 return GNUNET_SYSERR;
2028 }
2029 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
2030 &cache_key);
2031 if (NULL == pass)
2032 {
2033 GNUNET_free (*client_id);
2034 *client_id = NULL;
2035 return GNUNET_SYSERR;
2036 }
2037 *client_secret = strdup (pass);
2038 return GNUNET_OK;
2039}
2040
2041
2042static int
2043check_authorization (struct RequestHandle *handle,
2044 struct GNUNET_CRYPTO_PublicKey *cid)
2045{
2046 char *expected_pass;
2047 char *received_cid;
2048 char *received_cpw;
2049 char *pkce_cv;
2050
2051 if (GNUNET_OK == parse_credentials_basic_auth (handle,
2052 &received_cid,
2053 &received_cpw))
2054 {
2055 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2056 "Received client credentials in HTTP AuthZ header\n");
2057 }
2058 else if (GNUNET_OK == parse_credentials_post_body (handle,
2059 &received_cid,
2060 &received_cpw))
2061 {
2062 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2063 "Received client credentials in POST body\n");
2064 }
2065 else
2066 {
2067 /** Allow public clients with PKCE **/
2068 pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
2069 if (NULL == pkce_cv)
2070 {
2071 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
2072 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2073 return GNUNET_SYSERR;
2074 }
2075 handle->public_client = GNUNET_YES;
2076 GNUNET_free (pkce_cv);
2077 received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
2078 GNUNET_STRINGS_string_to_data (received_cid,
2079 strlen (received_cid),
2080 cid,
2081 sizeof(struct GNUNET_CRYPTO_PublicKey));
2082 GNUNET_free (received_cid);
2083 return GNUNET_OK;
2084
2085 }
2086
2087 // check client password
2088 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
2089 "reclaim-rest-plugin",
2090 "OIDC_CLIENT_HMAC_SECRET",
2091 &expected_pass))
2092 {
2093 if (0 != strcmp (expected_pass, received_cpw))
2094 {
2095 GNUNET_free (expected_pass);
2096 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
2097 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2098 GNUNET_free (received_cpw);
2099 GNUNET_free (received_cid);
2100 return GNUNET_SYSERR;
2101 }
2102 GNUNET_free (expected_pass);
2103 }
2104 else
2105 {
2106 GNUNET_free (received_cpw);
2107 GNUNET_free (received_cid);
2108 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
2109 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2110 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2111 return GNUNET_SYSERR;
2112 }
2113 // check client_id
2114 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
2115 handle->ego_entry = handle->ego_entry->next)
2116 {
2117 if (0 == strcmp (handle->ego_entry->keystring, received_cid))
2118 break;
2119 }
2120 if (NULL == handle->ego_entry)
2121 {
2122 GNUNET_free (received_cpw);
2123 GNUNET_free (received_cid);
2124 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
2125 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2126 return GNUNET_SYSERR;
2127 }
2128 GNUNET_STRINGS_string_to_data (received_cid,
2129 strlen (received_cid),
2130 cid,
2131 sizeof(struct GNUNET_CRYPTO_PublicKey));
2132
2133 GNUNET_free (received_cpw);
2134 GNUNET_free (received_cid);
2135 return GNUNET_OK;
2136}
2137
2138
2139const struct EgoEntry *
2140find_ego (struct RequestHandle *handle,
2141 struct GNUNET_CRYPTO_PublicKey *test_key)
2142{
2143 struct EgoEntry *ego_entry;
2144 struct GNUNET_CRYPTO_PublicKey pub_key;
2145
2146 for (ego_entry = ego_head; NULL != ego_entry;
2147 ego_entry = ego_entry->next)
2148 {
2149 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2150 if (0 == GNUNET_memcmp (&pub_key, test_key))
2151 return ego_entry;
2152 }
2153 return NULL;
2154}
2155
2156
2157/**
2158 * Responds to token url-encoded POST request
2159 *
2160 * @param con_handle the connection handle
2161 * @param url the url
2162 * @param cls the RequestHandle
2163 */
2164static void
2165token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2166 const char *url,
2167 void *cls)
2168{
2169 struct RequestHandle *handle = cls;
2170 const struct EgoEntry *ego_entry = NULL;
2171 struct GNUNET_TIME_Relative expiration_time;
2172 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2173 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2174 struct GNUNET_RECLAIM_Ticket ticket;
2175 struct GNUNET_CRYPTO_PublicKey cid;
2176 struct GNUNET_HashCode cache_key;
2177 struct MHD_Response *resp = NULL;
2178 char *grant_type = NULL;
2179 char *code = NULL;
2180 char *json_response = NULL;
2181 char *id_token = NULL;
2182 char *access_token = NULL;
2183 char *jwa = NULL;
2184 char *jwt_secret = NULL;
2185 char *nonce = NULL;
2186 char *code_verifier = NULL;
2187 json_t *oidc_jwk = NULL;
2188 char *oidc_jwk_path = NULL;
2189 char *oidc_directory = NULL;
2190 char *tmp_at = NULL;
2191
2192 /*
2193 * Check Authorization
2194 */
2195 if (GNUNET_SYSERR == check_authorization (handle, &cid))
2196 {
2197 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2198 "OIDC authorization for token endpoint failed\n");
2199 GNUNET_SCHEDULER_add_now (&do_error, handle);
2200 return;
2201 }
2202
2203 /*
2204 * Check parameter
2205 */
2206
2207 // TODO Do not allow multiple equal parameter names
2208 // REQUIRED grant_type
2209 GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY,
2210 strlen (OIDC_GRANT_TYPE_KEY),
2211 &cache_key);
2212 grant_type = get_url_parameter_copy (handle, OIDC_GRANT_TYPE_KEY);
2213 if (NULL == grant_type)
2214 {
2215 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2216 handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2217 handle->response_code = MHD_HTTP_BAD_REQUEST;
2218 GNUNET_SCHEDULER_add_now (&do_error, handle);
2219 return;
2220 }
2221
2222 // Check parameter grant_type == "authorization_code"
2223 if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2224 {
2225 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE);
2226 handle->response_code = MHD_HTTP_BAD_REQUEST;
2227 GNUNET_free (grant_type);
2228 GNUNET_SCHEDULER_add_now (&do_error, handle);
2229 return;
2230 }
2231 GNUNET_free (grant_type);
2232 // REQUIRED code
2233 code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
2234 if (NULL == code)
2235 {
2236 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2237 handle->edesc = GNUNET_strdup ("missing parameter code");
2238 handle->response_code = MHD_HTTP_BAD_REQUEST;
2239 GNUNET_SCHEDULER_add_now (&do_error, handle);
2240 return;
2241 }
2242 ego_entry = find_ego (handle, &cid);
2243 if (NULL == ego_entry)
2244 {
2245 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2246 handle->edesc = GNUNET_strdup ("Unknown client");
2247 handle->response_code = MHD_HTTP_BAD_REQUEST;
2248 GNUNET_free (code);
2249 GNUNET_SCHEDULER_add_now (&do_error, handle);
2250 return;
2251 }
2252
2253 // REQUIRED code verifier
2254 code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
2255 if (NULL == code_verifier)
2256 {
2257 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2258 "OAuth authorization request does not contain PKCE parameters!\n");
2259
2260 }
2261
2262 // decode code
2263 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2264 &cl, &pl, &nonce,
2265 OIDC_VERIFICATION_DEFAULT))
2266 {
2267 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2268 handle->edesc = GNUNET_strdup ("invalid code");
2269 handle->response_code = MHD_HTTP_BAD_REQUEST;
2270 GNUNET_free (code);
2271 if (NULL != code_verifier)
2272 GNUNET_free (code_verifier);
2273 GNUNET_SCHEDULER_add_now (&do_error, handle);
2274 return;
2275 }
2276 if (NULL != code_verifier)
2277 GNUNET_free (code_verifier);
2278
2279 // create jwt
2280 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
2281 "reclaim-rest-plugin",
2282 "expiration_time",
2283 &expiration_time))
2284 {
2285 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
2286 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2287 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2288 GNUNET_free (code);
2289 if (NULL != nonce)
2290 GNUNET_free (nonce);
2291 GNUNET_RECLAIM_attribute_list_destroy (cl);
2292 GNUNET_RECLAIM_presentation_list_destroy (pl);
2293 GNUNET_SCHEDULER_add_now (&do_error, handle);
2294 return;
2295 }
2296
2297 // Check if HMAC or RSA should be used
2298 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2299 "reclaim-rest-plugin",
2300 "oidc_json_web_algorithm",
2301 &jwa))
2302 {
2303 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2304 "Could not read OIDC JSON Web Algorithm config attribute."
2305 "Defaulting to RS256.");
2306 jwa = JWT_ALG_VALUE_RSA;
2307 }
2308
2309 if ( ! strcmp (jwa, JWT_ALG_VALUE_RSA))
2310 {
2311 // Replace for now
2312 oidc_jwk_path = get_oidc_jwk_path (cls);
2313 oidc_jwk = read_jwk_from_file (oidc_jwk_path);
2314
2315 // Check if secret JWK exists
2316 if (! oidc_jwk)
2317 {
2318 // Generate and save a new key
2319 oidc_jwk = generate_jwk ();
2320 oidc_directory = get_oidc_dir_path (cls);
2321
2322 // Create new oidc directory
2323 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2324 {
2325 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2326 ("Failed to create directory `%s' for storing oidc data\n"),
2327 oidc_directory);
2328 }
2329 else
2330 {
2331 write_jwk_to_file (oidc_jwk_path, oidc_jwk);
2332 }
2333 }
2334
2335 // Generate oidc token
2336 id_token = OIDC_generate_id_token_rsa (&ticket.audience,
2337 &ticket.identity,
2338 cl,
2339 pl,
2340 &expiration_time,
2341 (NULL != nonce) ? nonce : NULL,
2342 oidc_jwk);
2343 }
2344 else if ( ! strcmp (jwa, JWT_ALG_VALUE_HMAC))
2345 {
2346 // TODO OPTIONAL acr,amr,azp
2347 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2348 "reclaim-rest-plugin",
2349 "jwt_secret",
2350 &jwt_secret))
2351 {
2352 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2353 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2354 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2355 GNUNET_free (code);
2356 GNUNET_RECLAIM_attribute_list_destroy (cl);
2357 GNUNET_RECLAIM_presentation_list_destroy (pl);
2358 if (NULL != nonce)
2359 GNUNET_free (nonce);
2360 GNUNET_SCHEDULER_add_now (&do_error, handle);
2361 return;
2362 }
2363
2364 id_token = OIDC_generate_id_token_hmac (&ticket.audience,
2365 &ticket.identity,
2366 cl,
2367 pl,
2368 &expiration_time,
2369 (NULL != nonce) ? nonce : NULL,
2370 jwt_secret);
2371
2372 GNUNET_free (jwt_secret);
2373 }
2374 else
2375 {
2376 // TODO: OPTION NOT FOUND ERROR
2377 }
2378
2379 if (NULL != nonce)
2380 GNUNET_free (nonce);
2381 access_token = OIDC_access_token_new (&ticket);
2382 /**
2383 * Store mapping from access token to code so we can later
2384 * fall back on the provided attributes in userinfo one time.
2385 */
2386 GNUNET_CRYPTO_hash (access_token,
2387 strlen (access_token),
2388 &cache_key);
2389 /**
2390 * Note to future self: This cache has the following purpose:
2391 * Some OIDC plugins call the userendpoint right after receiving an
2392 * ID token and access token. There are reasons why this would make sense.
2393 * Others not so much.
2394 * In any case, in order to smoothen out the user experience upon login
2395 * (authorization), we speculatively cache the next
2396 * userinfo response in case the actual resolution through reclaim/GNS
2397 * takes too long.
2398 */
2399 tmp_at = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2400 &cache_key);
2401 GNUNET_CONTAINER_multihashmap_put (oidc_code_cache,
2402 &cache_key,
2403 code,
2404 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
2405 /* If there was a previous code in there, free the old value */
2406 if (NULL != tmp_at)
2407 {
2408 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2409 "OIDC access token already issued. Cleanup.\n");
2410 GNUNET_free (tmp_at);
2411 }
2412
2413 OIDC_build_token_response (access_token,
2414 id_token,
2415 &expiration_time,
2416 &json_response);
2417
2418 resp = GNUNET_REST_create_response (json_response);
2419 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2420 "Cache-Control",
2421 "no-store"));
2422 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2423 "Pragma", "no-cache"));
2424 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2425 "Content-Type",
2426 "application/json"));
2427 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2428 GNUNET_RECLAIM_attribute_list_destroy (cl);
2429 GNUNET_RECLAIM_presentation_list_destroy (pl);
2430 GNUNET_free (access_token);
2431 GNUNET_free (json_response);
2432 GNUNET_free (id_token);
2433 cleanup_handle (handle);
2434}
2435
2436
2437/**
2438 * Collects claims and stores them in handle
2439 */
2440static void
2441consume_ticket (void *cls,
2442 const struct GNUNET_CRYPTO_PublicKey *identity,
2443 const struct GNUNET_RECLAIM_Attribute *attr,
2444 const struct GNUNET_RECLAIM_Presentation *presentation)
2445{
2446 struct RequestHandle *handle = cls;
2447 struct GNUNET_RECLAIM_AttributeListEntry *ale;
2448 struct GNUNET_RECLAIM_PresentationListEntry *atle;
2449 struct MHD_Response *resp;
2450 struct GNUNET_HashCode cache_key;
2451 char *result_str;
2452 char *cached_code;
2453
2454 if (NULL != handle->consume_timeout_op)
2455 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2456 handle->consume_timeout_op = NULL;
2457 handle->idp_op = NULL;
2458
2459 /**
2460 * We received a reply. In any case clear the cache.
2461 */
2462 GNUNET_CRYPTO_hash (handle->access_token,
2463 strlen (handle->access_token),
2464 &cache_key);
2465 cached_code = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2466 &cache_key);
2467 if (NULL != cached_code)
2468 {
2469 GNUNET_assert (GNUNET_YES ==
2470 GNUNET_CONTAINER_multihashmap_remove (oidc_code_cache,
2471 &cache_key,
2472 cached_code));
2473 GNUNET_free (cached_code);
2474 }
2475
2476
2477 if (NULL == identity)
2478 {
2479 result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2480 handle->attr_userinfo_list,
2481 handle->presentations);
2482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2483 resp = GNUNET_REST_create_response (result_str);
2484 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2485 GNUNET_free (result_str);
2486 cleanup_handle (handle);
2487 return;
2488 }
2489 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
2490 ale->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
2491 &attr->credential,
2492 attr->type,
2493 attr->data,
2494 attr->data_size);
2495 ale->attribute->id = attr->id;
2496 ale->attribute->flag = attr->flag;
2497 ale->attribute->credential = attr->credential;
2498 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2499 handle->attr_userinfo_list->list_tail,
2500 ale);
2501 if (NULL == presentation)
2502 return;
2503 for (atle = handle->presentations->list_head;
2504 NULL != atle; atle = atle->next)
2505 {
2506 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (
2507 &atle->presentation->credential_id,
2508 &presentation->credential_id))
2509 continue;
2510 break; /** already in list **/
2511 }
2512 if (NULL == atle)
2513 {
2514 /** Credential matches for attribute, add **/
2515 atle = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
2516 atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2517 presentation->data,
2518 presentation->
2519 data_size);
2520 atle->presentation->credential_id = presentation->credential_id;
2521 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2522 handle->presentations->list_tail,
2523 atle);
2524 }
2525}
2526
2527
2528static void
2529consume_fail (void *cls)
2530{
2531 struct RequestHandle *handle = cls;
2532 struct GNUNET_HashCode cache_key;
2533 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2534 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2535 struct GNUNET_RECLAIM_Ticket ticket;
2536 struct MHD_Response *resp;
2537 char *nonce;
2538 char *cached_code;
2539 char *result_str;
2540
2541
2542 handle->consume_timeout_op = NULL;
2543 if (NULL != handle->idp_op)
2544 GNUNET_RECLAIM_cancel (handle->idp_op);
2545 handle->idp_op = NULL;
2546
2547 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2548 "Ticket consumptioned timed out. Using cache...\n");
2549 GNUNET_CRYPTO_hash (handle->access_token,
2550 strlen (handle->access_token),
2551 &cache_key);
2552 cached_code = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2553 &cache_key);
2554 if (NULL == cached_code)
2555 {
2556 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2557 handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2558 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2559 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2560 return;
2561 }
2562 /**
2563 * Remove the cached item
2564 */
2565 GNUNET_assert (GNUNET_YES ==
2566 GNUNET_CONTAINER_multihashmap_remove (oidc_code_cache,
2567 &cache_key,
2568 cached_code));
2569
2570 // decode code
2571 if (GNUNET_OK != OIDC_parse_authz_code (&handle->ticket.audience,
2572 cached_code, NULL, &ticket,
2573 &cl, &pl, &nonce,
2574 OIDC_VERIFICATION_NO_CODE_VERIFIER))
2575 {
2576 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2577 handle->edesc = GNUNET_strdup ("invalid code");
2578 handle->response_code = MHD_HTTP_BAD_REQUEST;
2579 GNUNET_free (cached_code);
2580 if (NULL != nonce)
2581 GNUNET_free (nonce);
2582 GNUNET_SCHEDULER_add_now (&do_error, handle);
2583 return;
2584 }
2585
2586 GNUNET_free (cached_code);
2587
2588 result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2589 cl,
2590 pl);
2591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2592 resp = GNUNET_REST_create_response (result_str);
2593 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2594 GNUNET_free (result_str);
2595 GNUNET_free (nonce);
2596 GNUNET_RECLAIM_attribute_list_destroy (cl);
2597 GNUNET_RECLAIM_presentation_list_destroy (pl);
2598 cleanup_handle (handle);
2599}
2600
2601
2602/**
2603 * Responds to userinfo GET and url-encoded POST request
2604 *
2605 * @param con_handle the connection handle
2606 * @param url the url
2607 * @param cls the RequestHandle
2608 */
2609static void
2610userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2611 const char *url,
2612 void *cls)
2613{
2614 // TODO expiration time
2615 struct RequestHandle *handle = cls;
2616 struct GNUNET_RECLAIM_Ticket *ticket;
2617 char delimiter[] = " ";
2618 struct GNUNET_HashCode cache_key;
2619 char *authorization;
2620 char *authorization_type;
2621 char *authorization_access_token;
2622 const struct EgoEntry *aud_ego;
2623 const struct GNUNET_CRYPTO_PrivateKey *privkey;
2624
2625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2626 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
2627 strlen (OIDC_AUTHORIZATION_HEADER_KEY),
2628 &cache_key);
2629 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
2630 ->header_param_map,
2631 &cache_key))
2632 {
2633 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2634 handle->edesc = GNUNET_strdup ("No Access Token");
2635 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2636 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2637 return;
2638 }
2639 authorization =
2640 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2641 &cache_key);
2642
2643 // split header in "Bearer" and access_token
2644 authorization = GNUNET_strdup (authorization);
2645 authorization_type = strtok (authorization, delimiter);
2646 if ((NULL == authorization_type) ||
2647 (0 != strcmp ("Bearer", authorization_type)))
2648 {
2649 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2650 handle->edesc = GNUNET_strdup ("No Access Token");
2651 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2652 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2653 GNUNET_free (authorization);
2654 return;
2655 }
2656 authorization_access_token = strtok (NULL, delimiter);
2657 if (NULL == authorization_access_token)
2658 {
2659 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2660 handle->edesc = GNUNET_strdup ("Access token missing");
2661 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2662 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2663 GNUNET_free (authorization);
2664 return;
2665 }
2666
2667 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2668 &ticket))
2669 {
2670 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2671 handle->edesc = GNUNET_strdup ("The access token is invalid");
2672 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2673 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2674 GNUNET_free (authorization);
2675 return;
2676
2677 }
2678 GNUNET_assert (NULL != ticket);
2679 handle->ticket = *ticket;
2680 GNUNET_free (ticket);
2681 aud_ego = find_ego (handle, &handle->ticket.audience);
2682 if (NULL == aud_ego)
2683 {
2684 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2685 handle->edesc = GNUNET_strdup ("The access token expired");
2686 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2687 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2688 GNUNET_free (authorization);
2689 return;
2690 }
2691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2692 privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2693 handle->attr_userinfo_list =
2694 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
2695 handle->presentations =
2696 GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
2697
2698 /* If the consume takes too long, we use values from the cache */
2699 handle->access_token = GNUNET_strdup (authorization_access_token);
2700 handle->consume_timeout_op = GNUNET_SCHEDULER_add_delayed (consume_timeout,
2701 &consume_fail,
2702 handle);
2703 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2704 privkey,
2705 &handle->ticket,
2706 &consume_ticket,
2707 handle);
2708 GNUNET_free (authorization);
2709}
2710
2711/**
2712 * Responds to /jwks.json
2713 *
2714 * @param con_handle the connection handle
2715 * @param url the url
2716 * @param cls the RequestHandle
2717 */
2718static void
2719jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2720 const char *url,
2721 void *cls)
2722{
2723 char *oidc_directory;
2724 char *oidc_jwk_path;
2725 char *oidc_jwk_pub_str;
2726 json_t *oidc_jwk;
2727 struct MHD_Response *resp;
2728 struct RequestHandle *handle = cls;
2729
2730 oidc_jwk_path = get_oidc_jwk_path (cls);
2731 oidc_jwk = read_jwk_from_file (oidc_jwk_path);
2732
2733 // Check if secret JWK exists
2734 if (! oidc_jwk)
2735 {
2736 // Generate and save a new key
2737 oidc_jwk = generate_jwk ();
2738 oidc_directory = get_oidc_dir_path (cls);
2739
2740 // Create new oidc directory
2741 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2742 {
2743 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2744 ("Failed to create directory `%s' for storing oidc data\n"),
2745 oidc_directory);
2746 }
2747 else
2748 {
2749 write_jwk_to_file (oidc_jwk_path, oidc_jwk);
2750 }
2751 }
2752
2753 // Convert secret JWK to public JWK
2754 jose_jwk_pub (NULL, oidc_jwk);
2755
2756 // Encode JWK as string and return to API endpoint
2757 oidc_jwk_pub_str = json_dumps (oidc_jwk, JSON_INDENT (1));
2758 resp = GNUNET_REST_create_response (oidc_jwk_pub_str);
2759 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2760 json_decref (oidc_jwk);
2761 GNUNET_free (oidc_jwk_pub_str);
2762 GNUNET_free (oidc_jwk_pub_str);
2763 cleanup_handle (handle);
2764}
2765
2766/**
2767 * If listing is enabled, prints information about the egos.
2768 *
2769 * This function is initially called for all egos and then again
2770 * whenever a ego's identifier changes or if it is deleted. At the
2771 * end of the initial pass over all egos, the function is once called
2772 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
2773 * be invoked in the future or that there was an error.
2774 *
2775 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', this
2776 * function is only called ONCE, and 'NULL' being passed in 'ego' does
2777 * indicate an error (for example because name is taken or no default value is
2778 * known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the
2779 * value WILL be passed to a subsequent call to the identity callback of
2780 * 'GNUNET_IDENTITY_connect' (if that one was not NULL).
2781 *
2782 * When an identity is renamed, this function is called with the
2783 * (known) ego but the NEW identifier.
2784 *
2785 * When an identity is deleted, this function is called with the
2786 * (known) ego and "NULL" for the 'identifier'. In this case,
2787 * the 'ego' is henceforth invalid (and the 'ctx' should also be
2788 * cleaned up).
2789 *
2790 * @param cls closure
2791 * @param ego ego handle
2792 * @param ctx context for application to store data for this ego
2793 * (during the lifetime of this process, initially NULL)
2794 * @param identifier identifier assigned by the user for this ego,
2795 * NULL if the user just deleted the ego and it
2796 * must thus no longer be used
2797 */
2798static void
2799list_ego (void *cls,
2800 struct GNUNET_IDENTITY_Ego *ego,
2801 void **ctx,
2802 const char *identifier)
2803{
2804 struct EgoEntry *ego_entry;
2805 struct GNUNET_CRYPTO_PublicKey pk;
2806
2807 if (NULL == ego)
2808 {
2809 state = ID_REST_STATE_POST_INIT;
2810 return;
2811 }
2812 if (ID_REST_STATE_INIT == state)
2813
2814 {
2815 ego_entry = GNUNET_new (struct EgoEntry);
2816 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
2817 ego_entry->keystring = GNUNET_CRYPTO_public_key_to_string (&pk);
2818 ego_entry->ego = ego;
2819 ego_entry->identifier = GNUNET_strdup (identifier);
2820 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
2821 ego_tail,
2822 ego_entry);
2823 return;
2824 }
2825 /* Ego renamed or added */
2826 if (identifier != NULL)
2827 {
2828 for (ego_entry = ego_head; NULL != ego_entry;
2829 ego_entry = ego_entry->next)
2830 {
2831 if (ego_entry->ego == ego)
2832 {
2833 /* Rename */
2834 GNUNET_free (ego_entry->identifier);
2835 ego_entry->identifier = GNUNET_strdup (identifier);
2836 break;
2837 }
2838 }
2839 if (NULL == ego_entry)
2840 {
2841 /* Add */
2842 ego_entry = GNUNET_new (struct EgoEntry);
2843 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
2844 ego_entry->keystring = GNUNET_CRYPTO_public_key_to_string (&pk);
2845 ego_entry->ego = ego;
2846 ego_entry->identifier = GNUNET_strdup (identifier);
2847 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
2848 ego_tail,
2849 ego_entry);
2850 }
2851 }
2852 else
2853 {
2854 /* Delete */
2855 for (ego_entry = ego_head; NULL != ego_entry;
2856 ego_entry = ego_entry->next)
2857 {
2858 if (ego_entry->ego == ego)
2859 break;
2860 }
2861 if (NULL == ego_entry)
2862 return; /* Not found */
2863
2864 GNUNET_CONTAINER_DLL_remove (ego_head,
2865 ego_tail,
2866 ego_entry);
2867 GNUNET_free (ego_entry->identifier);
2868 GNUNET_free (ego_entry->keystring);
2869 GNUNET_free (ego_entry);
2870 return;
2871 }
2872}
2873
2874
2875static void
2876oidc_config_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2877 const char *url,
2878 void *cls)
2879{
2880 json_t *oidc_config;
2881 json_t *auth_methods;
2882 json_t *sig_algs;
2883 json_t *scopes;
2884 json_t *response_types;
2885 json_t *sub_types;
2886 json_t *claim_types;
2887 char *oidc_config_str;
2888 struct MHD_Response *resp;
2889 struct RequestHandle *handle = cls;
2890
2891 oidc_config = json_object ();
2892 // FIXME get from config?
2893 json_object_set_new (oidc_config,
2894 "issuer", json_string ("http://localhost:7776"));
2895 json_object_set_new (oidc_config,
2896 "authorization_endpoint",
2897 json_string ("https://api.reclaim/openid/authorize"));
2898 json_object_set_new (oidc_config,
2899 "token_endpoint",
2900 json_string ("http://localhost:7776/openid/token"));
2901 auth_methods = json_array ();
2902 json_array_append_new (auth_methods,
2903 json_string ("client_secret_basic"));
2904 json_array_append_new (auth_methods,
2905 json_string ("client_secret_post"));
2906 json_object_set_new (oidc_config,
2907 "token_endpoint_auth_methods_supported",
2908 auth_methods);
2909 sig_algs = json_array ();
2910 json_array_append_new (sig_algs,
2911 json_string ("HS512"));
2912 json_array_append_new (sig_algs,
2913 json_string ("RS256"));
2914 json_object_set_new (oidc_config,
2915 "id_token_signing_alg_values_supported",
2916 sig_algs);
2917 json_object_set_new (oidc_config,
2918 "jwks_uri",
2919 json_string ("http://localhost:7776/jwks.json"));
2920 json_object_set_new (oidc_config,
2921 "userinfo_endpoint",
2922 json_string ("http://localhost:7776/openid/userinfo"));
2923 scopes = json_array ();
2924 json_array_append_new (scopes,
2925 json_string ("openid"));
2926 json_array_append_new (scopes,
2927 json_string ("profile"));
2928 json_array_append_new (scopes,
2929 json_string ("email"));
2930 json_array_append_new (scopes,
2931 json_string ("address"));
2932 json_array_append_new (scopes,
2933 json_string ("phone"));
2934 json_object_set_new (oidc_config,
2935 "scopes_supported",
2936 scopes);
2937 response_types = json_array ();
2938 json_array_append_new (response_types,
2939 json_string ("code"));
2940 json_object_set_new (oidc_config,
2941 "response_types_supported",
2942 response_types);
2943 sub_types = json_array ();
2944 json_array_append_new (sub_types,
2945 json_string ("public")); /* no pairwise support */
2946 json_object_set_new (oidc_config,
2947 "subject_types_supported",
2948 sub_types);
2949 claim_types = json_array ();
2950 json_array_append_new (claim_types,
2951 json_string ("normal"));
2952 json_array_append_new (claim_types,
2953 json_string ("aggregated"));
2954 json_object_set_new (oidc_config,
2955 "claim_types_supported",
2956 claim_types);
2957 json_object_set_new (oidc_config,
2958 "claims_parameter_supported",
2959 json_boolean (1));
2960 oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2961 resp = GNUNET_REST_create_response (oidc_config_str);
2962 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2963 json_decref (oidc_config);
2964 GNUNET_free (oidc_config_str);
2965 cleanup_handle (handle);
2966}
2967
2968
2969/**
2970 * Respond to OPTIONS request
2971 *
2972 * @param con_handle the connection handle
2973 * @param url the url
2974 * @param cls the RequestHandle
2975 */
2976static void
2977oidc_config_cors (struct GNUNET_REST_RequestHandle *con_handle,
2978 const char *url,
2979 void *cls)
2980{
2981 struct MHD_Response *resp;
2982 struct RequestHandle *handle = cls;
2983
2984 // For now, independent of path return all options
2985 resp = GNUNET_REST_create_response (NULL);
2986 GNUNET_assert (MHD_NO !=
2987 MHD_add_response_header (resp,
2988 "Access-Control-Allow-Methods",
2989 allow_methods));
2990 GNUNET_assert (MHD_NO !=
2991 MHD_add_response_header (resp,
2992 "Access-Control-Allow-Origin",
2993 "*"));
2994 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2995 cleanup_handle (handle);
2996 return;
2997}
2998
2999
3000static enum GNUNET_GenericReturnValue
3001rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
3002 GNUNET_REST_ResultProcessor proc,
3003 void *proc_cls)
3004{
3005 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3006 struct GNUNET_REST_RequestHandlerError err;
3007 static const struct GNUNET_REST_RequestHandler handlers[] =
3008 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3009 { MHD_HTTP_METHOD_POST,
3010 GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, // url-encoded
3011 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3012 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3013 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3014 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3015 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3016 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3017 &oidc_config_endpoint },
3018 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3019 &oidc_config_cors },
3020 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3021 GNUNET_REST_HANDLER_END };
3022
3023 handle->oidc = GNUNET_new (struct OIDC_Variables);
3024 if (NULL == OIDC_cookie_jar_map)
3025 OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
3026 GNUNET_NO);
3027 if (NULL == oidc_code_cache)
3028 oidc_code_cache = GNUNET_CONTAINER_multihashmap_create (10,
3029 GNUNET_NO);
3030
3031 handle->response_code = 0;
3032 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
3033 handle->proc_cls = proc_cls;
3034 handle->proc = proc;
3035 handle->rest_handle = rest_handle;
3036 handle->url = GNUNET_strdup (rest_handle->url);
3037 handle->timeout_task =
3038 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
3039 GNUNET_CONTAINER_DLL_insert (requests_head,
3040 requests_tail,
3041 handle);
3042 if (handle->url[strlen (handle->url) - 1] == '/')
3043 handle->url[strlen (handle->url) - 1] = '\0';
3044 if (GNUNET_NO ==
3045 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3046 return GNUNET_NO;
3047
3048 return GNUNET_YES;
3049}
3050
3051
3052/**
3053 * Entry point for the plugin.
3054 *
3055 * @param cls Config info
3056 * @return NULL on error, otherwise the plugin context
3057 */
3058void *
3059libgnunet_plugin_rest_openid_connect_init (void *cls)
3060{
3061 static struct Plugin plugin;
3062 struct GNUNET_REST_Plugin *api;
3063
3064 cfg = cls;
3065 if (NULL != plugin.cfg)
3066 return NULL; /* can only initialize once! */
3067 memset (&plugin, 0, sizeof(struct Plugin));
3068 plugin.cfg = cfg;
3069 api = GNUNET_new (struct GNUNET_REST_Plugin);
3070 api->cls = &plugin;
3071 api->name = GNUNET_REST_API_NS_OIDC;
3072 api->process_request = &rest_identity_process_request;
3073 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
3074 gns_handle = GNUNET_GNS_connect (cfg);
3075 idp = GNUNET_RECLAIM_connect (cfg);
3076 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
3077 "reclaim-rest-plugin",
3078 "OIDC_USERINFO_CONSUME_TIMEOUT",
3079 &consume_timeout))
3080 {
3081 consume_timeout = CONSUME_TIMEOUT;
3082 }
3083
3084
3085 state = ID_REST_STATE_INIT;
3086 GNUNET_asprintf (&allow_methods,
3087 "%s, %s, %s, %s, %s",
3088 MHD_HTTP_METHOD_GET,
3089 MHD_HTTP_METHOD_POST,
3090 MHD_HTTP_METHOD_PUT,
3091 MHD_HTTP_METHOD_DELETE,
3092 MHD_HTTP_METHOD_OPTIONS);
3093
3094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3095 _ ("OpenID Connect REST API initialized\n"));
3096 return api;
3097}
3098
3099
3100static int
3101cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
3102{
3103 GNUNET_free (value);
3104 return GNUNET_YES;
3105}
3106
3107
3108/**
3109 * Exit point from the plugin.
3110 *
3111 * @param cls the plugin context (as returned by "init")
3112 * @return always NULL
3113 */
3114void *
3115libgnunet_plugin_rest_openid_connect_done (void *cls)
3116{
3117 struct GNUNET_REST_Plugin *api = cls;
3118 struct Plugin *plugin = api->cls;
3119 struct EgoEntry *ego_entry;
3120
3121 plugin->cfg = NULL;
3122 while (NULL != requests_head)
3123 cleanup_handle (requests_head);
3124 if (NULL != OIDC_cookie_jar_map)
3125 {
3126 GNUNET_CONTAINER_multihashmap_iterate (OIDC_cookie_jar_map,
3127 &cleanup_hashmap,
3128 NULL);
3129 GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
3130 }
3131 if (NULL != oidc_code_cache)
3132 {
3133 GNUNET_CONTAINER_multihashmap_iterate (oidc_code_cache,
3134 &cleanup_hashmap,
3135 NULL);
3136 GNUNET_CONTAINER_multihashmap_destroy (oidc_code_cache);
3137 }
3138
3139 GNUNET_free (allow_methods);
3140 if (NULL != gns_handle)
3141 GNUNET_GNS_disconnect (gns_handle);
3142 if (NULL != identity_handle)
3143 GNUNET_IDENTITY_disconnect (identity_handle);
3144 if (NULL != idp)
3145 GNUNET_RECLAIM_disconnect (idp);
3146 while (NULL != (ego_entry = ego_head))
3147 {
3148 GNUNET_CONTAINER_DLL_remove (ego_head,
3149 ego_tail,
3150 ego_entry);
3151 GNUNET_free (ego_entry->identifier);
3152 GNUNET_free (ego_entry->keystring);
3153 GNUNET_free (ego_entry);
3154 }
3155 GNUNET_free (api);
3156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3157 "OpenID Connect REST plugin is finished\n");
3158 return NULL;
3159}
3160
3161
3162/* end of plugin_rest_openid_connect.c */
diff --git a/src/reclaim/plugin_rest_pabc.c b/src/reclaim/plugin_rest_pabc.c
deleted file mode 100644
index 4b7d21df3..000000000
--- a/src/reclaim/plugin_rest_pabc.c
+++ /dev/null
@@ -1,667 +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/plugin_rest_pabc.c
23 * @brief GNUnet pabc REST plugin
24 *
25 */
26#include "platform.h"
27#include "microhttpd.h"
28#include <inttypes.h>
29#include <jansson.h>
30#include <pabc/pabc.h>
31#include "gnunet_reclaim_lib.h"
32#include "gnunet_reclaim_service.h"
33#include "gnunet_rest_lib.h"
34#include "gnunet_rest_plugin.h"
35#include "gnunet_signatures.h"
36#include "pabc_helper.h"
37
38/**
39 * REST root namespace
40 */
41#define GNUNET_REST_API_NS_PABC "/pabc"
42
43/**
44 * Credential request endpoint
45 */
46#define GNUNET_REST_API_NS_PABC_CR "/pabc/cr"
47
48/**
49 * The configuration handle
50 */
51const struct GNUNET_CONFIGURATION_Handle *cfg;
52
53/**
54 * HTTP methods allows for this plugin
55 */
56static char *allow_methods;
57
58/**
59 * @brief struct returned by the initialization function of the plugin
60 */
61struct Plugin
62{
63 const struct GNUNET_CONFIGURATION_Handle *cfg;
64};
65
66
67struct RequestHandle
68{
69 /**
70 * DLL
71 */
72 struct RequestHandle *next;
73
74 /**
75 * DLL
76 */
77 struct RequestHandle *prev;
78
79 /**
80 * Rest connection
81 */
82 struct GNUNET_REST_RequestHandle *rest_handle;
83
84 /**
85 * Desired timeout for the lookup (default is no timeout).
86 */
87 struct GNUNET_TIME_Relative timeout;
88
89 /**
90 * ID of a task associated with the resolution process.
91 */
92 struct GNUNET_SCHEDULER_Task *timeout_task;
93
94 /**
95 * The plugin result processor
96 */
97 GNUNET_REST_ResultProcessor proc;
98
99 /**
100 * The closure of the result processor
101 */
102 void *proc_cls;
103
104 /**
105 * The url
106 */
107 char *url;
108
109 /**
110 * Error response message
111 */
112 char *emsg;
113
114 /**
115 * Response code
116 */
117 int response_code;
118
119 /**
120 * Response object
121 */
122 json_t *resp_object;
123};
124
125/**
126 * DLL
127 */
128static struct RequestHandle *requests_head;
129
130/**
131 * DLL
132 */
133static struct RequestHandle *requests_tail;
134
135
136/**
137 * Cleanup lookup handle
138 * @param handle Handle to clean up
139 */
140static void
141cleanup_handle (void *cls)
142{
143 struct RequestHandle *handle = cls;
144
145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
146 if (NULL != handle->resp_object)
147 json_decref (handle->resp_object);
148 if (NULL != handle->timeout_task)
149 GNUNET_SCHEDULER_cancel (handle->timeout_task);
150 if (NULL != handle->url)
151 GNUNET_free (handle->url);
152 if (NULL != handle->emsg)
153 GNUNET_free (handle->emsg);
154 GNUNET_CONTAINER_DLL_remove (requests_head,
155 requests_tail,
156 handle);
157 GNUNET_free (handle);
158}
159
160
161/**
162 * Task run on error, sends error message. Cleans up everything.
163 *
164 * @param cls the `struct RequestHandle`
165 */
166static void
167do_error (void *cls)
168{
169 struct RequestHandle *handle = cls;
170 struct MHD_Response *resp;
171 char *json_error;
172
173 GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", handle->emsg);
174 if (0 == handle->response_code)
175 {
176 handle->response_code = MHD_HTTP_BAD_REQUEST;
177 }
178 resp = GNUNET_REST_create_response (json_error);
179 MHD_add_response_header (resp, "Content-Type", "application/json");
180 handle->proc (handle->proc_cls, resp, handle->response_code);
181 cleanup_handle (handle);
182 GNUNET_free (json_error);
183}
184
185
186/**
187 * Task run on timeout, sends error message. Cleans up everything.
188 *
189 * @param cls the `struct RequestHandle`
190 */
191static void
192do_timeout (void *cls)
193{
194 struct RequestHandle *handle = cls;
195
196 handle->timeout_task = NULL;
197 do_error (handle);
198}
199
200
201static void
202return_response (void *cls)
203{
204 char *result_str;
205 struct RequestHandle *handle = cls;
206 struct MHD_Response *resp;
207
208 result_str = json_dumps (handle->resp_object, 0);
209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
210 resp = GNUNET_REST_create_response (result_str);
211 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
212 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
213 GNUNET_free (result_str);
214 cleanup_handle (handle);
215}
216
217
218static enum pabc_status
219set_attributes_from_idtoken (const struct pabc_context *ctx,
220 const struct pabc_public_parameters *pp,
221 struct pabc_user_context *usr_ctx,
222 const char *id_token)
223{
224 json_t *payload_json;
225 json_t *value;
226 json_error_t json_err;
227 const char *key;
228 const char *jwt_body;
229 char *decoded_jwt;
230 char delim[] = ".";
231 char *jwt_string;
232 const char *pabc_key;
233 enum pabc_status status;
234
235 // FIXME parse JWT
236 jwt_string = GNUNET_strndup (id_token, strlen (id_token));
237 jwt_body = strtok (jwt_string, delim);
238 jwt_body = strtok (NULL, delim);
239 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
240 (void **) &decoded_jwt);
241 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded ID Token: %s\n", decoded_jwt);
242 payload_json = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err);
243 GNUNET_free (decoded_jwt);
244
245 json_object_foreach (payload_json, key, value)
246 {
247 pabc_key = key;
248 if (0 == strcmp ("iss", key))
249 pabc_key = "issuer"; // rename
250 if (0 == strcmp ("sub", key))
251 pabc_key = "subject"; // rename
252 if (0 == strcmp ("jti", key))
253 continue;
254 if (0 == strcmp ("exp", key))
255 pabc_key = "expiration"; // rename
256 if (0 == strcmp ("iat", key))
257 continue;
258 if (0 == strcmp ("nbf", key))
259 continue;
260 if (0 == strcmp ("aud", key))
261 continue;
262 char *tmp_val;
263 if (json_is_string (value))
264 tmp_val = GNUNET_strdup (json_string_value (value));
265 else
266 tmp_val = json_dumps (value, JSON_ENCODE_ANY);
267 if (NULL == tmp_val)
268 {
269 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
270 "Unable to encode JSON value for `%s'\n", key);
271 continue;
272 }
273 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
274 "Setting `%s' to `%s'\n", key, tmp_val);
275 status = pabc_set_attribute_value_by_name (ctx, pp, usr_ctx,
276 pabc_key,
277 tmp_val);
278 GNUNET_free (tmp_val);
279 if (PABC_OK != status)
280 {
281 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
282 "Failed to set attribute `%s'.\n", key);
283 }
284 }
285 GNUNET_free (jwt_string);
286 return PABC_OK;
287}
288
289
290static enum GNUNET_GenericReturnValue
291setup_new_user_context (struct pabc_context *ctx,
292 struct pabc_public_parameters *pp,
293 struct pabc_user_context **usr_ctx)
294{
295 if (PABC_OK != pabc_new_user_context (ctx, pp, usr_ctx))
296 return GNUNET_SYSERR;
297
298 if (PABC_OK != pabc_populate_user_context (ctx, *usr_ctx))
299 {
300 pabc_free_user_context (ctx, pp, usr_ctx);
301 return GNUNET_SYSERR;
302 }
303 return GNUNET_OK;
304}
305
306
307static void
308cr_cont (struct GNUNET_REST_RequestHandle *con_handle,
309 const char *url,
310 void *cls)
311{
312 struct RequestHandle *handle = cls;
313 char term_data[handle->rest_handle->data_size + 1];
314 char *response_str;
315 json_t *data_json;
316 json_t *nonce_json;
317 json_t *pp_json;
318 json_t *idtoken_json;
319 json_t *iss_json;
320 json_t *identity_json;
321 json_error_t err;
322 struct pabc_public_parameters *pp = NULL;
323 struct pabc_context *ctx = NULL;
324 struct pabc_user_context *usr_ctx = NULL;
325 struct pabc_credential_request *cr = NULL;
326 struct pabc_nonce *nonce = NULL;
327 enum pabc_status status;
328
329
330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
331 "Credential request...\n");
332
333 if (0 >= handle->rest_handle->data_size)
334 {
335 GNUNET_SCHEDULER_add_now (&do_error, handle);
336 return;
337 }
338
339 term_data[handle->rest_handle->data_size] = '\0';
340 GNUNET_memcpy (term_data,
341 handle->rest_handle->data,
342 handle->rest_handle->data_size);
343 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
344 if (NULL == data_json)
345 {
346 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
347 "Unable to parse %s\n", term_data);
348 GNUNET_SCHEDULER_add_now (&do_error, handle);
349 return;
350 }
351 if (! json_is_object (data_json))
352 {
353 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
354 "Unable to parse %s\n", term_data);
355 json_decref (data_json);
356 GNUNET_SCHEDULER_add_now (&do_error, handle);
357 return;
358 }
359
360 nonce_json = json_object_get (data_json, "nonce");
361 if (NULL == nonce_json)
362 {
363 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
364 "Unable to parse nonce\n");
365 json_decref (data_json);
366 GNUNET_SCHEDULER_add_now (&do_error, handle);
367 return;
368 }
369 iss_json = json_object_get (data_json, "issuer");
370 if (NULL == iss_json)
371 {
372 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
373 "Unable to parse issuer\n");
374 json_decref (data_json);
375 GNUNET_SCHEDULER_add_now (&do_error, handle);
376 return;
377 }
378 identity_json = json_object_get (data_json, "identity");
379 if (NULL == identity_json)
380 {
381 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
382 "Unable to parse identity\n");
383 json_decref (data_json);
384 GNUNET_SCHEDULER_add_now (&do_error, handle);
385 return;
386 }
387 idtoken_json = json_object_get (data_json, "id_token");
388 if (NULL == idtoken_json)
389 {
390 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
391 "Unable to parse id_token\n");
392 json_decref (data_json);
393 GNUNET_SCHEDULER_add_now (&do_error, handle);
394 return;
395 }
396 pp_json = json_object_get (data_json, "public_params");
397 if (NULL == pp_json)
398 {
399 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
400 "Unable to parse public parameters\n");
401 json_decref (data_json);
402 GNUNET_SCHEDULER_add_now (&do_error, handle);
403 return;
404 }
405
406 PABC_ASSERT (pabc_new_ctx (&ctx));
407 char *pp_str = json_dumps (pp_json, JSON_ENCODE_ANY);
408 status = pabc_decode_and_new_public_parameters (ctx,
409 &pp,
410 pp_str);
411 char *ppid;
412 GNUNET_assert (PABC_OK == pabc_cred_get_ppid_from_pp (pp_str, &ppid));
413 GNUNET_free (pp_str);
414 if (status != PABC_OK)
415 {
416 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
417 "Failed to read public parameters: %s\n",
418 pp_str);
419 json_decref (data_json);
420 GNUNET_SCHEDULER_add_now (&do_error, handle);
421 return;
422 }
423 // (Over)write parameters
424 status = PABC_write_public_parameters (json_string_value (iss_json),
425 pp);
426 if (status != PABC_OK)
427 {
428 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
429 "Failed to write public parameters.\n");
430 json_decref (data_json);
431 GNUNET_SCHEDULER_add_now (&do_error, handle);
432 return;
433 }
434 status = PABC_read_usr_ctx (json_string_value (identity_json),
435 json_string_value (iss_json),
436 ctx, pp, &usr_ctx);
437 if (PABC_OK != status)
438 {
439 if (GNUNET_OK != setup_new_user_context (ctx, pp, &usr_ctx))
440 {
441 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup user context.\n");
442 pabc_free_public_parameters (ctx, &pp);
443 json_decref (data_json);
444 GNUNET_SCHEDULER_add_now (&do_error, handle);
445 return;
446 }
447 PABC_write_usr_ctx (json_string_value (identity_json),
448 json_string_value (iss_json),
449 ctx, pp, usr_ctx);
450 }
451
452 // Set attributes from JWT to context
453 status = set_attributes_from_idtoken (ctx,
454 pp,
455 usr_ctx,
456 json_string_value (idtoken_json));
457 if (status != PABC_OK)
458 {
459 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to set attributes.\n");
460 pabc_free_user_context (ctx, pp, &usr_ctx);
461 pabc_free_public_parameters (ctx, &pp);
462 json_decref (data_json);
463 GNUNET_SCHEDULER_add_now (&do_error, handle);
464 return;
465 }
466
467
468 // nonce
469 status = pabc_new_nonce (ctx, &nonce);
470 if (status != PABC_OK)
471 {
472 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to allocate nonce.\n");
473 pabc_free_user_context (ctx, pp, &usr_ctx);
474 pabc_free_public_parameters (ctx, &pp);
475 json_decref (data_json);
476 GNUNET_SCHEDULER_add_now (&do_error, handle);
477 return;
478 }
479 char *nonce_str = json_dumps (nonce_json, JSON_ENCODE_ANY);
480 status = pabc_decode_nonce (ctx, nonce, nonce_str);
481 if (status != PABC_OK)
482 {
483 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to decode nonce.\n");
484 pabc_free_nonce (ctx, &nonce);
485 pabc_free_user_context (ctx, pp, &usr_ctx);
486 pabc_free_public_parameters (ctx, &pp);
487 json_decref (data_json);
488 GNUNET_SCHEDULER_add_now (&do_error, handle);
489 return;
490 }
491
492 // cr
493 status = pabc_new_credential_request (ctx, pp, &cr);
494 if (PABC_OK != status)
495 {
496 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to allocate cr.\n");
497 pabc_free_nonce (ctx, &nonce);
498 pabc_free_user_context (ctx, pp, &usr_ctx);
499 pabc_free_public_parameters (ctx, &pp);
500 json_decref (data_json);
501 GNUNET_SCHEDULER_add_now (&do_error, handle);
502 return;
503 }
504
505 status = pabc_gen_credential_request (ctx, pp, usr_ctx, nonce, cr);
506 if (PABC_OK != status)
507 {
508 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to generate cr.\n");
509 pabc_free_nonce (ctx, &nonce);
510 pabc_free_credential_request (ctx, pp, &cr);
511 pabc_free_user_context (ctx, pp, &usr_ctx);
512 pabc_free_public_parameters (ctx, &pp);
513 json_decref (data_json);
514 GNUNET_SCHEDULER_add_now (&do_error, handle);
515 return;
516 }
517 handle->resp_object = json_object ();
518 GNUNET_assert (PABC_OK == pabc_cred_encode_cr (ctx, pp, cr,
519 json_string_value (
520 identity_json),
521 ppid, &response_str));
522 if (PABC_OK != status)
523 {
524 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to serialize cr.\n");
525 pabc_free_nonce (ctx, &nonce);
526 pabc_free_credential_request (ctx, pp, &cr);
527 pabc_free_user_context (ctx, pp, &usr_ctx);
528 pabc_free_public_parameters (ctx, &pp);
529 json_decref (data_json);
530 GNUNET_SCHEDULER_add_now (&do_error, handle);
531 return;
532 }
533 json_decref (handle->resp_object);
534 handle->resp_object = json_loads (response_str, JSON_DECODE_ANY, &err);
535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", response_str);
536 GNUNET_free (response_str);
537
538 // clean up
539 pabc_free_nonce (ctx, &nonce);
540 pabc_free_credential_request (ctx, pp, &cr);
541 pabc_free_user_context (ctx, pp, &usr_ctx);
542 pabc_free_public_parameters (ctx, &pp);
543 GNUNET_SCHEDULER_add_now (&return_response, handle);
544 json_decref (data_json);
545}
546
547
548/**
549 * Respond to OPTIONS request
550 *
551 * @param con_handle the connection handle
552 * @param url the url
553 * @param cls the RequestHandle
554 */
555static void
556options_cont (struct GNUNET_REST_RequestHandle *con_handle,
557 const char *url,
558 void *cls)
559{
560 struct MHD_Response *resp;
561 struct RequestHandle *handle = cls;
562
563 // For now, independent of path return all options
564 resp = GNUNET_REST_create_response (NULL);
565 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
566 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
567 cleanup_handle (handle);
568 return;
569}
570
571
572static enum GNUNET_GenericReturnValue
573rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
574 GNUNET_REST_ResultProcessor proc,
575 void *proc_cls)
576{
577 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
578 struct GNUNET_REST_RequestHandlerError err;
579 static const struct GNUNET_REST_RequestHandler handlers[] = {
580 {MHD_HTTP_METHOD_POST,
581 GNUNET_REST_API_NS_PABC_CR, &cr_cont },
582 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PABC, &options_cont },
583 GNUNET_REST_HANDLER_END
584 };
585
586 handle->response_code = 0;
587 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
588 handle->proc_cls = proc_cls;
589 handle->proc = proc;
590 handle->rest_handle = rest_handle;
591
592 handle->url = GNUNET_strdup (rest_handle->url);
593 if (handle->url[strlen (handle->url) - 1] == '/')
594 handle->url[strlen (handle->url) - 1] = '\0';
595 handle->timeout_task =
596 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
597 GNUNET_CONTAINER_DLL_insert (requests_head,
598 requests_tail,
599 handle);
600 if (GNUNET_NO ==
601 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
602 {
603 cleanup_handle (handle);
604 return GNUNET_NO;
605 }
606
607 return GNUNET_YES;
608}
609
610
611/**
612 * Entry point for the plugin.
613 *
614 * @param cls Config info
615 * @return NULL on error, otherwise the plugin context
616 */
617void *
618libgnunet_plugin_rest_pabc_init (void *cls)
619{
620 static struct Plugin plugin;
621 struct GNUNET_REST_Plugin *api;
622
623 cfg = cls;
624 if (NULL != plugin.cfg)
625 return NULL; /* can only initialize once! */
626 memset (&plugin, 0, sizeof(struct Plugin));
627 plugin.cfg = cfg;
628 api = GNUNET_new (struct GNUNET_REST_Plugin);
629 api->cls = &plugin;
630 api->name = GNUNET_REST_API_NS_PABC;
631 api->process_request = &rest_identity_process_request;
632 GNUNET_asprintf (&allow_methods,
633 "%s, %s",
634 MHD_HTTP_METHOD_POST,
635 MHD_HTTP_METHOD_OPTIONS);
636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
637 _ ("Identity Provider REST API initialized\n"));
638 return api;
639}
640
641
642/**
643 * Exit point from the plugin.
644 *
645 * @param cls the plugin context (as returned by "init")
646 * @return always NULL
647 */
648void *
649libgnunet_plugin_rest_reclaim_done (void *cls)
650{
651 struct GNUNET_REST_Plugin *api = cls;
652 struct Plugin *plugin = api->cls;
653 struct RequestHandle *request;
654
655 plugin->cfg = NULL;
656 while (NULL != (request = requests_head))
657 do_error (request);
658
659 GNUNET_free (allow_methods);
660 GNUNET_free (api);
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "PABC REST plugin is finished\n");
663 return NULL;
664}
665
666
667/* end of plugin_rest_reclaim.c */
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
deleted file mode 100644
index b2586109a..000000000
--- a/src/reclaim/plugin_rest_reclaim.c
+++ /dev/null
@@ -1,1564 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Martin Schanzenbach
22 * @author Philippe Buschmann
23 * @file reclaim/plugin_rest_reclaim.c
24 * @brief GNUnet reclaim REST plugin
25 *
26 */
27#include "platform.h"
28#include "microhttpd.h"
29#include <inttypes.h>
30#include <jansson.h>
31#include "gnunet_gns_service.h"
32#include "gnunet_gnsrecord_lib.h"
33#include "gnunet_identity_service.h"
34#include "gnunet_reclaim_lib.h"
35#include "gnunet_reclaim_service.h"
36#include "gnunet_rest_lib.h"
37#include "gnunet_rest_plugin.h"
38#include "gnunet_signatures.h"
39#include "json_reclaim.h"
40/**
41 * REST root namespace
42 */
43#define GNUNET_REST_API_NS_RECLAIM "/reclaim"
44
45/**
46 * Attribute namespace
47 */
48#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
49
50/**
51 * Credential namespace
52 */
53#define GNUNET_REST_API_NS_RECLAIM_CREDENTIAL "/reclaim/credential"
54
55/**
56 * Ticket namespace
57 */
58#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
59
60/**
61 * Revoke namespace
62 */
63#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/reclaim/revoke"
64
65/**
66 * Revoke namespace
67 */
68#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/reclaim/consume"
69
70/**
71 * State while collecting all egos
72 */
73#define ID_REST_STATE_INIT 0
74
75/**
76 * Done collecting egos
77 */
78#define ID_REST_STATE_POST_INIT 1
79
80/**
81 * The configuration handle
82 */
83const struct GNUNET_CONFIGURATION_Handle *cfg;
84
85/**
86 * HTTP methods allows for this plugin
87 */
88static char *allow_methods;
89
90/**
91 * Ego list
92 */
93static struct EgoEntry *ego_head;
94
95/**
96 * Ego list
97 */
98static struct EgoEntry *ego_tail;
99
100/**
101 * The processing state
102 */
103static int state;
104
105/**
106 * Handle to Identity service.
107 */
108static struct GNUNET_IDENTITY_Handle *identity_handle;
109
110/**
111 * Identity Provider
112 */
113static struct GNUNET_RECLAIM_Handle *idp;
114
115/**
116 * @brief struct returned by the initialization function of the plugin
117 */
118struct Plugin
119{
120 const struct GNUNET_CONFIGURATION_Handle *cfg;
121};
122
123/**
124 * The ego list
125 */
126struct EgoEntry
127{
128 /**
129 * DLL
130 */
131 struct EgoEntry *next;
132
133 /**
134 * DLL
135 */
136 struct EgoEntry *prev;
137
138 /**
139 * Ego Identifier
140 */
141 char *identifier;
142
143 /**
144 * Public key string
145 */
146 char *keystring;
147
148 /**
149 * The Ego
150 */
151 struct GNUNET_IDENTITY_Ego *ego;
152};
153
154
155struct RequestHandle
156{
157 /**
158 * DLL
159 */
160 struct RequestHandle *next;
161
162 /**
163 * DLL
164 */
165 struct RequestHandle *prev;
166
167 /**
168 * Selected ego
169 */
170 struct EgoEntry *ego_entry;
171
172 /**
173 * Pointer to ego private key
174 */
175 struct GNUNET_CRYPTO_PrivateKey priv_key;
176
177 /**
178 * Rest connection
179 */
180 struct GNUNET_REST_RequestHandle *rest_handle;
181
182 /**
183 * Attribute claim list
184 */
185 struct GNUNET_RECLAIM_AttributeList *attr_list;
186
187 /**
188 * IDENTITY Operation
189 */
190 struct GNUNET_IDENTITY_Operation *op;
191
192 /**
193 * Idp Operation
194 */
195 struct GNUNET_RECLAIM_Operation *idp_op;
196
197 /**
198 * Attribute iterator
199 */
200 struct GNUNET_RECLAIM_AttributeIterator *attr_it;
201
202 /**
203 * Attribute iterator
204 */
205 struct GNUNET_RECLAIM_CredentialIterator *cred_it;
206
207 /**
208 * Ticket iterator
209 */
210 struct GNUNET_RECLAIM_TicketIterator *ticket_it;
211
212 /**
213 * A ticket
214 */
215 struct GNUNET_RECLAIM_Ticket ticket;
216
217 /**
218 * Desired timeout for the lookup (default is no timeout).
219 */
220 struct GNUNET_TIME_Relative timeout;
221
222 /**
223 * ID of a task associated with the resolution process.
224 */
225 struct GNUNET_SCHEDULER_Task *timeout_task;
226
227 /**
228 * The plugin result processor
229 */
230 GNUNET_REST_ResultProcessor proc;
231
232 /**
233 * The closure of the result processor
234 */
235 void *proc_cls;
236
237 /**
238 * The url
239 */
240 char *url;
241
242 /**
243 * Error response message
244 */
245 char *emsg;
246
247 /**
248 * Response code
249 */
250 int response_code;
251
252 /**
253 * Response object
254 */
255 json_t *resp_object;
256};
257
258/**
259 * DLL
260 */
261static struct RequestHandle *requests_head;
262
263/**
264 * DLL
265 */
266static struct RequestHandle *requests_tail;
267
268
269/**
270 * Cleanup lookup handle
271 * @param handle Handle to clean up
272 */
273static void
274cleanup_handle (void *cls)
275{
276 struct RequestHandle *handle = cls;
277
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
279 if (NULL != handle->resp_object)
280 json_decref (handle->resp_object);
281 if (NULL != handle->timeout_task)
282 GNUNET_SCHEDULER_cancel (handle->timeout_task);
283 if (NULL != handle->attr_it)
284 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
285 if (NULL != handle->cred_it)
286 GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
287 if (NULL != handle->ticket_it)
288 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
289 if (NULL != handle->url)
290 GNUNET_free (handle->url);
291 if (NULL != handle->emsg)
292 GNUNET_free (handle->emsg);
293 if (NULL != handle->attr_list)
294 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list);
295 GNUNET_CONTAINER_DLL_remove (requests_head,
296 requests_tail,
297 handle);
298 GNUNET_free (handle);
299}
300
301
302/**
303 * Task run on error, sends error message. Cleans up everything.
304 *
305 * @param cls the `struct RequestHandle`
306 */
307static void
308do_error (void *cls)
309{
310 struct RequestHandle *handle = cls;
311 struct MHD_Response *resp;
312 char *json_error;
313
314 GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", handle->emsg);
315 if (0 == handle->response_code)
316 {
317 handle->response_code = MHD_HTTP_BAD_REQUEST;
318 }
319 resp = GNUNET_REST_create_response (json_error);
320 GNUNET_assert (MHD_NO != MHD_add_response_header (resp, "Content-Type", "application/json"));
321 handle->proc (handle->proc_cls, resp, handle->response_code);
322 cleanup_handle (handle);
323 GNUNET_free (json_error);
324}
325
326
327/**
328 * Task run on timeout, sends error message. Cleans up everything.
329 *
330 * @param cls the `struct RequestHandle`
331 */
332static void
333do_timeout (void *cls)
334{
335 struct RequestHandle *handle = cls;
336
337 handle->timeout_task = NULL;
338 do_error (handle);
339}
340
341
342static void
343collect_error_cb (void *cls)
344{
345 GNUNET_SCHEDULER_add_now (&do_error, cls);
346}
347
348
349static void
350finished_cont (void *cls, int32_t success, const char *emsg)
351{
352 struct RequestHandle *handle = cls;
353 struct MHD_Response *resp;
354
355 handle->idp_op = NULL;
356 if (GNUNET_OK != success)
357 {
358 GNUNET_SCHEDULER_add_now (&do_error, handle);
359 return;
360 }
361 resp = GNUNET_REST_create_response (emsg);
362 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
363 "Content-Type",
364 "application/json"));
365 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
366 "Access-Control-Allow-Methods",
367 allow_methods));
368 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
369 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
370}
371
372
373static void
374delete_finished_cb (void *cls, int32_t success, const char *emsg)
375{
376 struct RequestHandle *handle = cls;
377 struct MHD_Response *resp;
378
379 if (GNUNET_OK != success)
380 {
381 GNUNET_SCHEDULER_add_now (&do_error, handle);
382 return;
383 }
384 resp = GNUNET_REST_create_response (emsg);
385 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
386 "Access-Control-Allow-Methods",
387 allow_methods));
388 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
389 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
390}
391
392
393/**
394 * Return attributes for identity
395 *
396 * @param cls the request handle
397 */
398static void
399return_response (void *cls)
400{
401 char *result_str;
402 struct RequestHandle *handle = cls;
403 struct MHD_Response *resp;
404
405 result_str = json_dumps (handle->resp_object, 0);
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
407 resp = GNUNET_REST_create_response (result_str);
408 GNUNET_assert (MHD_NO !=
409 MHD_add_response_header (resp,
410 "Access-Control-Allow-Methods",
411 allow_methods));
412 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
413 GNUNET_free (result_str);
414 cleanup_handle (handle);
415}
416
417
418static void
419collect_finished_cb (void *cls)
420{
421 struct RequestHandle *handle = cls;
422
423 // Done
424 handle->attr_it = NULL;
425 handle->cred_it = NULL;
426 handle->ticket_it = NULL;
427 GNUNET_SCHEDULER_add_now (&return_response, handle);
428}
429
430
431/**
432 * Collect all attributes for an ego
433 *
434 */
435static void
436ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
437{
438 json_t *json_resource;
439 struct RequestHandle *handle = cls;
440 json_t *value;
441 char *tmp;
442
443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
444 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
445 json_resource = json_object ();
446 GNUNET_free (tmp);
447 json_array_append (handle->resp_object, json_resource);
448
449 tmp =
450 GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
451 sizeof(struct
452 GNUNET_CRYPTO_PublicKey));
453 value = json_string (tmp);
454 json_object_set_new (json_resource, "issuer", value);
455 GNUNET_free (tmp);
456 tmp =
457 GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
458 sizeof(struct
459 GNUNET_CRYPTO_PublicKey));
460 value = json_string (tmp);
461 json_object_set_new (json_resource, "audience", value);
462 GNUNET_free (tmp);
463 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof(ticket->rnd));
464 value = json_string (tmp);
465 json_object_set_new (json_resource, "rnd", value);
466 GNUNET_free (tmp);
467 GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
468}
469
470
471static void
472add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
473 const char *url,
474 void *cls)
475{
476 struct RequestHandle *handle = cls;
477 const struct GNUNET_CRYPTO_PrivateKey *identity_priv;
478 const char *identity;
479 struct EgoEntry *ego_entry;
480 struct GNUNET_RECLAIM_Credential *attribute;
481 struct GNUNET_TIME_Relative exp;
482 char term_data[handle->rest_handle->data_size + 1];
483 json_t *data_json;
484 json_error_t err;
485 struct GNUNET_JSON_Specification attrspec[] =
486 { GNUNET_RECLAIM_JSON_spec_credential (&attribute),
487 GNUNET_JSON_spec_end () };
488
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Adding an credential for %s.\n",
491 handle->url);
492 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
493 handle->url))
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
496 GNUNET_SCHEDULER_add_now (&do_error, handle);
497 return;
498 }
499 identity = handle->url + strlen (
500 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
501
502 for (ego_entry = ego_head; NULL != ego_entry;
503 ego_entry = ego_entry->next)
504 if (0 == strcmp (identity, ego_entry->identifier))
505 break;
506
507 if (NULL == ego_entry)
508 {
509 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
510 return;
511 }
512 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
513
514 if (0 >= handle->rest_handle->data_size)
515 {
516 GNUNET_SCHEDULER_add_now (&do_error, handle);
517 return;
518 }
519
520 term_data[handle->rest_handle->data_size] = '\0';
521 GNUNET_memcpy (term_data,
522 handle->rest_handle->data,
523 handle->rest_handle->data_size);
524 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
525 if (GNUNET_OK != GNUNET_JSON_parse (data_json, attrspec, NULL, NULL))
526 {
527 json_decref (data_json);
528 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
529 "Unable to parse JSON from %s\n",
530 term_data);
531 GNUNET_SCHEDULER_add_now (&do_error, handle);
532 return;
533 }
534 json_decref (data_json);
535 if (NULL == attribute)
536 {
537 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
538 "Unable to parse credential from %s\n",
539 term_data);
540 GNUNET_SCHEDULER_add_now (&do_error, handle);
541 return;
542 }
543 /**
544 * New ID for attribute
545 */
546 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
547 GNUNET_RECLAIM_id_generate (&attribute->id);
548 exp = GNUNET_TIME_UNIT_HOURS;
549 handle->idp_op = GNUNET_RECLAIM_credential_store (idp,
550 identity_priv,
551 attribute,
552 &exp,
553 &finished_cont,
554 handle);
555 GNUNET_JSON_parse_free (attrspec);
556}
557
558
559/**
560 * Collect all credentials for an ego
561 *
562 */
563static void
564cred_collect (void *cls,
565 const struct GNUNET_CRYPTO_PublicKey *identity,
566 const struct GNUNET_RECLAIM_Credential *cred)
567{
568 struct RequestHandle *handle = cls;
569 struct GNUNET_RECLAIM_AttributeList *attrs;
570 struct GNUNET_RECLAIM_AttributeListEntry *ale;
571 struct GNUNET_TIME_Absolute exp;
572 json_t *attr_obj;
573 json_t *cred_obj;
574 const char *type;
575 char *tmp_value;
576 char *id_str;
577 char *issuer;
578
579
580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential: %s\n",
581 cred->name);
582 attrs = GNUNET_RECLAIM_credential_get_attributes (cred);
583 issuer = GNUNET_RECLAIM_credential_get_issuer (cred);
584 tmp_value = GNUNET_RECLAIM_credential_value_to_string (cred->type,
585 cred->data,
586 cred->data_size);
587 cred_obj = json_object ();
588 json_object_set_new (cred_obj, "value", json_string (tmp_value));
589 json_object_set_new (cred_obj, "name", json_string (cred->name));
590 type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
591 json_object_set_new (cred_obj, "type", json_string (type));
592 if (NULL != issuer)
593 {
594 json_object_set_new (cred_obj, "issuer", json_string (issuer));
595 GNUNET_free (issuer);
596 }
597 if (GNUNET_OK == GNUNET_RECLAIM_credential_get_expiration (cred,
598 &exp))
599 {
600 json_object_set_new (cred_obj, "expiration", json_integer (
601 exp.abs_value_us));
602 }
603 id_str = GNUNET_STRINGS_data_to_string_alloc (&cred->id,
604 sizeof(cred->id));
605 json_object_set_new (cred_obj, "id", json_string (id_str));
606 GNUNET_free (tmp_value);
607 GNUNET_free (id_str);
608 if (NULL != attrs)
609 {
610 json_t *attr_arr = json_array ();
611 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
612 {
613 tmp_value =
614 GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
615 ale->attribute->data,
616 ale->attribute->data_size);
617 attr_obj = json_object ();
618 json_object_set_new (attr_obj, "value", json_string (tmp_value));
619 json_object_set_new (attr_obj, "name", json_string (
620 ale->attribute->name));
621
622 json_object_set_new (attr_obj, "flag", json_string ("1")); // FIXME
623 type = GNUNET_RECLAIM_attribute_number_to_typename (ale->attribute->type);
624 json_object_set_new (attr_obj, "type", json_string (type));
625 json_object_set_new (attr_obj, "id", json_string (""));
626 json_object_set_new (attr_obj, "credential", json_string (""));
627 json_array_append_new (attr_arr, attr_obj);
628 GNUNET_free (tmp_value);
629 }
630 json_object_set_new (cred_obj, "attributes", attr_arr);
631 }
632 json_array_append_new (handle->resp_object, cred_obj);
633 if (NULL != attrs)
634 GNUNET_RECLAIM_attribute_list_destroy (attrs);
635 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
636}
637
638
639/**
640 * Lists credential for identity request
641 *
642 * @param con_handle the connection handle
643 * @param url the url
644 * @param cls the RequestHandle
645 */
646static void
647list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
648 const char *url,
649 void *cls)
650{
651 struct RequestHandle *handle = cls;
652 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
653 struct EgoEntry *ego_entry;
654 char *identity;
655
656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
657 "Getting credentials for %s.\n",
658 handle->url);
659 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
660 handle->url))
661 {
662 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
663 GNUNET_SCHEDULER_add_now (&do_error, handle);
664 return;
665 }
666 identity = handle->url + strlen (
667 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
668
669 for (ego_entry = ego_head; NULL != ego_entry;
670 ego_entry = ego_entry->next)
671 if (0 == strcmp (identity, ego_entry->identifier))
672 break;
673 handle->resp_object = json_array ();
674
675
676 if (NULL == ego_entry)
677 {
678 // Done
679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
680 GNUNET_SCHEDULER_add_now (&return_response, handle);
681 return;
682 }
683 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
684 handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
685 priv_key,
686 &collect_error_cb,
687 handle,
688 &cred_collect,
689 handle,
690 &
691 collect_finished_cb,
692 handle);
693}
694
695
696/**
697 * Deletes credential from an identity
698 *
699 * @param con_handle the connection handle
700 * @param url the url
701 * @param cls the RequestHandle
702 */
703static void
704delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
705 const char *url,
706 void *cls)
707{
708 struct RequestHandle *handle = cls;
709 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
710 struct GNUNET_RECLAIM_Credential attr;
711 struct EgoEntry *ego_entry;
712 char *identity_id_str;
713 char *identity;
714 char *id;
715
716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting credential.\n");
717 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
718 handle->url))
719 {
720 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
721 GNUNET_SCHEDULER_add_now (&do_error, handle);
722 return;
723 }
724 identity_id_str =
725 strdup (handle->url + strlen (
726 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1);
727 identity = strtok (identity_id_str, "/");
728 id = strtok (NULL, "/");
729 if ((NULL == identity) || (NULL == id))
730 {
731 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
732 GNUNET_free (identity_id_str);
733 GNUNET_SCHEDULER_add_now (&do_error, handle);
734 return;
735 }
736
737 for (ego_entry = ego_head; NULL != ego_entry;
738 ego_entry = ego_entry->next)
739 if (0 == strcmp (identity, ego_entry->identifier))
740 break;
741 handle->resp_object = json_array ();
742 if (NULL == ego_entry)
743 {
744 // Done
745 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
746 GNUNET_free (identity_id_str);
747 GNUNET_SCHEDULER_add_now (&return_response, handle);
748 return;
749 }
750 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
751 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Credential));
752 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
753 attr.name = "";
754 handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
755 priv_key,
756 &attr,
757 &delete_finished_cb,
758 handle);
759 GNUNET_free (identity_id_str);
760}
761
762
763/**
764 * List tickets for identity request
765 *
766 * @param con_handle the connection handle
767 * @param url the url
768 * @param cls the RequestHandle
769 */
770static void
771list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
772 const char *url,
773 void *cls)
774{
775 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
776 struct RequestHandle *handle = cls;
777 struct EgoEntry *ego_entry;
778 char *identity;
779
780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
781 "Getting tickets for %s.\n",
782 handle->url);
783 if (strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= strlen (handle->url))
784 {
785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
786 GNUNET_SCHEDULER_add_now (&do_error, handle);
787 return;
788 }
789 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
790
791 for (ego_entry = ego_head; NULL != ego_entry;
792 ego_entry = ego_entry->next)
793 if (0 == strcmp (identity, ego_entry->identifier))
794 break;
795 handle->resp_object = json_array ();
796
797 if (NULL == ego_entry)
798 {
799 // Done
800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
801 GNUNET_SCHEDULER_add_now (&return_response, handle);
802 return;
803 }
804 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
805 handle->ticket_it =
806 GNUNET_RECLAIM_ticket_iteration_start (idp,
807 priv_key,
808 &collect_error_cb,
809 handle,
810 &ticket_collect,
811 handle,
812 &collect_finished_cb,
813 handle);
814}
815
816
817static void
818add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
819 const char *url,
820 void *cls)
821{
822 const struct GNUNET_CRYPTO_PrivateKey *identity_priv;
823 const char *identity;
824 struct RequestHandle *handle = cls;
825 struct EgoEntry *ego_entry;
826 struct GNUNET_RECLAIM_Attribute *attribute;
827 struct GNUNET_TIME_Relative exp;
828 char term_data[handle->rest_handle->data_size + 1];
829 json_t *data_json;
830 json_error_t err;
831 struct GNUNET_JSON_Specification attrspec[] =
832 { GNUNET_RECLAIM_JSON_spec_attribute (&attribute), GNUNET_JSON_spec_end () };
833
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
835 "Adding an attribute for %s.\n",
836 handle->url);
837 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
838 {
839 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
840 GNUNET_SCHEDULER_add_now (&do_error, handle);
841 return;
842 }
843 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
844
845 for (ego_entry = ego_head; NULL != ego_entry;
846 ego_entry = ego_entry->next)
847 if (0 == strcmp (identity, ego_entry->identifier))
848 break;
849
850 if (NULL == ego_entry)
851 {
852 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
853 return;
854 }
855 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
856
857 if (0 >= handle->rest_handle->data_size)
858 {
859 GNUNET_SCHEDULER_add_now (&do_error, handle);
860 return;
861 }
862
863 term_data[handle->rest_handle->data_size] = '\0';
864 GNUNET_memcpy (term_data,
865 handle->rest_handle->data,
866 handle->rest_handle->data_size);
867 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
868 GNUNET_assert (GNUNET_OK ==
869 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
870 json_decref (data_json);
871 if (NULL == attribute)
872 {
873 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
874 "Unable to parse attribute from %s\n",
875 term_data);
876 GNUNET_SCHEDULER_add_now (&do_error, handle);
877 return;
878 }
879 /**
880 * New ID for attribute
881 */
882 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
883 GNUNET_RECLAIM_id_generate (&attribute->id);
884 exp = GNUNET_TIME_UNIT_HOURS;
885 handle->idp_op = GNUNET_RECLAIM_attribute_store (idp,
886 identity_priv,
887 attribute,
888 &exp,
889 &finished_cont,
890 handle);
891 GNUNET_JSON_parse_free (attrspec);
892}
893
894
895/**
896 * Parse a JWT and return the respective claim value as Attribute
897 *
898 * @param cred the jwt credential
899 * @param claim the name of the claim in the JWT
900 *
901 * @return a GNUNET_RECLAIM_Attribute, containing the new value
902 */
903struct GNUNET_RECLAIM_Attribute *
904parse_jwt (const struct GNUNET_RECLAIM_Credential *cred,
905 const char *claim)
906{
907 char *jwt_string;
908 struct GNUNET_RECLAIM_Attribute *attr;
909 char delim[] = ".";
910 const char *type_str = NULL;
911 const char *val_str = NULL;
912 char *data;
913 size_t data_size;
914 uint32_t type;
915 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
916 char *decoded_jwt;
917 json_t *json_val;
918 json_error_t *json_err = NULL;
919
920 jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type,
921 cred->data,
922 cred->data_size);
923 char *jwt_body = strtok (jwt_string, delim);
924 jwt_body = strtok (NULL, delim);
925 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
926 (void **) &decoded_jwt);
927 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
928 const char *key;
929 json_t *value;
930 json_object_foreach (json_val, key, value) {
931 if (0 == strcasecmp (key,claim))
932 {
933 val_str = json_dumps (value, JSON_ENCODE_ANY);
934 }
935 }
936 type_str = "String";
937 type = GNUNET_RECLAIM_attribute_typename_to_number (type_str);
938 if (GNUNET_SYSERR == GNUNET_RECLAIM_attribute_string_to_value (type,val_str,
939 (void **) &data,
940 &data_size))
941 {
942 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
943 "Attribute value from JWT Parser invalid!\n");
944 GNUNET_RECLAIM_attribute_string_to_value (type,
945 "Error: Referenced Claim Name not Found",
946 (void **) &data,
947 &data_size);
948 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
949 type, data, data_size);
950 attr->id = cred->id;
951 attr->flag = 1;
952 }
953 else
954 {
955 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
956 type, data, data_size);
957 attr->id = cred->id;
958 attr->flag = 1;
959 }
960 return attr;
961}
962
963
964/**
965 * Collect all attributes for an ego
966 *
967 */
968static void
969attr_collect (void *cls,
970 const struct GNUNET_CRYPTO_PublicKey *identity,
971 const struct GNUNET_RECLAIM_Attribute *attr)
972{
973 struct RequestHandle *handle = cls;
974 json_t *attr_obj;
975 const char *type;
976 char *id_str;
977
978 char *tmp_value;
979 tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
980 attr->data,
981 attr->data_size);
982 attr_obj = json_object ();
983 json_object_set_new (attr_obj, "value", json_string (tmp_value));
984 json_object_set_new (attr_obj, "name", json_string (attr->name));
985
986 if (GNUNET_RECLAIM_id_is_zero (&attr->credential))
987 json_object_set_new (attr_obj, "flag", json_string ("0"));
988 else
989 json_object_set_new (attr_obj, "flag", json_string ("1"));
990 type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
991 json_object_set_new (attr_obj, "type", json_string (type));
992 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
993 sizeof(attr->id));
994 json_object_set_new (attr_obj, "id", json_string (id_str));
995 GNUNET_free (id_str);
996 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
997 sizeof(attr->credential));
998 json_object_set_new (attr_obj, "credential", json_string (id_str));
999 GNUNET_free (id_str);
1000 json_array_append (handle->resp_object, attr_obj);
1001 json_decref (attr_obj);
1002 GNUNET_free (tmp_value);
1003 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1004}
1005
1006
1007/**
1008 * List attributes for identity request
1009 *
1010 * @param con_handle the connection handle
1011 * @param url the url
1012 * @param cls the RequestHandle
1013 */
1014static void
1015list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1016 const char *url,
1017 void *cls)
1018{
1019 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1020 struct RequestHandle *handle = cls;
1021 struct EgoEntry *ego_entry;
1022 char *identity;
1023
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1025 "Getting attributes for %s.\n",
1026 handle->url);
1027 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1028 {
1029 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1030 GNUNET_SCHEDULER_add_now (&do_error, handle);
1031 return;
1032 }
1033 identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
1034
1035 for (ego_entry = ego_head; NULL != ego_entry;
1036 ego_entry = ego_entry->next)
1037 if (0 == strcmp (identity, ego_entry->identifier))
1038 break;
1039 handle->resp_object = json_array ();
1040
1041
1042 if (NULL == ego_entry)
1043 {
1044 // Done
1045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1046 GNUNET_SCHEDULER_add_now (&return_response, handle);
1047 return;
1048 }
1049 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1050 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (idp,
1051 priv_key,
1052 &collect_error_cb,
1053 handle,
1054 &attr_collect,
1055 handle,
1056 &collect_finished_cb,
1057 handle);
1058}
1059
1060
1061/**
1062 * List attributes for identity request
1063 *
1064 * @param con_handle the connection handle
1065 * @param url the url
1066 * @param cls the RequestHandle
1067 */
1068static void
1069delete_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
1070 const char *url,
1071 void *cls)
1072{
1073 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1074 struct RequestHandle *handle = cls;
1075 struct GNUNET_RECLAIM_Attribute attr;
1076 struct EgoEntry *ego_entry;
1077 char *identity_id_str;
1078 char *identity;
1079 char *id;
1080
1081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attributes.\n");
1082 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen (handle->url))
1083 {
1084 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1085 GNUNET_SCHEDULER_add_now (&do_error, handle);
1086 return;
1087 }
1088 identity_id_str =
1089 strdup (handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1);
1090 identity = strtok (identity_id_str, "/");
1091 id = strtok (NULL, "/");
1092 if ((NULL == identity) || (NULL == id))
1093 {
1094 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
1095 GNUNET_free (identity_id_str);
1096 GNUNET_SCHEDULER_add_now (&do_error, handle);
1097 return;
1098 }
1099
1100 for (ego_entry = ego_head; NULL != ego_entry;
1101 ego_entry = ego_entry->next)
1102 if (0 == strcmp (identity, ego_entry->identifier))
1103 break;
1104 handle->resp_object = json_array ();
1105 if (NULL == ego_entry)
1106 {
1107 // Done
1108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1109 GNUNET_free (identity_id_str);
1110 GNUNET_SCHEDULER_add_now (&return_response, handle);
1111 return;
1112 }
1113 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1114 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Attribute));
1115 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
1116 attr.name = "";
1117 handle->idp_op = GNUNET_RECLAIM_attribute_delete (idp,
1118 priv_key,
1119 &attr,
1120 &delete_finished_cb,
1121 handle);
1122 GNUNET_free (identity_id_str);
1123}
1124
1125
1126static void
1127revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1128 const char *url,
1129 void *cls)
1130{
1131 const struct GNUNET_CRYPTO_PrivateKey *identity_priv;
1132 struct RequestHandle *handle = cls;
1133 struct EgoEntry *ego_entry;
1134 struct GNUNET_RECLAIM_Ticket *ticket = NULL;
1135 struct GNUNET_CRYPTO_PublicKey tmp_pk;
1136 char term_data[handle->rest_handle->data_size + 1];
1137 json_t *data_json;
1138 json_error_t err;
1139 struct GNUNET_JSON_Specification tktspec[] =
1140 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1141
1142 if (0 >= handle->rest_handle->data_size)
1143 {
1144 GNUNET_SCHEDULER_add_now (&do_error, handle);
1145 return;
1146 }
1147
1148 term_data[handle->rest_handle->data_size] = '\0';
1149 GNUNET_memcpy (term_data,
1150 handle->rest_handle->data,
1151 handle->rest_handle->data_size);
1152 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1153 if ((NULL == data_json) ||
1154 (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL)))
1155 {
1156 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1157 GNUNET_SCHEDULER_add_now (&do_error, handle);
1158 GNUNET_JSON_parse_free (tktspec);
1159 if (NULL != data_json)
1160 json_decref (data_json);
1161 return;
1162 }
1163 json_decref (data_json);
1164 if (NULL == ticket)
1165 {
1166 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1167 "Unable to parse ticket from %s\n",
1168 term_data);
1169 GNUNET_SCHEDULER_add_now (&do_error, handle);
1170 return;
1171 }
1172
1173 for (ego_entry = ego_head; NULL != ego_entry;
1174 ego_entry = ego_entry->next)
1175 {
1176 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1177 if (0 == memcmp (&ticket->identity,
1178 &tmp_pk,
1179 sizeof(struct GNUNET_CRYPTO_PublicKey)))
1180 break;
1181 }
1182 if (NULL == ego_entry)
1183 {
1184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1185 GNUNET_JSON_parse_free (tktspec);
1186 return;
1187 }
1188 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1189
1190 handle->idp_op = GNUNET_RECLAIM_ticket_revoke (idp,
1191 identity_priv,
1192 ticket,
1193 &finished_cont,
1194 handle);
1195 GNUNET_JSON_parse_free (tktspec);
1196}
1197
1198
1199static void
1200consume_cont (void *cls,
1201 const struct GNUNET_CRYPTO_PublicKey *identity,
1202 const struct GNUNET_RECLAIM_Attribute *attr,
1203 const struct GNUNET_RECLAIM_Presentation *presentation)
1204{
1205 struct RequestHandle *handle = cls;
1206 char *val_str;
1207 json_t *value;
1208
1209 if (NULL == identity)
1210 {
1211 GNUNET_SCHEDULER_add_now (&return_response, handle);
1212 return;
1213 }
1214
1215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
1216 val_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
1217 attr->data,
1218 attr->data_size);
1219 if (NULL == val_str)
1220 {
1221 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1222 "Failed to parse value for: %s\n",
1223 attr->name);
1224 return;
1225 }
1226 value = json_string (val_str);
1227 json_object_set_new (handle->resp_object, attr->name, value);
1228 json_decref (value);
1229 GNUNET_free (val_str);
1230}
1231
1232
1233static void
1234consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
1235 const char *url,
1236 void *cls)
1237{
1238 const struct GNUNET_CRYPTO_PrivateKey *identity_priv;
1239 struct RequestHandle *handle = cls;
1240 struct EgoEntry *ego_entry;
1241 struct GNUNET_RECLAIM_Ticket *ticket;
1242 struct GNUNET_CRYPTO_PublicKey tmp_pk;
1243 char term_data[handle->rest_handle->data_size + 1];
1244 json_t *data_json;
1245 json_error_t err;
1246 struct GNUNET_JSON_Specification tktspec[] =
1247 { GNUNET_RECLAIM_JSON_spec_ticket (&ticket), GNUNET_JSON_spec_end () };
1248
1249 if (0 >= handle->rest_handle->data_size)
1250 {
1251 GNUNET_SCHEDULER_add_now (&do_error, handle);
1252 return;
1253 }
1254
1255 term_data[handle->rest_handle->data_size] = '\0';
1256 GNUNET_memcpy (term_data,
1257 handle->rest_handle->data,
1258 handle->rest_handle->data_size);
1259 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1260 if (NULL == data_json)
1261 {
1262 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1263 "Unable to parse JSON Object from %s\n",
1264 term_data);
1265 GNUNET_SCHEDULER_add_now (&do_error, handle);
1266 return;
1267 }
1268 if (GNUNET_OK != GNUNET_JSON_parse (data_json, tktspec, NULL, NULL))
1269 {
1270 handle->emsg = GNUNET_strdup ("Not a ticket!\n");
1271 GNUNET_SCHEDULER_add_now (&do_error, handle);
1272 GNUNET_JSON_parse_free (tktspec);
1273 json_decref (data_json);
1274 return;
1275 }
1276 for (ego_entry = ego_head; NULL != ego_entry;
1277 ego_entry = ego_entry->next)
1278 {
1279 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
1280 if (0 == memcmp (&ticket->audience,
1281 &tmp_pk,
1282 sizeof(struct GNUNET_CRYPTO_PublicKey)))
1283 break;
1284 }
1285 if (NULL == ego_entry)
1286 {
1287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
1288 GNUNET_JSON_parse_free (tktspec);
1289 return;
1290 }
1291 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1292 handle->resp_object = json_object ();
1293 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
1294 identity_priv,
1295 ticket,
1296 &consume_cont,
1297 handle);
1298 GNUNET_JSON_parse_free (tktspec);
1299}
1300
1301
1302/**
1303 * Respond to OPTIONS request
1304 *
1305 * @param con_handle the connection handle
1306 * @param url the url
1307 * @param cls the RequestHandle
1308 */
1309static void
1310options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1311 const char *url,
1312 void *cls)
1313{
1314 struct MHD_Response *resp;
1315 struct RequestHandle *handle = cls;
1316
1317 // For now, independent of path return all options
1318 resp = GNUNET_REST_create_response (NULL);
1319 GNUNET_assert (MHD_NO != MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods));
1320 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1321 cleanup_handle (handle);
1322 return;
1323}
1324
1325
1326/**
1327 * If listing is enabled, prints information about the egos.
1328 *
1329 * This function is initially called for all egos and then again
1330 * whenever a ego's identifier changes or if it is deleted. At the
1331 * end of the initial pass over all egos, the function is once called
1332 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
1333 * be invoked in the future or that there was an error.
1334 *
1335 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', this
1336 * function is only called ONCE, and 'NULL' being passed in 'ego' does
1337 * indicate an error (for example because name is taken or no default value is
1338 * known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the
1339 * value WILL be passed to a subsequent call to the identity callback of
1340 * 'GNUNET_IDENTITY_connect' (if that one was not NULL).
1341 *
1342 * When an identity is renamed, this function is called with the
1343 * (known) ego but the NEW identifier.
1344 *
1345 * When an identity is deleted, this function is called with the
1346 * (known) ego and "NULL" for the 'identifier'. In this case,
1347 * the 'ego' is henceforth invalid (and the 'ctx' should also be
1348 * cleaned up).
1349 *
1350 * @param cls closure
1351 * @param ego ego handle
1352 * @param ctx context for application to store data for this ego
1353 * (during the lifetime of this process, initially NULL)
1354 * @param identifier identifier assigned by the user for this ego,
1355 * NULL if the user just deleted the ego and it
1356 * must thus no longer be used
1357 */
1358static void
1359list_ego (void *cls,
1360 struct GNUNET_IDENTITY_Ego *ego,
1361 void **ctx,
1362 const char *identifier)
1363{
1364 struct EgoEntry *ego_entry;
1365 struct GNUNET_CRYPTO_PublicKey pk;
1366
1367 if (NULL == ego)
1368 {
1369 state = ID_REST_STATE_POST_INIT;
1370 return;
1371 }
1372 if (ID_REST_STATE_INIT == state)
1373 {
1374 ego_entry = GNUNET_new (struct EgoEntry);
1375 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1376 ego_entry->keystring = GNUNET_CRYPTO_public_key_to_string (&pk);
1377 ego_entry->ego = ego;
1378 ego_entry->identifier = GNUNET_strdup (identifier);
1379 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1380 ego_tail,
1381 ego_entry);
1382 }
1383 /* Ego renamed or added */
1384 if (identifier != NULL)
1385 {
1386 for (ego_entry = ego_head; NULL != ego_entry;
1387 ego_entry = ego_entry->next)
1388 {
1389 if (ego_entry->ego == ego)
1390 {
1391 /* Rename */
1392 GNUNET_free (ego_entry->identifier);
1393 ego_entry->identifier = GNUNET_strdup (identifier);
1394 break;
1395 }
1396 }
1397 if (NULL == ego_entry)
1398 {
1399 /* Add */
1400 ego_entry = GNUNET_new (struct EgoEntry);
1401 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1402 ego_entry->keystring = GNUNET_CRYPTO_public_key_to_string (&pk);
1403 ego_entry->ego = ego;
1404 ego_entry->identifier = GNUNET_strdup (identifier);
1405 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1406 ego_tail,
1407 ego_entry);
1408 }
1409 }
1410 else
1411 {
1412 /* Delete */
1413 for (ego_entry = ego_head; NULL != ego_entry;
1414 ego_entry = ego_entry->next)
1415 {
1416 if (ego_entry->ego == ego)
1417 break;
1418 }
1419 if (NULL == ego_entry)
1420 return; /* Not found */
1421
1422 GNUNET_CONTAINER_DLL_remove (ego_head,
1423 ego_tail,
1424 ego_entry);
1425 GNUNET_free (ego_entry->identifier);
1426 GNUNET_free (ego_entry->keystring);
1427 GNUNET_free (ego_entry);
1428 return;
1429 }
1430
1431}
1432
1433
1434static enum GNUNET_GenericReturnValue
1435rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1436 GNUNET_REST_ResultProcessor proc,
1437 void *proc_cls)
1438{
1439 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1440 struct GNUNET_REST_RequestHandlerError err;
1441 static const struct GNUNET_REST_RequestHandler handlers[] =
1442 { { MHD_HTTP_METHOD_GET,
1443 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont },
1444 { MHD_HTTP_METHOD_POST,
1445 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont },
1446 { MHD_HTTP_METHOD_DELETE,
1447 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont },
1448 { MHD_HTTP_METHOD_GET,
1449 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
1450 { MHD_HTTP_METHOD_POST,
1451 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
1452 { MHD_HTTP_METHOD_DELETE,
1453 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont },
1454 { MHD_HTTP_METHOD_GET,
1455 GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont },
1456 { MHD_HTTP_METHOD_POST,
1457 GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont },
1458 { MHD_HTTP_METHOD_POST,
1459 GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont },
1460 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
1461 GNUNET_REST_HANDLER_END};
1462
1463 handle->response_code = 0;
1464 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1465 handle->proc_cls = proc_cls;
1466 handle->proc = proc;
1467 handle->rest_handle = rest_handle;
1468
1469 handle->url = GNUNET_strdup (rest_handle->url);
1470 if (handle->url[strlen (handle->url) - 1] == '/')
1471 handle->url[strlen (handle->url) - 1] = '\0';
1472 handle->timeout_task =
1473 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
1474 GNUNET_CONTAINER_DLL_insert (requests_head,
1475 requests_tail,
1476 handle);
1477 if (GNUNET_NO ==
1478 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1479 {
1480 cleanup_handle (handle);
1481 return GNUNET_NO;
1482 }
1483
1484 return GNUNET_YES;
1485}
1486
1487
1488/**
1489 * Entry point for the plugin.
1490 *
1491 * @param cls Config info
1492 * @return NULL on error, otherwise the plugin context
1493 */
1494void *
1495libgnunet_plugin_rest_reclaim_init (void *cls)
1496{
1497 static struct Plugin plugin;
1498 struct GNUNET_REST_Plugin *api;
1499
1500 cfg = cls;
1501 if (NULL != plugin.cfg)
1502 return NULL; /* can only initialize once! */
1503 memset (&plugin, 0, sizeof(struct Plugin));
1504 plugin.cfg = cfg;
1505 api = GNUNET_new (struct GNUNET_REST_Plugin);
1506 api->cls = &plugin;
1507 api->name = GNUNET_REST_API_NS_RECLAIM;
1508 api->process_request = &rest_identity_process_request;
1509 GNUNET_asprintf (&allow_methods,
1510 "%s, %s, %s, %s, %s",
1511 MHD_HTTP_METHOD_GET,
1512 MHD_HTTP_METHOD_POST,
1513 MHD_HTTP_METHOD_PUT,
1514 MHD_HTTP_METHOD_DELETE,
1515 MHD_HTTP_METHOD_OPTIONS);
1516 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1517 state = ID_REST_STATE_INIT;
1518 idp = GNUNET_RECLAIM_connect (cfg);
1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1520 _ ("Identity Provider REST API initialized\n"));
1521 return api;
1522}
1523
1524
1525/**
1526 * Exit point from the plugin.
1527 *
1528 * @param cls the plugin context (as returned by "init")
1529 * @return always NULL
1530 */
1531void *
1532libgnunet_plugin_rest_reclaim_done (void *cls)
1533{
1534 struct GNUNET_REST_Plugin *api = cls;
1535 struct Plugin *plugin = api->cls;
1536 struct RequestHandle *request;
1537 struct EgoEntry *ego_entry;
1538 struct EgoEntry *ego_tmp;
1539
1540 plugin->cfg = NULL;
1541 while (NULL != (request = requests_head))
1542 do_error (request);
1543 if (NULL != idp)
1544 GNUNET_RECLAIM_disconnect (idp);
1545 if (NULL != identity_handle)
1546 GNUNET_IDENTITY_disconnect (identity_handle);
1547 for (ego_entry = ego_head; NULL != ego_entry;)
1548 {
1549 ego_tmp = ego_entry;
1550 ego_entry = ego_entry->next;
1551 GNUNET_free (ego_tmp->identifier);
1552 GNUNET_free (ego_tmp->keystring);
1553 GNUNET_free (ego_tmp);
1554 }
1555
1556 GNUNET_free (allow_methods);
1557 GNUNET_free (api);
1558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1559 "Identity Provider REST plugin is finished\n");
1560 return NULL;
1561}
1562
1563
1564/* end of plugin_rest_reclaim.c */
diff --git a/src/reclaim/reclaim.conf b/src/reclaim/reclaim.conf
deleted file mode 100644
index 07facc232..000000000
--- a/src/reclaim/reclaim.conf
+++ /dev/null
@@ -1,22 +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_JSON_WEB_ALGORITHM = RS256
18OIDC_CLIENT_HMAC_SECRET = secret
19OIDC_DIR = $GNUNET_DATA_HOME/oidc
20OIDC_USERINFO_CONSUME_TIMEOUT = 5s
21JWT_SECRET = secret
22EXPIRATION_TIME = 1d
diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h
deleted file mode 100644
index 9d5118269..000000000
--- a/src/reclaim/reclaim.h
+++ /dev/null
@@ -1,600 +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 * The expiration interval of the attribute
49 */
50 uint64_t exp GNUNET_PACKED;
51
52 /**
53 * Unique identifier for this request (for key collisions).
54 */
55 uint32_t id GNUNET_PACKED;
56
57 /**
58 * The length of the attribute
59 */
60 uint16_t attr_len GNUNET_PACKED;
61
62 /**
63 * The length of the private key
64 */
65 uint16_t key_len GNUNET_PACKED;
66
67 /*
68 * followed by the zone private key
69 * followed by the serialized attribute */
70};
71
72
73/**
74 * Use to delete an identity attribute
75 */
76struct AttributeDeleteMessage
77{
78 /**
79 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
80 */
81 struct GNUNET_MessageHeader header;
82
83 /**
84 * Unique identifier for this request (for key collisions).
85 */
86 uint32_t id GNUNET_PACKED;
87
88 /**
89 * The length of the attribute
90 */
91 uint16_t attr_len GNUNET_PACKED;
92
93 /**
94 * The length of the private key
95 */
96 uint16_t key_len GNUNET_PACKED;
97
98 /* followed by the serialized attribute */
99};
100
101
102/**
103 * Attribute store/delete response message
104 */
105struct SuccessResultMessage
106{
107 /**
108 * Message header
109 */
110 struct GNUNET_MessageHeader header;
111
112 /**
113 * Unique identifier for this request (for key collisions).
114 */
115 uint32_t id GNUNET_PACKED;
116
117 /**
118 * #GNUNET_SYSERR on failure, #GNUNET_OK on success
119 */
120 int32_t op_result GNUNET_PACKED;
121};
122
123/**
124 * Attribute is returned from the idp.
125 */
126struct AttributeResultMessage
127{
128 /**
129 * Message header
130 */
131 struct GNUNET_MessageHeader header;
132
133 /**
134 * Unique identifier for this request (for key collisions).
135 */
136 uint32_t id GNUNET_PACKED;
137
138 /**
139 * Reserved (alignment)
140 */
141 uint16_t reserved GNUNET_PACKED;
142
143 /**
144 * Length of serialized attribute data
145 */
146 uint16_t attr_len GNUNET_PACKED;
147
148 /**
149 * Length of serialized credential data
150 */
151 uint16_t credential_len GNUNET_PACKED;
152
153 /**
154 * The length of the public key
155 */
156 uint16_t pkey_len GNUNET_PACKED;
157
158 /**
159 * followed by the public key key.
160 * followed by:
161 * serialized attribute data
162 */
163};
164
165/**
166 * Credential is returned from the idp.
167 */
168struct CredentialResultMessage
169{
170 /**
171 * Message header
172 */
173 struct GNUNET_MessageHeader header;
174
175 /**
176 * Unique identifier for this request (for key collisions).
177 */
178 uint32_t id GNUNET_PACKED;
179
180 /**
181 * Length of serialized attribute data
182 */
183 uint16_t credential_len GNUNET_PACKED;
184
185 /**
186 * The length of the public key
187 */
188 uint16_t key_len GNUNET_PACKED;
189
190 /**
191 * followed by the private key.
192 * followed by:
193 * serialized credential data
194 */
195};
196
197
198/**
199 * Start a attribute iteration for the given identity
200 */
201struct AttributeIterationStartMessage
202{
203 /**
204 * Message
205 */
206 struct GNUNET_MessageHeader header;
207
208 /**
209 * Unique identifier for this request (for key collisions).
210 */
211 uint32_t id GNUNET_PACKED;
212
213 /**
214 * Reserved (alignment)
215 */
216 uint16_t reserved GNUNET_PACKED;
217
218 /**
219 * The length of the private key
220 */
221 uint16_t key_len GNUNET_PACKED;
222
223 /**
224 * followed by the private key.
225 */
226};
227
228
229/**
230 * Ask for next result of attribute iteration for the given operation
231 */
232struct AttributeIterationNextMessage
233{
234 /**
235 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
236 */
237 struct GNUNET_MessageHeader header;
238
239 /**
240 * Unique identifier for this request (for key collisions).
241 */
242 uint32_t id GNUNET_PACKED;
243};
244
245
246/**
247 * Start a credential iteration for the given identity
248 */
249struct CredentialIterationStartMessage
250{
251 /**
252 * Message
253 */
254 struct GNUNET_MessageHeader header;
255
256 /**
257 * Unique identifier for this request (for key collisions).
258 */
259 uint32_t id GNUNET_PACKED;
260
261 /**
262 * Reserved (alignment)
263 */
264 uint16_t reserved GNUNET_PACKED;
265
266 /**
267 * The length of the private key
268 */
269 uint16_t key_len GNUNET_PACKED;
270
271 /**
272 * followed by the private key.
273 */
274};
275
276
277/**
278 * Ask for next result of credential iteration for the given operation
279 */
280struct CredentialIterationNextMessage
281{
282 /**
283 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
284 */
285 struct GNUNET_MessageHeader header;
286
287 /**
288 * Unique identifier for this request (for key collisions).
289 */
290 uint32_t id GNUNET_PACKED;
291};
292
293
294/**
295 * Stop credential iteration for the given operation
296 */
297struct CredentialIterationStopMessage
298{
299 /**
300 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP
301 */
302 struct GNUNET_MessageHeader header;
303
304 /**
305 * Unique identifier for this request (for key collisions).
306 */
307 uint32_t id GNUNET_PACKED;
308};
309
310
311/**
312 * Stop attribute iteration for the given operation
313 */
314struct AttributeIterationStopMessage
315{
316 /**
317 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP
318 */
319 struct GNUNET_MessageHeader header;
320
321 /**
322 * Unique identifier for this request (for key collisions).
323 */
324 uint32_t id GNUNET_PACKED;
325};
326
327/**
328 * Start a ticket iteration for the given identity
329 */
330struct TicketIterationStartMessage
331{
332 /**
333 * Message
334 */
335 struct GNUNET_MessageHeader header;
336
337 /**
338 * Unique identifier for this request (for key collisions).
339 */
340 uint32_t id GNUNET_PACKED;
341
342 /**
343 * Reserved (alignment)
344 */
345 uint16_t reserved GNUNET_PACKED;
346
347 /**
348 * The length of the private key
349 */
350 uint16_t key_len GNUNET_PACKED;
351
352 /**
353 * followed by the private key.
354 */
355};
356
357
358/**
359 * Ask for next result of ticket iteration for the given operation
360 */
361struct TicketIterationNextMessage
362{
363 /**
364 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT
365 */
366 struct GNUNET_MessageHeader header;
367
368 /**
369 * Unique identifier for this request (for key collisions).
370 */
371 uint32_t id GNUNET_PACKED;
372};
373
374
375/**
376 * Stop ticket iteration for the given operation
377 */
378struct TicketIterationStopMessage
379{
380 /**
381 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP
382 */
383 struct GNUNET_MessageHeader header;
384
385 /**
386 * Unique identifier for this request (for key collisions).
387 */
388 uint32_t id GNUNET_PACKED;
389};
390
391
392/**
393 * Ticket issue message
394 */
395struct IssueTicketMessage
396{
397 /**
398 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET
399 */
400 struct GNUNET_MessageHeader header;
401
402 /**
403 * Unique identifier for this request (for key collisions).
404 */
405 uint32_t id GNUNET_PACKED;
406
407 /**
408 * Reserved (alignment)
409 */
410 uint16_t reserved GNUNET_PACKED;
411
412 /**
413 * length of serialized attribute list
414 */
415 uint16_t attr_len GNUNET_PACKED;
416
417 /**
418 * The length of the identity private key
419 */
420 uint16_t key_len GNUNET_PACKED;
421
422 /**
423 * The length of the relying party public key
424 */
425 uint16_t pkey_len GNUNET_PACKED;
426
427 /**
428 * Followed by the private key.
429 * Followed by the public key.
430 * Followed by a serialized attribute list
431 */
432};
433
434/**
435 * Ticket revoke message
436 */
437struct RevokeTicketMessage
438{
439 /**
440 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET
441 */
442 struct GNUNET_MessageHeader header;
443
444 /**
445 * Unique identifier for this request (for key collisions).
446 */
447 uint32_t id GNUNET_PACKED;
448
449 /**
450 * The length of the private key
451 */
452 uint16_t key_len GNUNET_PACKED;
453
454 /**
455 * The length of the ticket
456 */
457 uint16_t tkt_len GNUNET_PACKED;
458
459 /**
460 * Followed by the serialized ticket.
461 * Followed by the private key.
462 * Followed by a serialized attribute list
463 */
464};
465
466/**
467 * Ticket revoke message
468 */
469struct RevokeTicketResultMessage
470{
471 /**
472 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
473 */
474 struct GNUNET_MessageHeader header;
475
476 /**
477 * Unique identifier for this request (for key collisions).
478 */
479 uint32_t id GNUNET_PACKED;
480
481 /**
482 * Revocation result
483 */
484 uint32_t success GNUNET_PACKED;
485};
486
487
488/**
489 * Ticket result message
490 */
491struct TicketResultMessage
492{
493 /**
494 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
495 */
496 struct GNUNET_MessageHeader header;
497
498 /**
499 * Unique identifier for this request (for key collisions).
500 */
501 uint32_t id GNUNET_PACKED;
502
503 /**
504 * Ticket length
505 */
506 uint16_t tkt_len GNUNET_PACKED;
507
508 /**
509 * Length of new presentations created
510 */
511 uint16_t presentations_len GNUNET_PACKED;
512
513 /*
514 * Followed by the serialized ticket
515 * Followed by the serialized GNUNET_RECLAIM_PresentationList
516 */
517};
518
519/**
520 * Ticket consume message
521 */
522struct ConsumeTicketMessage
523{
524 /**
525 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET
526 */
527 struct GNUNET_MessageHeader header;
528
529 /**
530 * Unique identifier for this request (for key collisions).
531 */
532 uint32_t id GNUNET_PACKED;
533
534 /**
535 * The length of the private key
536 */
537 uint16_t key_len GNUNET_PACKED;
538
539 /**
540 * The length of the ticket
541 */
542 uint16_t tkt_len GNUNET_PACKED;
543
544 /**
545 * Followed by the private key.
546 * Followed by the serialized ticket.
547 */
548};
549
550/**
551 * Attribute list is returned from the idp.
552 */
553struct ConsumeTicketResultMessage
554{
555 /**
556 * Message header
557 */
558 struct GNUNET_MessageHeader header;
559
560 /**
561 * Unique identifier for this request (for key collisions).
562 */
563 uint32_t id GNUNET_PACKED;
564
565 /**
566 * Result
567 */
568 uint32_t result GNUNET_PACKED;
569
570 /**
571 * Reserved (alignment)
572 */
573 uint16_t reserved GNUNET_PACKED;
574
575 /**
576 * Length of serialized attribute data
577 */
578 uint16_t attrs_len GNUNET_PACKED;
579
580 /**
581 * Length of presentation data
582 */
583 uint16_t presentations_len;
584
585 /**
586 * The length of the private key
587 */
588 uint16_t key_len GNUNET_PACKED;
589
590 /**
591 * Followed by the private key.
592 * followed by:
593 * serialized attributes data
594 */
595};
596
597
598GNUNET_NETWORK_STRUCT_END
599
600#endif
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
deleted file mode 100644
index e9a34dd95..000000000
--- a/src/reclaim/reclaim_api.c
+++ /dev/null
@@ -1,1813 +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_protocols.h"
30#include "gnunet_reclaim_lib.h"
31#include "gnunet_reclaim_service.h"
32#include "reclaim.h"
33
34#define LOG(kind, ...) GNUNET_log_from (kind, "reclaim-api", __VA_ARGS__)
35
36
37/**
38 * Handle for an operation with the service.
39 */
40struct GNUNET_RECLAIM_Operation
41{
42 /**
43 * Main handle.
44 */
45 struct GNUNET_RECLAIM_Handle *h;
46
47 /**
48 * We keep operations in a DLL.
49 */
50 struct GNUNET_RECLAIM_Operation *next;
51
52 /**
53 * We keep operations in a DLL.
54 */
55 struct GNUNET_RECLAIM_Operation *prev;
56
57 /**
58 * Message to send to the service.
59 * Allocated at the end of this struct.
60 */
61 const struct GNUNET_MessageHeader *msg;
62
63 /**
64 * Continuation to invoke after attribute store call
65 */
66 GNUNET_RECLAIM_ContinuationWithStatus as_cb;
67
68 /**
69 * Attribute result callback
70 */
71 GNUNET_RECLAIM_AttributeResult ar_cb;
72
73 /**
74 * Attribute result callback
75 */
76 GNUNET_RECLAIM_AttributeTicketResult atr_cb;
77
78 /**
79 * Credential result callback
80 */
81 GNUNET_RECLAIM_CredentialResult at_cb;
82
83 /**
84 * Revocation result callback
85 */
86 GNUNET_RECLAIM_ContinuationWithStatus rvk_cb;
87
88 /**
89 * Ticket result callback
90 */
91 GNUNET_RECLAIM_TicketCallback tr_cb;
92
93 /**
94 * Ticket issue result callback
95 */
96 GNUNET_RECLAIM_IssueTicketCallback ti_cb;
97
98 /**
99 * Envelope with the message for this queue entry.
100 */
101 struct GNUNET_MQ_Envelope *env;
102
103 /**
104 * request id
105 */
106 uint32_t r_id;
107
108 /**
109 * Closure for @e cont or @e cb.
110 */
111 void *cls;
112};
113
114
115/**
116 * Handle for a ticket iterator operation
117 */
118struct GNUNET_RECLAIM_TicketIterator
119{
120 /**
121 * Kept in a DLL.
122 */
123 struct GNUNET_RECLAIM_TicketIterator *next;
124
125 /**
126 * Kept in a DLL.
127 */
128 struct GNUNET_RECLAIM_TicketIterator *prev;
129
130 /**
131 * Main handle to access the idp.
132 */
133 struct GNUNET_RECLAIM_Handle *h;
134
135 /**
136 * Function to call on completion.
137 */
138 GNUNET_SCHEDULER_TaskCallback finish_cb;
139
140 /**
141 * Closure for @e finish_cb.
142 */
143 void *finish_cb_cls;
144
145 /**
146 * The continuation to call with the results
147 */
148 GNUNET_RECLAIM_TicketCallback tr_cb;
149
150 /**
151 * Closure for @e tr_cb.
152 */
153 void *cls;
154
155 /**
156 * Function to call on errors.
157 */
158 GNUNET_SCHEDULER_TaskCallback error_cb;
159
160 /**
161 * Closure for @e error_cb.
162 */
163 void *error_cb_cls;
164
165 /**
166 * Envelope of the message to send to the service, if not yet
167 * sent.
168 */
169 struct GNUNET_MQ_Envelope *env;
170
171 /**
172 * The operation id this zone iteration operation has
173 */
174 uint32_t r_id;
175};
176
177
178/**
179 * Handle for a attribute iterator operation
180 */
181struct GNUNET_RECLAIM_AttributeIterator
182{
183 /**
184 * Kept in a DLL.
185 */
186 struct GNUNET_RECLAIM_AttributeIterator *next;
187
188 /**
189 * Kept in a DLL.
190 */
191 struct GNUNET_RECLAIM_AttributeIterator *prev;
192
193 /**
194 * Main handle to access the service.
195 */
196 struct GNUNET_RECLAIM_Handle *h;
197
198 /**
199 * Function to call on completion.
200 */
201 GNUNET_SCHEDULER_TaskCallback finish_cb;
202
203 /**
204 * Closure for @e finish_cb.
205 */
206 void *finish_cb_cls;
207
208 /**
209 * The continuation to call with the results
210 */
211 GNUNET_RECLAIM_AttributeResult proc;
212
213 /**
214 * Closure for @e proc.
215 */
216 void *proc_cls;
217
218 /**
219 * Function to call on errors.
220 */
221 GNUNET_SCHEDULER_TaskCallback error_cb;
222
223 /**
224 * Closure for @e error_cb.
225 */
226 void *error_cb_cls;
227
228 /**
229 * Envelope of the message to send to the service, if not yet
230 * sent.
231 */
232 struct GNUNET_MQ_Envelope *env;
233
234 /**
235 * Private key of the zone.
236 */
237 struct GNUNET_CRYPTO_PrivateKey identity;
238
239 /**
240 * The operation id this zone iteration operation has
241 */
242 uint32_t r_id;
243};
244
245/**
246 * Handle for a credential iterator operation
247 */
248struct GNUNET_RECLAIM_CredentialIterator
249{
250 /**
251 * Kept in a DLL.
252 */
253 struct GNUNET_RECLAIM_CredentialIterator *next;
254
255 /**
256 * Kept in a DLL.
257 */
258 struct GNUNET_RECLAIM_CredentialIterator *prev;
259
260 /**
261 * Main handle to access the service.
262 */
263 struct GNUNET_RECLAIM_Handle *h;
264
265 /**
266 * Function to call on completion.
267 */
268 GNUNET_SCHEDULER_TaskCallback finish_cb;
269
270 /**
271 * Closure for @e finish_cb.
272 */
273 void *finish_cb_cls;
274
275 /**
276 * The continuation to call with the results
277 */
278 GNUNET_RECLAIM_CredentialResult proc;
279
280 /**
281 * Closure for @e proc.
282 */
283 void *proc_cls;
284
285 /**
286 * Function to call on errors.
287 */
288 GNUNET_SCHEDULER_TaskCallback error_cb;
289
290 /**
291 * Closure for @e error_cb.
292 */
293 void *error_cb_cls;
294
295 /**
296 * Envelope of the message to send to the service, if not yet
297 * sent.
298 */
299 struct GNUNET_MQ_Envelope *env;
300
301 /**
302 * Private key of the zone.
303 */
304 struct GNUNET_CRYPTO_PrivateKey identity;
305
306 /**
307 * The operation id this zone iteration operation has
308 */
309 uint32_t r_id;
310};
311
312
313/**
314 * Handle to the service.
315 */
316struct GNUNET_RECLAIM_Handle
317{
318 /**
319 * Configuration to use.
320 */
321 const struct GNUNET_CONFIGURATION_Handle *cfg;
322
323 /**
324 * Socket (if available).
325 */
326 struct GNUNET_CLIENT_Connection *client;
327
328 /**
329 * Closure for 'cb'.
330 */
331 void *cb_cls;
332
333 /**
334 * Head of active operations.
335 */
336 struct GNUNET_RECLAIM_Operation *op_head;
337
338 /**
339 * Tail of active operations.
340 */
341 struct GNUNET_RECLAIM_Operation *op_tail;
342
343 /**
344 * Head of active iterations
345 */
346 struct GNUNET_RECLAIM_AttributeIterator *it_head;
347
348 /**
349 * Tail of active iterations
350 */
351 struct GNUNET_RECLAIM_AttributeIterator *it_tail;
352
353 /**
354 * Head of active iterations
355 */
356 struct GNUNET_RECLAIM_CredentialIterator *ait_head;
357
358 /**
359 * Tail of active iterations
360 */
361 struct GNUNET_RECLAIM_CredentialIterator *ait_tail;
362
363 /**
364 * Head of active iterations
365 */
366 struct GNUNET_RECLAIM_TicketIterator *ticket_it_head;
367
368 /**
369 * Tail of active iterations
370 */
371 struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail;
372
373 /**
374 * Currently pending transmission request, or NULL for none.
375 */
376 struct GNUNET_CLIENT_TransmitHandle *th;
377
378 /**
379 * Task doing exponential back-off trying to reconnect.
380 */
381 struct GNUNET_SCHEDULER_Task *reconnect_task;
382
383 /**
384 * Time for next connect retry.
385 */
386 struct GNUNET_TIME_Relative reconnect_backoff;
387
388 /**
389 * Connection to service (if available).
390 */
391 struct GNUNET_MQ_Handle *mq;
392
393 /**
394 * Request Id generator. Incremented by one for each request.
395 */
396 uint32_t r_id_gen;
397
398 /**
399 * Are we polling for incoming messages right now?
400 */
401 int in_receive;
402};
403
404
405/**
406 * Try again to connect to the service.
407 *
408 * @param h handle to the reclaim service.
409 */
410static void
411reconnect (struct GNUNET_RECLAIM_Handle *h);
412
413
414/**
415 * Reconnect
416 *
417 * @param cls the handle
418 */
419static void
420reconnect_task (void *cls)
421{
422 struct GNUNET_RECLAIM_Handle *handle = cls;
423
424 handle->reconnect_task = NULL;
425 reconnect (handle);
426}
427
428
429/**
430 * Disconnect from service and then reconnect.
431 *
432 * @param handle our service
433 */
434static void
435force_reconnect (struct GNUNET_RECLAIM_Handle *handle)
436{
437 GNUNET_MQ_destroy (handle->mq);
438 handle->mq = NULL;
439 handle->reconnect_backoff =
440 GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
441 handle->reconnect_task =
442 GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
443 &reconnect_task,
444 handle);
445}
446
447
448/**
449 * Free @a it.
450 *
451 * @param it entry to free
452 */
453static void
454free_it (struct GNUNET_RECLAIM_AttributeIterator *it)
455{
456 struct GNUNET_RECLAIM_Handle *h = it->h;
457
458 GNUNET_CONTAINER_DLL_remove (h->it_head, h->it_tail, it);
459 if (NULL != it->env)
460 GNUNET_MQ_discard (it->env);
461 GNUNET_free (it);
462}
463
464
465/**
466 * Free @a it.
467 *
468 * @param ait entry to free
469 */
470static void
471free_ait (struct GNUNET_RECLAIM_CredentialIterator *ait)
472{
473 struct GNUNET_RECLAIM_Handle *h = ait->h;
474
475 GNUNET_CONTAINER_DLL_remove (h->ait_head, h->ait_tail, ait);
476 if (NULL != ait->env)
477 GNUNET_MQ_discard (ait->env);
478 GNUNET_free (ait);
479}
480
481
482/**
483 * Free @a op
484 *
485 * @param op the operation to free
486 */
487static void
488free_op (struct GNUNET_RECLAIM_Operation *op)
489{
490 if (NULL == op)
491 return;
492 if (NULL != op->env)
493 GNUNET_MQ_discard (op->env);
494 GNUNET_free (op);
495}
496
497
498/**
499 * Generic error handler, called with the appropriate error code and
500 * the same closure specified at the creation of the message queue.
501 * Not every message queue implementation supports an error handler.
502 *
503 * @param cls closure with the `struct GNUNET_GNS_Handle *`
504 * @param error error code
505 */
506static void
507mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
508{
509 struct GNUNET_RECLAIM_Handle *handle = cls;
510
511 force_reconnect (handle);
512}
513
514
515/**
516 * Handle an incoming message of type
517 * #GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE
518 *
519 * @param cls
520 * @param msg the message we received
521 */
522static void
523handle_success_response (void *cls, const struct SuccessResultMessage *msg)
524{
525 struct GNUNET_RECLAIM_Handle *h = cls;
526 struct GNUNET_RECLAIM_Operation *op;
527 uint32_t r_id = ntohl (msg->id);
528 int res;
529 const char *emsg;
530
531 for (op = h->op_head; NULL != op; op = op->next)
532 if (op->r_id == r_id)
533 break;
534 if (NULL == op)
535 return;
536
537 res = ntohl (msg->op_result);
538 LOG (GNUNET_ERROR_TYPE_DEBUG,
539 "Received SUCCESS_RESPONSE with result %d\n",
540 res);
541
542 /* TODO: add actual error message to response... */
543 if (GNUNET_SYSERR == res)
544 emsg = _ ("failed to store record\n");
545 else
546 emsg = NULL;
547 if (NULL != op->as_cb)
548 op->as_cb (op->cls, res, emsg);
549 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
550 free_op (op);
551}
552
553
554/**
555 * Handle an incoming message of type
556 * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
557 *
558 * @param cls
559 * @param msg the message we received
560 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
561 */
562static int
563check_consume_ticket_result (void *cls,
564 const struct ConsumeTicketResultMessage *msg)
565{
566 size_t msg_len;
567 size_t attrs_len;
568 size_t pl_len;
569 size_t key_len;
570
571 msg_len = ntohs (msg->header.size);
572 attrs_len = ntohs (msg->attrs_len);
573 key_len = ntohs (msg->key_len);
574 pl_len = ntohs (msg->presentations_len);
575 if (msg_len != sizeof(*msg) + attrs_len + pl_len + key_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_CRYPTO_PublicKey identity;
596 struct GNUNET_RECLAIM_Handle *h = cls;
597 struct GNUNET_RECLAIM_Operation *op;
598 size_t attrs_len;
599 size_t pl_len;
600 size_t key_len;
601 size_t read;
602 uint32_t r_id = ntohl (msg->id);
603 char *read_ptr;
604
605 attrs_len = ntohs (msg->attrs_len);
606 key_len = ntohs (msg->key_len);
607 pl_len = ntohs (msg->presentations_len);
608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n");
609
610
611 for (op = h->op_head; NULL != op; op = op->next)
612 if (op->r_id == r_id)
613 break;
614 if (NULL == op)
615 return;
616
617 {
618 struct GNUNET_RECLAIM_AttributeList *attrs;
619 struct GNUNET_RECLAIM_AttributeListEntry *le;
620 struct GNUNET_RECLAIM_PresentationList *pl;
621 struct GNUNET_RECLAIM_PresentationListEntry *ple;
622 read_ptr = (char *) &msg[1];
623 GNUNET_assert (GNUNET_SYSERR !=
624 GNUNET_CRYPTO_read_public_key_from_buffer (read_ptr,
625 key_len,
626 &identity,
627 &read));
628 read_ptr += read;
629 attrs =
630 GNUNET_RECLAIM_attribute_list_deserialize (read_ptr, attrs_len);
631 read_ptr += attrs_len;
632 pl = GNUNET_RECLAIM_presentation_list_deserialize (read_ptr, pl_len);
633 if (NULL != op->atr_cb)
634 {
635 if (NULL == attrs)
636 {
637 op->atr_cb (op->cls, &identity, NULL, NULL);
638 }
639 else
640 {
641 for (le = attrs->list_head; NULL != le; le = le->next)
642 {
643 if (GNUNET_NO ==
644 GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
645 {
646 for (ple = pl->list_head; NULL != ple; ple = ple->next)
647 {
648 if (GNUNET_YES ==
649 GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
650 &ple->presentation->credential_id))
651 {
652 op->atr_cb (op->cls, &identity,
653 le->attribute, ple->presentation);
654 break;
655 }
656
657 }
658 }
659 else // No credentials
660 {
661 op->atr_cb (op->cls, &identity,
662 le->attribute, NULL);
663 }
664 }
665 }
666 op->atr_cb (op->cls, NULL, NULL, NULL);
667 }
668 if (NULL != attrs)
669 GNUNET_RECLAIM_attribute_list_destroy (attrs);
670 if (NULL != pl)
671 GNUNET_RECLAIM_presentation_list_destroy (pl);
672 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
673 free_op (op);
674 return;
675 }
676 GNUNET_assert (0);
677}
678
679
680/**
681 * Handle an incoming message of type
682 * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
683 *
684 * @param cls
685 * @param msg the message we received
686 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
687 */
688static int
689check_attribute_result (void *cls, const struct AttributeResultMessage *msg)
690{
691 size_t msg_len;
692 size_t attr_len;
693 size_t key_len;
694
695 msg_len = ntohs (msg->header.size);
696 attr_len = ntohs (msg->attr_len);
697 key_len = ntohs (msg->pkey_len);
698 if (msg_len != sizeof(*msg) + attr_len + key_len)
699 {
700 GNUNET_break (0);
701 return GNUNET_SYSERR;
702 }
703 return GNUNET_OK;
704}
705
706
707/**
708 * Handle an incoming message of type
709 * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
710 *
711 * @param cls
712 * @param msg the message we received
713 */
714static void
715handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
716{
717 static struct GNUNET_CRYPTO_PublicKey identity;
718 struct GNUNET_RECLAIM_Handle *h = cls;
719 struct GNUNET_RECLAIM_AttributeIterator *it;
720 struct GNUNET_RECLAIM_Operation *op;
721 size_t attr_len;
722 size_t key_len;
723 size_t read;
724 uint32_t r_id = ntohl (msg->id);
725 char *buf;
726
727 attr_len = ntohs (msg->attr_len);
728 key_len = ntohs (msg->pkey_len);
729 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attribute result.\n");
730
731 for (it = h->it_head; NULL != it; it = it->next)
732 if (it->r_id == r_id)
733 break;
734 for (op = h->op_head; NULL != op; op = op->next)
735 if (op->r_id == r_id)
736 break;
737 if ((NULL == it) && (NULL == op))
738 return;
739
740 buf = (char *) &msg[1];
741 if (0 == key_len)
742 {
743 if ((NULL == it) && (NULL == op))
744 {
745 GNUNET_break (0);
746 force_reconnect (h);
747 return;
748 }
749 if (NULL != it)
750 {
751 if (NULL != it->finish_cb)
752 it->finish_cb (it->finish_cb_cls);
753 free_it (it);
754 }
755 if (NULL != op)
756 {
757 if (NULL != op->ar_cb)
758 op->ar_cb (op->cls, NULL, NULL);
759 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
760 free_op (op);
761 }
762 return;
763 }
764
765 {
766 struct GNUNET_RECLAIM_Attribute *attr;
767 GNUNET_assert (GNUNET_SYSERR !=
768 GNUNET_CRYPTO_read_public_key_from_buffer (buf,
769 key_len,
770 &identity,
771 &read));
772 buf += read;
773 GNUNET_RECLAIM_attribute_deserialize (buf, attr_len, &attr);
774 if (NULL != it)
775 {
776 if (NULL != it->proc)
777 it->proc (it->proc_cls, &identity, attr);
778 }
779 else if (NULL != op)
780 {
781 if (NULL != op->ar_cb)
782 op->ar_cb (op->cls, &identity, attr);
783 }
784 GNUNET_free (attr);
785 return;
786 }
787 GNUNET_assert (0);
788}
789
790
791/**
792 * Handle an incoming message of type
793 * #GNUNET_MESSAGE_TYPE_RECLAIM_credential_RESULT
794 *
795 * @param cls
796 * @param msg the message we received
797 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
798 */
799static int
800check_credential_result (void *cls, const struct CredentialResultMessage *msg)
801{
802 size_t msg_len;
803 size_t cred_len;
804 size_t key_len;
805
806 msg_len = ntohs (msg->header.size);
807 cred_len = ntohs (msg->credential_len);
808 key_len = ntohs (msg->key_len);
809 if (msg_len != sizeof(*msg) + cred_len + key_len)
810 {
811 GNUNET_break (0);
812 return GNUNET_SYSERR;
813 }
814 return GNUNET_OK;
815}
816
817
818/**
819 * Handle an incoming message of type
820 * #GNUNET_MESSAGE_TYPE_RECLAIM_credential_RESULT
821 *
822 * @param cls
823 * @param msg the message we received
824 */
825static void
826handle_credential_result (void *cls, const struct
827 CredentialResultMessage *msg)
828{
829 struct GNUNET_CRYPTO_PublicKey identity;
830 struct GNUNET_RECLAIM_Handle *h = cls;
831 struct GNUNET_RECLAIM_CredentialIterator *it;
832 struct GNUNET_RECLAIM_Operation *op;
833 size_t att_len;
834 size_t key_len;
835 size_t read;
836 uint32_t r_id = ntohl (msg->id);
837 char *buf;
838
839 key_len = ntohs (msg->key_len);
840 att_len = ntohs (msg->credential_len);
841 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing credential result.\n");
842
843
844 for (it = h->ait_head; NULL != it; it = it->next)
845 if (it->r_id == r_id)
846 break;
847 for (op = h->op_head; NULL != op; op = op->next)
848 if (op->r_id == r_id)
849 break;
850 if ((NULL == it) && (NULL == op))
851 return;
852
853 buf = (char *) &msg[1];
854 if (0 < key_len)
855 {
856 GNUNET_assert (GNUNET_SYSERR !=
857 GNUNET_CRYPTO_read_public_key_from_buffer (buf,
858 key_len,
859 &identity,
860 &read));
861 buf += read;
862 }
863 if (0 == key_len)
864 {
865 if ((NULL == it) && (NULL == op))
866 {
867 GNUNET_break (0);
868 force_reconnect (h);
869 return;
870 }
871 if (NULL != it)
872 {
873 if (NULL != it->finish_cb)
874 it->finish_cb (it->finish_cb_cls);
875 free_ait (it);
876 }
877 if (NULL != op)
878 {
879 if (NULL != op->at_cb)
880 op->at_cb (op->cls, NULL, NULL);
881 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
882 free_op (op);
883 }
884 return;
885 }
886
887 {
888 struct GNUNET_RECLAIM_Credential *att;
889 att = GNUNET_RECLAIM_credential_deserialize (buf, att_len);
890
891 if (NULL != it)
892 {
893 if (NULL != it->proc)
894 it->proc (it->proc_cls, &identity, att);
895 }
896 else if (NULL != op)
897 {
898 if (NULL != op->at_cb)
899 op->at_cb (op->cls, &identity, att);
900 }
901 GNUNET_free (att);
902 return;
903 }
904 GNUNET_assert (0);
905}
906
907
908/**
909 * Handle an incoming message of type
910 * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
911 *
912 * @param cls
913 * @param msg the message we received
914 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
915 */
916static int
917check_ticket_result (void *cls, const struct TicketResultMessage *msg)
918{
919 size_t msg_len;
920 size_t pres_len;
921 size_t tkt_len;
922
923 msg_len = ntohs (msg->header.size);
924 pres_len = ntohs (msg->presentations_len);
925 tkt_len = ntohs (msg->tkt_len);
926 if (msg_len != sizeof(*msg) + pres_len + tkt_len)
927 {
928 GNUNET_break (0);
929 return GNUNET_SYSERR;
930 }
931 return GNUNET_OK;
932}
933
934
935/**
936 * Handle an incoming message of type
937 * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
938 *
939 * @param cls
940 * @param msg the message we received
941 */
942static void
943handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
944{
945 struct GNUNET_RECLAIM_Handle *handle = cls;
946 struct GNUNET_RECLAIM_Operation *op;
947 struct GNUNET_RECLAIM_TicketIterator *it;
948 struct GNUNET_RECLAIM_PresentationList *presentation;
949 uint32_t r_id = ntohl (msg->id);
950 struct GNUNET_RECLAIM_Ticket ticket;
951 size_t pres_len;
952 size_t tkt_len;
953 size_t tb_read;
954 char *buf;
955
956 tkt_len = ntohs (msg->tkt_len);
957 pres_len = ntohs (msg->presentations_len);
958 for (op = handle->op_head; NULL != op; op = op->next)
959 if (op->r_id == r_id)
960 break;
961 for (it = handle->ticket_it_head; NULL != it; it = it->next)
962 if (it->r_id == r_id)
963 break;
964 if ((NULL == op) && (NULL == it))
965 return;
966 buf = (char*) &msg[1];
967 GNUNET_assert (GNUNET_SYSERR !=
968 GNUNET_RECLAIM_read_ticket_from_buffer (buf,
969 tkt_len,
970 &ticket,
971 &tb_read));
972 buf += tb_read;
973 if (NULL != op)
974 {
975 if (0 < pres_len)
976 presentation = GNUNET_RECLAIM_presentation_list_deserialize (
977 buf,
978 pres_len);
979 GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
980 if (0 == tb_read)
981 {
982 if (NULL != op->ti_cb)
983 op->ti_cb (op->cls, NULL, NULL);
984 }
985 else
986 {
987 if (NULL != op->ti_cb)
988 op->ti_cb (op->cls,
989 &ticket,
990 (0 < pres_len) ? presentation : NULL);
991 }
992 if (0 < pres_len)
993 GNUNET_RECLAIM_presentation_list_destroy (presentation);
994 free_op (op);
995 return;
996 }
997 else if (NULL != it)
998 {
999 if (0 == tkt_len)
1000 {
1001 GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
1002 handle->ticket_it_tail,
1003 it);
1004 it->finish_cb (it->finish_cb_cls);
1005 GNUNET_free (it);
1006 }
1007 else
1008 {
1009 if (NULL != it->tr_cb)
1010 it->tr_cb (it->cls, &ticket);
1011 }
1012 return;
1013 }
1014 GNUNET_break (0);
1015}
1016
1017
1018/**
1019 * Handle an incoming message of type
1020 * #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
1021 *
1022 * @param cls
1023 * @param msg the message we received
1024 */
1025static void
1026handle_revoke_ticket_result (void *cls,
1027 const struct RevokeTicketResultMessage *msg)
1028{
1029 struct GNUNET_RECLAIM_Handle *h = cls;
1030 struct GNUNET_RECLAIM_Operation *op;
1031 uint32_t r_id = ntohl (msg->id);
1032 int32_t success;
1033
1034 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing revocation result.\n");
1035
1036
1037 for (op = h->op_head; NULL != op; op = op->next)
1038 if (op->r_id == r_id)
1039 break;
1040 if (NULL == op)
1041 return;
1042 success = ntohl (msg->success);
1043 {
1044 if (NULL != op->rvk_cb)
1045 {
1046 op->rvk_cb (op->cls, success, NULL);
1047 }
1048 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
1049 free_op (op);
1050 return;
1051 }
1052 GNUNET_assert (0);
1053}
1054
1055
1056/**
1057 * Try again to connect to the service.
1058 *
1059 * @param h handle to the reclaim service.
1060 */
1061static void
1062reconnect (struct GNUNET_RECLAIM_Handle *h)
1063{
1064 struct GNUNET_MQ_MessageHandler handlers[] =
1065 { GNUNET_MQ_hd_fixed_size (success_response,
1066 GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE,
1067 struct SuccessResultMessage,
1068 h),
1069 GNUNET_MQ_hd_var_size (attribute_result,
1070 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
1071 struct AttributeResultMessage,
1072 h),
1073 GNUNET_MQ_hd_var_size (credential_result,
1074 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT,
1075 struct CredentialResultMessage,
1076 h),
1077 GNUNET_MQ_hd_var_size (ticket_result,
1078 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
1079 struct TicketResultMessage,
1080 h),
1081 GNUNET_MQ_hd_var_size (consume_ticket_result,
1082 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
1083 struct ConsumeTicketResultMessage,
1084 h),
1085 GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
1086 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT,
1087 struct RevokeTicketResultMessage,
1088 h),
1089 GNUNET_MQ_handler_end () };
1090 struct GNUNET_RECLAIM_Operation *op;
1091
1092 GNUNET_assert (NULL == h->mq);
1093 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to reclaim service.\n");
1094
1095 h->mq =
1096 GNUNET_CLIENT_connect (h->cfg, "reclaim", handlers, &mq_error_handler, h);
1097 if (NULL == h->mq)
1098 return;
1099 for (op = h->op_head; NULL != op; op = op->next)
1100 GNUNET_MQ_send_copy (h->mq, op->env);
1101}
1102
1103
1104/**
1105 * Connect to the reclaim service.
1106 *
1107 * @param cfg the configuration to use
1108 * @return handle to use
1109 */
1110struct GNUNET_RECLAIM_Handle *
1111GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
1112{
1113 struct GNUNET_RECLAIM_Handle *h;
1114
1115 h = GNUNET_new (struct GNUNET_RECLAIM_Handle);
1116 h->cfg = cfg;
1117 reconnect (h);
1118 if (NULL == h->mq)
1119 {
1120 GNUNET_free (h);
1121 return NULL;
1122 }
1123 return h;
1124}
1125
1126
1127void
1128GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op)
1129{
1130 struct GNUNET_RECLAIM_Handle *h = op->h;
1131
1132 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
1133 free_op (op);
1134}
1135
1136
1137/**
1138 * Disconnect from service
1139 *
1140 * @param h handle to destroy
1141 */
1142void
1143GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h)
1144{
1145 GNUNET_assert (NULL != h);
1146 if (NULL != h->mq)
1147 {
1148 GNUNET_MQ_destroy (h->mq);
1149 h->mq = NULL;
1150 }
1151 if (NULL != h->reconnect_task)
1152 {
1153 GNUNET_SCHEDULER_cancel (h->reconnect_task);
1154 h->reconnect_task = NULL;
1155 }
1156 GNUNET_assert (NULL == h->op_head);
1157 GNUNET_free (h);
1158}
1159
1160
1161struct GNUNET_RECLAIM_Operation *
1162GNUNET_RECLAIM_attribute_store (
1163 struct GNUNET_RECLAIM_Handle *h,
1164 const struct GNUNET_CRYPTO_PrivateKey *pkey,
1165 const struct GNUNET_RECLAIM_Attribute *attr,
1166 const struct GNUNET_TIME_Relative *exp_interval,
1167 GNUNET_RECLAIM_ContinuationWithStatus cont,
1168 void *cont_cls)
1169{
1170 struct GNUNET_RECLAIM_Operation *op;
1171 struct AttributeStoreMessage *sam;
1172 size_t attr_len;
1173 size_t key_len;
1174 ssize_t written;
1175 char *buf;
1176
1177 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1178 op->h = h;
1179 op->as_cb = cont;
1180 op->cls = cont_cls;
1181 op->r_id = h->r_id_gen++;
1182 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1183 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
1184 attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (attr);
1185 op->env = GNUNET_MQ_msg_extra (sam,
1186 attr_len + key_len,
1187 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE);
1188 sam->key_len = htons (key_len);
1189 buf = (char *) &sam[1];
1190 written = GNUNET_CRYPTO_write_private_key_to_buffer (pkey, buf, key_len);
1191 GNUNET_assert (0 < written);
1192 buf += written;
1193 sam->id = htonl (op->r_id);
1194 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1195
1196 GNUNET_RECLAIM_attribute_serialize (attr, buf);
1197
1198 sam->attr_len = htons (attr_len);
1199 if (NULL != h->mq)
1200 GNUNET_MQ_send_copy (h->mq, op->env);
1201 return op;
1202}
1203
1204
1205struct GNUNET_RECLAIM_Operation *
1206GNUNET_RECLAIM_attribute_delete (
1207 struct GNUNET_RECLAIM_Handle *h,
1208 const struct GNUNET_CRYPTO_PrivateKey *pkey,
1209 const struct GNUNET_RECLAIM_Attribute *attr,
1210 GNUNET_RECLAIM_ContinuationWithStatus cont,
1211 void *cont_cls)
1212{
1213 struct GNUNET_RECLAIM_Operation *op;
1214 struct AttributeDeleteMessage *dam;
1215 size_t attr_len;
1216 size_t key_len;
1217 ssize_t written;
1218 char *buf;
1219
1220 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1221 op->h = h;
1222 op->as_cb = cont;
1223 op->cls = cont_cls;
1224 op->r_id = h->r_id_gen++;
1225 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1226 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
1227 attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (attr);
1228 op->env = GNUNET_MQ_msg_extra (dam,
1229 attr_len + key_len,
1230 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE);
1231 dam->key_len = htons (key_len);
1232 buf = (char *) &dam[1];
1233 written = GNUNET_CRYPTO_write_private_key_to_buffer (pkey, buf, key_len);
1234 GNUNET_assert (0 < written);
1235 buf += written;
1236 dam->id = htonl (op->r_id);
1237 GNUNET_RECLAIM_attribute_serialize (attr, buf);
1238
1239 dam->attr_len = htons (attr_len);
1240 if (NULL != h->mq)
1241 GNUNET_MQ_send_copy (h->mq, op->env);
1242 return op;
1243}
1244
1245
1246struct GNUNET_RECLAIM_Operation *
1247GNUNET_RECLAIM_credential_store (
1248 struct GNUNET_RECLAIM_Handle *h,
1249 const struct GNUNET_CRYPTO_PrivateKey *pkey,
1250 const struct GNUNET_RECLAIM_Credential *credential,
1251 const struct GNUNET_TIME_Relative *exp_interval,
1252 GNUNET_RECLAIM_ContinuationWithStatus cont,
1253 void *cont_cls)
1254{
1255 struct GNUNET_RECLAIM_Operation *op;
1256 struct AttributeStoreMessage *sam;
1257 size_t attr_len;
1258 size_t key_len;
1259 ssize_t written;
1260 char *buf;
1261
1262 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1263 op->h = h;
1264 op->as_cb = cont;
1265 op->cls = cont_cls;
1266 op->r_id = h->r_id_gen++;
1267 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
1268 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1269 attr_len = GNUNET_RECLAIM_credential_serialize_get_size (credential);
1270 op->env = GNUNET_MQ_msg_extra (sam,
1271 attr_len + key_len,
1272 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE);
1273 sam->key_len = htons (key_len);
1274 buf = (char *) &sam[1];
1275 written = GNUNET_CRYPTO_write_private_key_to_buffer (pkey, buf, key_len);
1276 GNUNET_assert (0 <= written);
1277 buf += written;
1278 sam->id = htonl (op->r_id);
1279 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1280
1281 GNUNET_RECLAIM_credential_serialize (credential, buf);
1282
1283 sam->attr_len = htons (attr_len);
1284 if (NULL != h->mq)
1285 GNUNET_MQ_send_copy (h->mq, op->env);
1286 return op;
1287}
1288
1289
1290struct GNUNET_RECLAIM_Operation *
1291GNUNET_RECLAIM_credential_delete (
1292 struct GNUNET_RECLAIM_Handle *h,
1293 const struct GNUNET_CRYPTO_PrivateKey *pkey,
1294 const struct GNUNET_RECLAIM_Credential *attr,
1295 GNUNET_RECLAIM_ContinuationWithStatus cont,
1296 void *cont_cls)
1297{
1298 struct GNUNET_RECLAIM_Operation *op;
1299 struct AttributeDeleteMessage *dam;
1300 size_t attr_len;
1301 size_t key_len;
1302 ssize_t written;
1303 char *buf;
1304
1305 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1306 op->h = h;
1307 op->as_cb = cont;
1308 op->cls = cont_cls;
1309 op->r_id = h->r_id_gen++;
1310 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
1311 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1312 attr_len = GNUNET_RECLAIM_credential_serialize_get_size (attr);
1313 op->env = GNUNET_MQ_msg_extra (dam,
1314 attr_len + key_len,
1315 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE);
1316 dam->key_len = htons (key_len);
1317 buf = (char *) &dam[1];
1318 written = GNUNET_CRYPTO_write_private_key_to_buffer (pkey, buf, key_len);
1319 GNUNET_assert (0 <= written);
1320 buf += written;
1321 dam->id = htonl (op->r_id);
1322 GNUNET_RECLAIM_credential_serialize (attr, buf);
1323
1324 dam->attr_len = htons (attr_len);
1325 if (NULL != h->mq)
1326 GNUNET_MQ_send_copy (h->mq, op->env);
1327 return op;
1328}
1329
1330
1331struct GNUNET_RECLAIM_AttributeIterator *
1332GNUNET_RECLAIM_get_attributes_start (
1333 struct GNUNET_RECLAIM_Handle *h,
1334 const struct GNUNET_CRYPTO_PrivateKey *identity,
1335 GNUNET_SCHEDULER_TaskCallback error_cb,
1336 void *error_cb_cls,
1337 GNUNET_RECLAIM_AttributeResult proc,
1338 void *proc_cls,
1339 GNUNET_SCHEDULER_TaskCallback finish_cb,
1340 void *finish_cb_cls)
1341{
1342 struct GNUNET_RECLAIM_AttributeIterator *it;
1343 struct GNUNET_MQ_Envelope *env;
1344 struct AttributeIterationStartMessage *msg;
1345 uint32_t rid;
1346 size_t key_len;
1347
1348 rid = h->r_id_gen++;
1349 it = GNUNET_new (struct GNUNET_RECLAIM_AttributeIterator);
1350 it->h = h;
1351 it->error_cb = error_cb;
1352 it->error_cb_cls = error_cb_cls;
1353 it->finish_cb = finish_cb;
1354 it->finish_cb_cls = finish_cb_cls;
1355 it->proc = proc;
1356 it->proc_cls = proc_cls;
1357 it->r_id = rid;
1358 it->identity = *identity;
1359 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1360 GNUNET_CONTAINER_DLL_insert_tail (h->it_head, h->it_tail, it);
1361 env =
1362 GNUNET_MQ_msg_extra (msg,
1363 key_len,
1364 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START);
1365 msg->id = htonl (rid);
1366 msg->key_len = htons (key_len);
1367 GNUNET_CRYPTO_write_private_key_to_buffer (identity, &msg[1], key_len);
1368 if (NULL == h->mq)
1369 it->env = env;
1370 else
1371 GNUNET_MQ_send (h->mq, env);
1372 return it;
1373}
1374
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
1390void
1391GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
1392{
1393 struct GNUNET_RECLAIM_Handle *h = it->h;
1394 struct GNUNET_MQ_Envelope *env;
1395 struct AttributeIterationStopMessage *msg;
1396
1397 if (NULL != h->mq)
1398 {
1399 env =
1400 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP);
1401 msg->id = htonl (it->r_id);
1402 GNUNET_MQ_send (h->mq, env);
1403 }
1404 free_it (it);
1405}
1406
1407
1408struct GNUNET_RECLAIM_CredentialIterator *
1409GNUNET_RECLAIM_get_credentials_start (
1410 struct GNUNET_RECLAIM_Handle *h,
1411 const struct GNUNET_CRYPTO_PrivateKey *identity,
1412 GNUNET_SCHEDULER_TaskCallback error_cb,
1413 void *error_cb_cls,
1414 GNUNET_RECLAIM_CredentialResult proc,
1415 void *proc_cls,
1416 GNUNET_SCHEDULER_TaskCallback finish_cb,
1417 void *finish_cb_cls)
1418{
1419 struct GNUNET_RECLAIM_CredentialIterator *ait;
1420 struct GNUNET_MQ_Envelope *env;
1421 struct CredentialIterationStartMessage *msg;
1422 uint32_t rid;
1423 size_t key_len;
1424
1425 rid = h->r_id_gen++;
1426 ait = GNUNET_new (struct GNUNET_RECLAIM_CredentialIterator);
1427 ait->h = h;
1428 ait->error_cb = error_cb;
1429 ait->error_cb_cls = error_cb_cls;
1430 ait->finish_cb = finish_cb;
1431 ait->finish_cb_cls = finish_cb_cls;
1432 ait->proc = proc;
1433 ait->proc_cls = proc_cls;
1434 ait->r_id = rid;
1435 ait->identity = *identity;
1436 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1437 GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait);
1438 env =
1439 GNUNET_MQ_msg_extra (msg,
1440 key_len,
1441 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START);
1442 msg->id = htonl (rid);
1443 msg->key_len = htons (key_len);
1444 GNUNET_CRYPTO_write_private_key_to_buffer (identity, &msg[1], key_len);
1445 if (NULL == h->mq)
1446 ait->env = env;
1447 else
1448 GNUNET_MQ_send (h->mq, env);
1449 return ait;
1450}
1451
1452
1453void
1454GNUNET_RECLAIM_get_credentials_next (struct
1455 GNUNET_RECLAIM_CredentialIterator *ait)
1456{
1457 struct GNUNET_RECLAIM_Handle *h = ait->h;
1458 struct CredentialIterationNextMessage *msg;
1459 struct GNUNET_MQ_Envelope *env;
1460
1461 env =
1462 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT);
1463 msg->id = htonl (ait->r_id);
1464 GNUNET_MQ_send (h->mq, env);
1465}
1466
1467
1468void
1469GNUNET_RECLAIM_get_credentials_stop (struct
1470 GNUNET_RECLAIM_CredentialIterator *ait)
1471{
1472 struct GNUNET_RECLAIM_Handle *h = ait->h;
1473 struct GNUNET_MQ_Envelope *env;
1474 struct CredentialIterationStopMessage *msg;
1475
1476 if (NULL != h->mq)
1477 {
1478 env =
1479 GNUNET_MQ_msg (msg,
1480 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP);
1481 msg->id = htonl (ait->r_id);
1482 GNUNET_MQ_send (h->mq, env);
1483 }
1484 free_ait (ait);
1485}
1486
1487
1488struct GNUNET_RECLAIM_Operation *
1489GNUNET_RECLAIM_ticket_issue (
1490 struct GNUNET_RECLAIM_Handle *h,
1491 const struct GNUNET_CRYPTO_PrivateKey *iss,
1492 const struct GNUNET_CRYPTO_PublicKey *rp,
1493 const struct GNUNET_RECLAIM_AttributeList *attrs,
1494 GNUNET_RECLAIM_IssueTicketCallback cb,
1495 void *cb_cls)
1496{
1497 struct GNUNET_RECLAIM_Operation *op;
1498 struct IssueTicketMessage *tim;
1499 size_t attr_len;
1500 size_t key_len;
1501 size_t rpk_len;
1502 ssize_t written;
1503 char *buf;
1504
1505 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1506 op->h = h;
1507 op->ti_cb = cb;
1508 op->cls = cb_cls;
1509 op->r_id = h->r_id_gen++;
1510 key_len = GNUNET_CRYPTO_private_key_get_length (iss);
1511 rpk_len = GNUNET_CRYPTO_public_key_get_length (rp);
1512 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1513 attr_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
1514 op->env = GNUNET_MQ_msg_extra (tim,
1515 attr_len + key_len + rpk_len,
1516 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET);
1517 tim->key_len = htons (key_len);
1518 tim->pkey_len = htons (rpk_len);
1519 buf = (char *) &tim[1];
1520 written = GNUNET_CRYPTO_write_private_key_to_buffer (iss, buf, key_len);
1521 GNUNET_assert (0 <= written);
1522 buf += written;
1523 written = GNUNET_CRYPTO_write_public_key_to_buffer (rp, buf, rpk_len);
1524 GNUNET_assert (0 <= written);
1525 buf += written;
1526 tim->id = htonl (op->r_id);
1527
1528 GNUNET_RECLAIM_attribute_list_serialize (attrs, buf);
1529 tim->attr_len = htons (attr_len);
1530 if (NULL != h->mq)
1531 GNUNET_MQ_send_copy (h->mq, op->env);
1532 return op;
1533}
1534
1535
1536/**
1537 * Consumes an issued ticket. The ticket is persisted
1538 * and used to retrieve identity information from the issuer
1539 *
1540 * @param h the reclaim to use
1541 * @param identity the identity that is the subject of the issued ticket (the
1542 * relying party)
1543 * @param ticket the issued ticket to consume
1544 * @param cb the callback to call
1545 * @param cb_cls the callback closure
1546 * @return handle to abort the operation
1547 */
1548struct GNUNET_RECLAIM_Operation *
1549GNUNET_RECLAIM_ticket_consume (
1550 struct GNUNET_RECLAIM_Handle *h,
1551 const struct GNUNET_CRYPTO_PrivateKey *identity,
1552 const struct GNUNET_RECLAIM_Ticket *ticket,
1553 GNUNET_RECLAIM_AttributeTicketResult cb,
1554 void *cb_cls)
1555{
1556 struct GNUNET_RECLAIM_Operation *op;
1557 struct ConsumeTicketMessage *ctm;
1558 size_t key_len;
1559 size_t tkt_len;
1560 char *buf;
1561
1562 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1563 op->h = h;
1564 op->atr_cb = cb;
1565 op->cls = cb_cls;
1566 op->r_id = h->r_id_gen++;
1567 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1568 tkt_len = GNUNET_RECLAIM_ticket_serialize_get_size (ticket);
1569 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1570 op->env = GNUNET_MQ_msg_extra (ctm,
1571 key_len + tkt_len,
1572 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET);
1573 ctm->key_len = htons (key_len);
1574 buf = (char*) &ctm[1];
1575 GNUNET_CRYPTO_write_private_key_to_buffer (identity, buf, key_len);
1576 buf += key_len;
1577 ctm->tkt_len = htons (tkt_len);
1578 GNUNET_RECLAIM_write_ticket_to_buffer (ticket, buf, tkt_len);
1579 ctm->id = htonl (op->r_id);
1580 if (NULL != h->mq)
1581 GNUNET_MQ_send_copy (h->mq, op->env);
1582 else
1583 reconnect (h);
1584 return op;
1585}
1586
1587
1588struct GNUNET_RECLAIM_TicketIterator *
1589GNUNET_RECLAIM_ticket_iteration_start (
1590 struct GNUNET_RECLAIM_Handle *h,
1591 const struct GNUNET_CRYPTO_PrivateKey *identity,
1592 GNUNET_SCHEDULER_TaskCallback error_cb,
1593 void *error_cb_cls,
1594 GNUNET_RECLAIM_TicketCallback proc,
1595 void *proc_cls,
1596 GNUNET_SCHEDULER_TaskCallback finish_cb,
1597 void *finish_cb_cls)
1598{
1599 struct GNUNET_RECLAIM_TicketIterator *it;
1600 struct GNUNET_MQ_Envelope *env;
1601 struct TicketIterationStartMessage *msg;
1602 uint32_t rid;
1603 size_t key_len;
1604
1605 rid = h->r_id_gen++;
1606 it = GNUNET_new (struct GNUNET_RECLAIM_TicketIterator);
1607 it->h = h;
1608 it->error_cb = error_cb;
1609 it->error_cb_cls = error_cb_cls;
1610 it->finish_cb = finish_cb;
1611 it->finish_cb_cls = finish_cb_cls;
1612 it->tr_cb = proc;
1613 it->cls = proc_cls;
1614 it->r_id = rid;
1615
1616 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1617 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, h->ticket_it_tail, it);
1618 env = GNUNET_MQ_msg_extra (msg,
1619 key_len,
1620 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START);
1621 msg->id = htonl (rid);
1622 msg->key_len = htons (key_len);
1623 GNUNET_CRYPTO_write_private_key_to_buffer (identity,
1624 &msg[1],
1625 key_len);
1626 if (NULL == h->mq)
1627 it->env = env;
1628 else
1629 GNUNET_MQ_send (h->mq, env);
1630 return it;
1631}
1632
1633
1634/**
1635 * Calls the ticket processor specified in
1636 * #GNUNET_RECLAIM_ticket_iteration_start for the next record.
1637 *
1638 * @param it the iterator
1639 */
1640void
1641GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it)
1642{
1643 struct GNUNET_RECLAIM_Handle *h = it->h;
1644 struct TicketIterationNextMessage *msg;
1645 struct GNUNET_MQ_Envelope *env;
1646
1647 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT);
1648 msg->id = htonl (it->r_id);
1649 GNUNET_MQ_send (h->mq, env);
1650}
1651
1652
1653/**
1654 * Stops iteration and releases the handle for further calls. Must
1655 * be called on any iteration that has not yet completed prior to calling
1656 * #GNUNET_RECLAIM_disconnect.
1657 *
1658 * @param it the iterator
1659 */
1660void
1661GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it)
1662{
1663 struct GNUNET_RECLAIM_Handle *h = it->h;
1664 struct GNUNET_MQ_Envelope *env;
1665 struct TicketIterationStopMessage *msg;
1666
1667 if (NULL != h->mq)
1668 {
1669 env =
1670 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP);
1671 msg->id = htonl (it->r_id);
1672 GNUNET_MQ_send (h->mq, env);
1673 }
1674 GNUNET_free (it);
1675}
1676
1677
1678/**
1679 * Revoked an issued ticket. The relying party will be unable to retrieve
1680 * attributes. Other issued tickets remain unaffected.
1681 * This includes tickets issued to other relying parties as well as to
1682 * other tickets issued to the audience specified in this ticket.
1683 *
1684 * @param h the identity provider to use
1685 * @param identity the issuing identity
1686 * @param ticket the ticket to revoke
1687 * @param cb the callback
1688 * @param cb_cls the callback closure
1689 * @return handle to abort the operation
1690 */
1691struct GNUNET_RECLAIM_Operation *
1692GNUNET_RECLAIM_ticket_revoke (
1693 struct GNUNET_RECLAIM_Handle *h,
1694 const struct GNUNET_CRYPTO_PrivateKey *identity,
1695 const struct GNUNET_RECLAIM_Ticket *ticket,
1696 GNUNET_RECLAIM_ContinuationWithStatus cb,
1697 void *cb_cls)
1698{
1699 struct GNUNET_RECLAIM_Operation *op;
1700 struct RevokeTicketMessage *msg;
1701 uint32_t rid;
1702 size_t key_len;
1703 size_t tkt_len;
1704 ssize_t written;
1705 char *buf;
1706
1707 rid = h->r_id_gen++;
1708 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1709 op->h = h;
1710 op->rvk_cb = cb;
1711 op->cls = cb_cls;
1712 op->r_id = rid;
1713 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1714 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1715 tkt_len = GNUNET_RECLAIM_ticket_serialize_get_size (ticket);
1716 op->env = GNUNET_MQ_msg_extra (msg,
1717 key_len + tkt_len,
1718 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET);
1719 msg->id = htonl (rid);
1720 msg->key_len = htons (key_len);
1721 msg->tkt_len = htons (tkt_len);
1722 buf = (char*) &msg[1];
1723 written = GNUNET_CRYPTO_write_private_key_to_buffer (identity,
1724 buf,
1725 key_len);
1726 GNUNET_assert (0 <= written);
1727 buf += written;
1728 GNUNET_RECLAIM_write_ticket_to_buffer (ticket,
1729 buf,
1730 tkt_len);
1731 if (NULL != h->mq)
1732 {
1733 GNUNET_MQ_send (h->mq, op->env);
1734 op->env = NULL;
1735 }
1736 return op;
1737}
1738
1739size_t
1740GNUNET_RECLAIM_ticket_serialize_get_size (const struct
1741 GNUNET_RECLAIM_Ticket *tkt)
1742{
1743 size_t size = sizeof (tkt->rnd);
1744 size += GNUNET_CRYPTO_public_key_get_length (&tkt->identity);
1745 size += GNUNET_CRYPTO_public_key_get_length (&tkt->audience);
1746 return size;
1747}
1748
1749enum GNUNET_GenericReturnValue
1750GNUNET_RECLAIM_read_ticket_from_buffer (const void *buffer,
1751 size_t len,
1752 struct GNUNET_RECLAIM_Ticket *tkt,
1753 size_t *tb_read)
1754{
1755 const char *tmp = buffer;
1756 size_t read = 0;
1757 size_t left = len;
1758 if (GNUNET_SYSERR ==
1759 GNUNET_CRYPTO_read_public_key_from_buffer (tmp,
1760 left,
1761 &tkt->identity,
1762 &read))
1763 return GNUNET_SYSERR;
1764 left -= read;
1765 tmp += read;
1766 if (GNUNET_SYSERR ==
1767 GNUNET_CRYPTO_read_public_key_from_buffer (tmp,
1768 left,
1769 &tkt->audience,
1770 &read))
1771 return GNUNET_SYSERR;
1772 left -= read;
1773 tmp += read;
1774 if (left < sizeof (tkt->rnd))
1775 return GNUNET_SYSERR;
1776 memcpy (&tkt->rnd, tmp, sizeof (tkt->rnd));
1777 *tb_read = tmp - (char*) buffer + sizeof (tkt->rnd);
1778 return GNUNET_OK;
1779}
1780
1781
1782ssize_t
1783GNUNET_RECLAIM_write_ticket_to_buffer (const struct
1784 GNUNET_RECLAIM_Ticket *tkt,
1785 void *buffer,
1786 size_t len)
1787{
1788 char *tmp = buffer;
1789 size_t left = len;
1790 ssize_t written = 0;
1791 written = GNUNET_CRYPTO_write_public_key_to_buffer (&tkt->identity,
1792 buffer,
1793 left);
1794 if (0 > written)
1795 return written;
1796 left -= written;
1797 tmp += written;
1798 written = GNUNET_CRYPTO_write_public_key_to_buffer (&tkt->audience,
1799 tmp,
1800 left);
1801 if (0 > written)
1802 return written;
1803 left -= written;
1804 tmp += written;
1805 if (left < sizeof (tkt->rnd))
1806 return -1;
1807 memcpy (tmp, &tkt->rnd, sizeof (tkt->rnd));
1808 return tmp - (char*) buffer + sizeof (tkt->rnd);
1809}
1810
1811
1812
1813/* end of reclaim_api.c */
diff --git a/src/reclaim/reclaim_attribute.c b/src/reclaim/reclaim_attribute.c
deleted file mode 100644
index b235ed945..000000000
--- a/src/reclaim/reclaim_attribute.c
+++ /dev/null
@@ -1,547 +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_in_context (GNUNET_OS_project_data_default (),
100 "libgnunet_plugin_reclaim_attribute_",
101 NULL,
102 &add_plugin,
103 NULL);
104}
105
106/**
107 * Dual function to #init().
108 */
109void __attribute__ ((destructor))
110RECLAIM_ATTRIBUTE_fini ()
111{
112 struct Plugin *plugin;
113 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
114 const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default ();
115
116 if (pd != dpd)
117 GNUNET_OS_init (dpd);
118
119 for (unsigned int i = 0; i < num_plugins; i++)
120 {
121 plugin = attr_plugins[i];
122 GNUNET_break (NULL ==
123 GNUNET_PLUGIN_unload (plugin->library_name,
124 plugin->api));
125 GNUNET_free (plugin->library_name);
126 GNUNET_free (plugin);
127 }
128 GNUNET_free (attr_plugins);
129
130 if (pd != dpd)
131 GNUNET_OS_init (pd);
132
133 attr_plugins = NULL;
134}
135
136
137
138/**
139 * Convert a type name to the corresponding number
140 *
141 * @param typename name to convert
142 * @return corresponding number, UINT32_MAX on error
143 */
144uint32_t
145GNUNET_RECLAIM_attribute_typename_to_number (const char *typename)
146{
147 unsigned int i;
148 struct Plugin *plugin;
149 uint32_t ret;
150
151 init ();
152 for (i = 0; i < num_plugins; i++)
153 {
154 plugin = attr_plugins[i];
155 if (UINT32_MAX !=
156 (ret = plugin->api->typename_to_number (plugin->api->cls, typename)))
157 return ret;
158 }
159 return UINT32_MAX;
160}
161
162
163/**
164 * Convert a type number to the corresponding type string
165 *
166 * @param type number of a type
167 * @return corresponding typestring, NULL on error
168 */
169const char *
170GNUNET_RECLAIM_attribute_number_to_typename (uint32_t type)
171{
172 unsigned int i;
173 struct Plugin *plugin;
174 const char *ret;
175
176 init ();
177 for (i = 0; i < num_plugins; i++)
178 {
179 plugin = attr_plugins[i];
180 if (NULL !=
181 (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
182 return ret;
183 }
184 return NULL;
185}
186
187
188/**
189 * Convert human-readable version of a 'claim' of an attribute to the binary
190 * representation
191 *
192 * @param type type of the claim
193 * @param s human-readable string
194 * @param data set to value in binary encoding (will be allocated)
195 * @param data_size set to number of bytes in @a data
196 * @return #GNUNET_OK on success
197 */
198int
199GNUNET_RECLAIM_attribute_string_to_value (uint32_t type,
200 const char *s,
201 void **data,
202 size_t *data_size)
203{
204 unsigned int i;
205 struct Plugin *plugin;
206
207 init ();
208 for (i = 0; i < num_plugins; i++)
209 {
210 plugin = attr_plugins[i];
211 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
212 type,
213 s,
214 data,
215 data_size))
216 return GNUNET_OK;
217 }
218 return GNUNET_SYSERR;
219}
220
221
222/**
223 * Convert the 'claim' of an attribute to a string
224 *
225 * @param type the type of attribute
226 * @param data claim in binary encoding
227 * @param data_size number of bytes in @a data
228 * @return NULL on error, otherwise human-readable representation of the claim
229 */
230char *
231GNUNET_RECLAIM_attribute_value_to_string (uint32_t type,
232 const void *data,
233 size_t data_size)
234{
235 unsigned int i;
236 struct Plugin *plugin;
237 char *ret;
238
239 init ();
240 for (i = 0; i < num_plugins; i++)
241 {
242 plugin = attr_plugins[i];
243 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
244 type,
245 data,
246 data_size)))
247 return ret;
248 }
249 return NULL;
250}
251
252
253struct GNUNET_RECLAIM_Attribute *
254GNUNET_RECLAIM_attribute_new (const char *attr_name,
255 const struct
256 GNUNET_RECLAIM_Identifier *credential,
257 uint32_t type,
258 const void *data,
259 size_t data_size)
260{
261 struct GNUNET_RECLAIM_Attribute *attr;
262 char *write_ptr;
263 char *attr_name_tmp = GNUNET_strdup (attr_name);
264
265 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
266
267 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
268 + strlen (attr_name_tmp) + 1 + data_size);
269 if (NULL != credential)
270 attr->credential = *credential;
271 attr->type = type;
272 attr->data_size = data_size;
273 attr->flag = 0;
274 write_ptr = (char *) &attr[1];
275 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
276 attr->name = write_ptr;
277 write_ptr += strlen (attr->name) + 1;
278 GNUNET_memcpy (write_ptr, data, data_size);
279 attr->data = write_ptr;
280 GNUNET_free (attr_name_tmp);
281 return attr;
282}
283
284
285void
286GNUNET_RECLAIM_attribute_list_add (
287 struct GNUNET_RECLAIM_AttributeList *al,
288 const char *attr_name,
289 const struct GNUNET_RECLAIM_Identifier *credential,
290 uint32_t type,
291 const void *data,
292 size_t data_size)
293{
294 struct GNUNET_RECLAIM_AttributeListEntry *ale;
295
296 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
297 ale->attribute =
298 GNUNET_RECLAIM_attribute_new (attr_name, credential,
299 type, data, data_size);
300 GNUNET_CONTAINER_DLL_insert (al->list_head,
301 al->list_tail,
302 ale);
303}
304
305
306/**
307 * Get required size for serialization buffer
308 *
309 * @param attrs the attribute list to serialize
310 * @return the required buffer size
311 */
312size_t
313GNUNET_RECLAIM_attribute_list_serialize_get_size (
314 const struct GNUNET_RECLAIM_AttributeList *al)
315{
316 struct GNUNET_RECLAIM_AttributeListEntry *ale;
317 size_t len = 0;
318
319 for (ale = al->list_head; NULL != ale; ale = ale->next)
320 {
321 GNUNET_assert (NULL != ale->attribute);
322 len += GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
323 }
324 return len;
325}
326
327
328size_t
329GNUNET_RECLAIM_attribute_list_serialize (
330 const struct GNUNET_RECLAIM_AttributeList *attrs,
331 char *result)
332{
333 struct GNUNET_RECLAIM_AttributeListEntry *ale;
334 size_t len;
335 size_t total_len;
336 char *write_ptr;
337 write_ptr = result;
338 total_len = 0;
339 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
340 {
341 GNUNET_assert (NULL != ale->attribute);
342 len = GNUNET_RECLAIM_attribute_serialize (ale->attribute, write_ptr);
343 total_len += len;
344 write_ptr += len;
345 }
346 return total_len;
347}
348
349
350/**
351 * Deserialize an attribute list
352 *
353 * @param data the serialized attribute list
354 * @param data_size the length of the serialized data
355 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
356 */
357struct GNUNET_RECLAIM_AttributeList *
358GNUNET_RECLAIM_attribute_list_deserialize (const char *data, size_t data_size)
359{
360 struct GNUNET_RECLAIM_AttributeList *al;
361 struct GNUNET_RECLAIM_AttributeListEntry *ale;
362 size_t attr_len;
363 const char *read_ptr;
364 size_t left = data_size;
365
366 al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
367 if (data_size < sizeof(struct Attribute))
368 return al;
369 read_ptr = data;
370 while (left >= sizeof(struct Attribute))
371 {
372 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
373 attr_len =
374 GNUNET_RECLAIM_attribute_deserialize (read_ptr,
375 left,
376 &ale->attribute);
377 if (-1 == attr_len)
378 {
379 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
380 "Failed to deserialize malformed attribute.\n");
381 GNUNET_free (ale);
382 return al;
383 }
384 left -= attr_len;
385 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
386 read_ptr += attr_len;
387 }
388 return al;
389}
390
391
392struct GNUNET_RECLAIM_AttributeList *
393GNUNET_RECLAIM_attribute_list_dup (
394 const struct GNUNET_RECLAIM_AttributeList *attrs)
395{
396 struct GNUNET_RECLAIM_AttributeListEntry *ale;
397 struct GNUNET_RECLAIM_AttributeListEntry *result_ale;
398 struct GNUNET_RECLAIM_AttributeList *result;
399
400 result = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
401 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
402 {
403 result_ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
404 GNUNET_assert (NULL != ale->attribute);
405 {
406 result_ale->attribute =
407 GNUNET_RECLAIM_attribute_new (ale->attribute->name,
408 &ale->attribute->credential,
409 ale->attribute->type,
410 ale->attribute->data,
411 ale->attribute->data_size);
412
413 result_ale->attribute->id = ale->attribute->id;
414 result_ale->attribute->flag = ale->attribute->flag;
415 }
416 GNUNET_CONTAINER_DLL_insert (result->list_head,
417 result->list_tail,
418 result_ale);
419 }
420 return result;
421}
422
423
424void
425GNUNET_RECLAIM_attribute_list_destroy (
426 struct GNUNET_RECLAIM_AttributeList *al)
427{
428 struct GNUNET_RECLAIM_AttributeListEntry *ale;
429 struct GNUNET_RECLAIM_AttributeListEntry *tmp_ale;
430
431 for (ale = al->list_head; NULL != ale;)
432 {
433 if (NULL != ale->attribute)
434 GNUNET_free (ale->attribute);
435 tmp_ale = ale;
436 ale = ale->next;
437 GNUNET_free (tmp_ale);
438 }
439 GNUNET_free (al);
440}
441
442
443/**
444 * Get required size for serialization buffer
445 *
446 * @param attr the attribute to serialize
447 * @return the required buffer size
448 */
449size_t
450GNUNET_RECLAIM_attribute_serialize_get_size (
451 const struct GNUNET_RECLAIM_Attribute *attr)
452{
453 return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
454}
455
456
457/**
458 * Serialize an attribute
459 *
460 * @param attr the attribute to serialize
461 * @param result the serialized attribute
462 * @return length of serialized data
463 */
464size_t
465GNUNET_RECLAIM_attribute_serialize (
466 const struct GNUNET_RECLAIM_Attribute *attr,
467 char *result)
468{
469 size_t data_len_ser;
470 size_t name_len;
471 struct Attribute *attr_ser;
472 char *write_ptr;
473
474 attr_ser = (struct Attribute *) result;
475 attr_ser->attribute_type = htonl (attr->type);
476 attr_ser->attribute_flag = htonl (attr->flag);
477 attr_ser->attribute_id = attr->id;
478 attr_ser->credential_id = attr->credential;
479 name_len = strlen (attr->name);
480 attr_ser->name_len = htons (name_len);
481 write_ptr = (char *) &attr_ser[1];
482 GNUNET_memcpy (write_ptr, attr->name, name_len);
483 write_ptr += name_len;
484 // TODO plugin-ize
485 // data_len_ser = plugin->serialize_attribute_value (attr,
486 // &attr_ser[1]);
487 data_len_ser = attr->data_size;
488 GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
489 attr_ser->data_size = htons (data_len_ser);
490
491 return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
492}
493
494
495/**
496 * Deserialize an attribute
497 *
498 * @param data the serialized attribute
499 * @param data_size the length of the serialized data
500 *
501 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
502 */
503ssize_t
504GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size,
505 struct GNUNET_RECLAIM_Attribute **attr)
506{
507 struct Attribute *attr_ser;
508 struct GNUNET_RECLAIM_Attribute *attribute;
509 size_t data_len;
510 size_t name_len;
511 char *write_ptr;
512
513 if (data_size < sizeof(struct Attribute))
514 return -1;
515
516 attr_ser = (struct Attribute *) data;
517 data_len = ntohs (attr_ser->data_size);
518 name_len = ntohs (attr_ser->name_len);
519 if (data_size < sizeof(struct Attribute) + data_len + name_len)
520 {
521 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
522 "Buffer too small to deserialize\n");
523 return -1;
524 }
525 attribute = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
526 + data_len + name_len + 1);
527 attribute->type = ntohl (attr_ser->attribute_type);
528 attribute->flag = ntohl (attr_ser->attribute_flag);
529 attribute->id = attr_ser->attribute_id;
530 attribute->credential = attr_ser->credential_id;
531 attribute->data_size = data_len;
532
533 write_ptr = (char *) &attribute[1];
534 GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
535 write_ptr[name_len] = '\0';
536 attribute->name = write_ptr;
537
538 write_ptr += name_len + 1;
539 GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len,
540 attribute->data_size);
541 *attr = attribute;
542 attribute->data = write_ptr;
543 return sizeof(struct Attribute) + data_len + name_len;
544}
545
546
547/* end of reclaim_attribute.c */
diff --git a/src/reclaim/reclaim_attribute.h b/src/reclaim/reclaim_attribute.h
deleted file mode 100644
index 44d85e61c..000000000
--- a/src/reclaim/reclaim_attribute.h
+++ /dev/null
@@ -1,83 +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 * Reserved (alignment)
60 */
61 uint16_t reserved_nl GNUNET_PACKED;
62
63 /**
64 * Name length
65 */
66 uint16_t name_len GNUNET_PACKED;
67
68 /**
69 * Reserved (alignment)
70 */
71 uint16_t reserved_ds GNUNET_PACKED;
72
73 /**
74 * Data size
75 */
76 uint16_t data_size GNUNET_PACKED;
77
78 // followed by data_size Attribute value data
79};
80
81GNUNET_NETWORK_STRUCT_BEGIN
82
83#endif
diff --git a/src/reclaim/reclaim_credential.c b/src/reclaim/reclaim_credential.c
deleted file mode 100644
index 1aad261a1..000000000
--- a/src/reclaim/reclaim_credential.c
+++ /dev/null
@@ -1,1004 +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_in_context (GNUNET_OS_project_data_default (),
100 "libgnunet_plugin_reclaim_credential_",
101 NULL,
102 &add_plugin,
103 NULL);
104}
105
106
107/**
108 * Dual function to #init().
109 */
110void __attribute__ ((destructor))
111RECLAIM_CREDENTIAL_fini ()
112{
113 struct Plugin *plugin;
114 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
115 const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default ();
116
117 if (pd != dpd)
118 GNUNET_OS_init (dpd);
119
120 for (unsigned int i = 0; i < num_plugins; i++)
121 {
122 plugin = credential_plugins[i];
123 GNUNET_break (NULL ==
124 GNUNET_PLUGIN_unload (plugin->library_name,
125 plugin->api));
126 GNUNET_free (plugin->library_name);
127 GNUNET_free (plugin);
128 }
129 GNUNET_free (credential_plugins);
130
131 if (pd != dpd)
132 GNUNET_OS_init (pd);
133
134 credential_plugins = NULL;
135}
136
137
138/**
139 * Convert an credential type name to the corresponding number
140 *
141 * @param typename name to convert
142 * @return corresponding number, UINT32_MAX on error
143 */
144uint32_t
145GNUNET_RECLAIM_credential_typename_to_number (const char *typename)
146{
147 unsigned int i;
148 struct Plugin *plugin;
149 uint32_t ret;
150 init ();
151 for (i = 0; i < num_plugins; i++)
152 {
153 plugin = credential_plugins[i];
154 if (UINT32_MAX !=
155 (ret = plugin->api->typename_to_number (plugin->api->cls,
156 typename)))
157 return ret;
158 }
159 return UINT32_MAX;
160}
161
162
163/**
164 * Convert an credential type number to the corresponding credential type string
165 *
166 * @param type number of a type
167 * @return corresponding typestring, NULL on error
168 */
169const char *
170GNUNET_RECLAIM_credential_number_to_typename (uint32_t type)
171{
172 unsigned int i;
173 struct Plugin *plugin;
174 const char *ret;
175
176 init ();
177 for (i = 0; i < num_plugins; i++)
178 {
179 plugin = credential_plugins[i];
180 if (NULL !=
181 (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
182 return ret;
183 }
184 return NULL;
185}
186
187
188/**
189 * Convert human-readable version of a 'claim' of an credential to the binary
190 * representation
191 *
192 * @param type type of the claim
193 * @param s human-readable string
194 * @param data set to value in binary encoding (will be allocated)
195 * @param data_size set to number of bytes in @a data
196 * @return #GNUNET_OK on success
197 */
198int
199GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
200 const char *s,
201 void **data,
202 size_t *data_size)
203{
204 unsigned int i;
205 struct Plugin *plugin;
206
207 init ();
208 for (i = 0; i < num_plugins; i++)
209 {
210 plugin = credential_plugins[i];
211 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
212 type,
213 s,
214 data,
215 data_size))
216 return GNUNET_OK;
217 }
218 return GNUNET_SYSERR;
219}
220
221
222/**
223 * Convert the 'claim' of an credential to a string
224 *
225 * @param type the type of credential
226 * @param data claim in binary encoding
227 * @param data_size number of bytes in @a data
228 * @return NULL on error, otherwise human-readable representation of the claim
229 */
230char *
231GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
232 const void *data,
233 size_t data_size)
234{
235 unsigned int i;
236 struct Plugin *plugin;
237 char *ret;
238
239 init ();
240 for (i = 0; i < num_plugins; i++)
241 {
242 plugin = credential_plugins[i];
243 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
244 type,
245 data,
246 data_size)))
247 return ret;
248 }
249 return NULL;
250}
251
252
253struct GNUNET_RECLAIM_Credential *
254GNUNET_RECLAIM_credential_new (const char *attr_name,
255 uint32_t type,
256 const void *data,
257 size_t data_size)
258{
259 struct GNUNET_RECLAIM_Credential *attr;
260 char *write_ptr;
261 char *attr_name_tmp = GNUNET_strdup (attr_name);
262
263 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
264
265 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
266 + strlen (attr_name_tmp) + 1 + data_size);
267 attr->type = type;
268 attr->data_size = data_size;
269 attr->flag = 0;
270 write_ptr = (char *) &attr[1];
271 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
272 attr->name = write_ptr;
273 write_ptr += strlen (attr->name) + 1;
274 GNUNET_memcpy (write_ptr, data, data_size);
275 attr->data = write_ptr;
276 GNUNET_free (attr_name_tmp);
277 return attr;
278}
279
280
281/**
282 * Get required size for serialization buffer
283 *
284 * @param attrs the attribute list to serialize
285 * @return the required buffer size
286 */
287size_t
288GNUNET_RECLAIM_credential_list_serialize_get_size (
289 const struct GNUNET_RECLAIM_CredentialList *credentials)
290{
291 struct GNUNET_RECLAIM_CredentialListEntry *le;
292 size_t len = 0;
293
294 for (le = credentials->list_head; NULL != le; le = le->next)
295 {
296 GNUNET_assert (NULL != le->credential);
297 len += GNUNET_RECLAIM_credential_serialize_get_size (le->credential);
298 len += sizeof(struct GNUNET_RECLAIM_CredentialListEntry);
299 }
300 return len;
301}
302
303
304size_t
305GNUNET_RECLAIM_credential_list_serialize (
306 const struct GNUNET_RECLAIM_CredentialList *credentials,
307 char *result)
308{
309 struct GNUNET_RECLAIM_CredentialListEntry *le;
310 size_t len;
311 size_t total_len;
312 char *write_ptr;
313 write_ptr = result;
314 total_len = 0;
315 for (le = credentials->list_head; NULL != le; le = le->next)
316 {
317 GNUNET_assert (NULL != le->credential);
318 len = GNUNET_RECLAIM_credential_serialize (le->credential, write_ptr);
319 total_len += len;
320 write_ptr += len;
321 }
322 return total_len;
323}
324
325
326struct GNUNET_RECLAIM_CredentialList *
327GNUNET_RECLAIM_credential_list_deserialize (const char *data, size_t data_size)
328{
329 struct GNUNET_RECLAIM_CredentialList *al;
330 struct GNUNET_RECLAIM_CredentialListEntry *ale;
331 size_t att_len;
332 const char *read_ptr;
333
334 al = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
335
336 if ((data_size < sizeof(struct
337 Credential)
338 + sizeof(struct GNUNET_RECLAIM_CredentialListEntry)))
339 return al;
340
341 read_ptr = data;
342 while (((data + data_size) - read_ptr) >= sizeof(struct Credential))
343 {
344 ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
345 ale->credential =
346 GNUNET_RECLAIM_credential_deserialize (read_ptr,
347 data_size - (read_ptr - data));
348 if (NULL == ale->credential)
349 {
350 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
351 "Failed to deserialize malformed credential.\n");
352 GNUNET_free (ale);
353 return al;
354 }
355 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
356 att_len = GNUNET_RECLAIM_credential_serialize_get_size (ale->credential);
357 read_ptr += att_len;
358 }
359 return al;
360}
361
362
363/**
364 * Make a (deep) copy of the credential list
365 * @param attrs claim list to copy
366 * @return copied claim list
367 */
368struct GNUNET_RECLAIM_CredentialList *
369GNUNET_RECLAIM_credential_list_dup (
370 const struct GNUNET_RECLAIM_CredentialList *al)
371{
372 struct GNUNET_RECLAIM_CredentialListEntry *ale;
373 struct GNUNET_RECLAIM_CredentialListEntry *result_ale;
374 struct GNUNET_RECLAIM_CredentialList *result;
375
376 result = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
377 for (ale = al->list_head; NULL != ale; ale = ale->next)
378 {
379 result_ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
380 GNUNET_assert (NULL != ale->credential);
381 result_ale->credential =
382 GNUNET_RECLAIM_credential_new (ale->credential->name,
383 ale->credential->type,
384 ale->credential->data,
385 ale->credential->data_size);
386 result_ale->credential->id = ale->credential->id;
387 GNUNET_CONTAINER_DLL_insert (result->list_head,
388 result->list_tail,
389 result_ale);
390 }
391 return result;
392}
393
394
395void
396GNUNET_RECLAIM_credential_list_destroy (
397 struct GNUNET_RECLAIM_CredentialList *credentials)
398{
399 struct GNUNET_RECLAIM_CredentialListEntry *ale;
400 struct GNUNET_RECLAIM_CredentialListEntry *tmp_ale;
401
402 for (ale = credentials->list_head; NULL != ale;)
403 {
404 if (NULL != ale->credential)
405 GNUNET_free (ale->credential);
406 tmp_ale = ale;
407 ale = ale->next;
408 GNUNET_free (tmp_ale);
409 }
410 GNUNET_free (credentials);
411}
412
413
414/**
415 * Get required size for serialization buffer
416 *
417 * @param attr the credential to serialize
418 * @return the required buffer size
419 */
420size_t
421GNUNET_RECLAIM_credential_serialize_get_size (
422 const struct GNUNET_RECLAIM_Credential *credential)
423{
424 return sizeof(struct Credential) + strlen (credential->name)
425 + credential->data_size;
426}
427
428
429size_t
430GNUNET_RECLAIM_credential_serialize (
431 const struct GNUNET_RECLAIM_Credential *credential,
432 char *result)
433{
434 size_t data_len_ser;
435 size_t name_len;
436 struct Credential *atts;
437 char *write_ptr;
438
439 atts = (struct Credential *) result;
440 atts->credential_type = htonl (credential->type);
441 atts->credential_flag = htonl (credential->flag);
442 atts->credential_id = credential->id;
443 name_len = strlen (credential->name);
444 atts->name_len = htons (name_len);
445 write_ptr = (char *) &atts[1];
446 GNUNET_memcpy (write_ptr, credential->name, name_len);
447 write_ptr += name_len;
448 // TODO plugin-ize
449 // data_len_ser = plugin->serialize_attribute_value (attr,
450 // &attr_ser[1]);
451 data_len_ser = credential->data_size;
452 GNUNET_memcpy (write_ptr, credential->data, credential->data_size);
453 atts->data_size = htons (data_len_ser);
454
455 return sizeof(struct Credential) + strlen (credential->name)
456 + credential->data_size;
457}
458
459
460/**
461 * Deserialize an credential
462 *
463 * @param data the serialized credential
464 * @param data_size the length of the serialized data
465 *
466 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
467 */
468struct GNUNET_RECLAIM_Credential *
469GNUNET_RECLAIM_credential_deserialize (const char *data, size_t data_size)
470{
471 struct GNUNET_RECLAIM_Credential *credential;
472 struct Credential *atts;
473 size_t data_len;
474 size_t name_len;
475 char *write_ptr;
476
477 if (data_size < sizeof(struct Credential))
478 return NULL;
479
480 atts = (struct Credential *) data;
481 data_len = ntohs (atts->data_size);
482 name_len = ntohs (atts->name_len);
483 if (data_size < sizeof(struct Credential) + data_len + name_len)
484 {
485 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
486 "Buffer too small to deserialize\n");
487 return NULL;
488 }
489 credential = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
490 + data_len + name_len + 1);
491 credential->type = ntohl (atts->credential_type);
492 credential->flag = ntohl (atts->credential_flag);
493 credential->id = atts->credential_id;
494 credential->data_size = data_len;
495
496 write_ptr = (char *) &credential[1];
497 GNUNET_memcpy (write_ptr, &atts[1], name_len);
498 write_ptr[name_len] = '\0';
499 credential->name = write_ptr;
500
501 write_ptr += name_len + 1;
502 GNUNET_memcpy (write_ptr, (char *) &atts[1] + name_len,
503 credential->data_size);
504 credential->data = write_ptr;
505 return credential;
506}
507
508
509struct GNUNET_RECLAIM_AttributeList*
510GNUNET_RECLAIM_credential_get_attributes (const struct
511 GNUNET_RECLAIM_Credential *credential)
512{
513 unsigned int i;
514 struct Plugin *plugin;
515 struct GNUNET_RECLAIM_AttributeList *ret;
516 init ();
517 for (i = 0; i < num_plugins; i++)
518 {
519 plugin = credential_plugins[i];
520 if (NULL !=
521 (ret = plugin->api->get_attributes (plugin->api->cls,
522 credential)))
523 return ret;
524 }
525 return NULL;
526}
527
528
529char*
530GNUNET_RECLAIM_credential_get_issuer (const struct
531 GNUNET_RECLAIM_Credential *credential)
532{
533 unsigned int i;
534 struct Plugin *plugin;
535 char *ret;
536 init ();
537 for (i = 0; i < num_plugins; i++)
538 {
539 plugin = credential_plugins[i];
540 if (NULL !=
541 (ret = plugin->api->get_issuer (plugin->api->cls,
542 credential)))
543 return ret;
544 }
545 return NULL;
546}
547
548
549int
550GNUNET_RECLAIM_credential_get_expiration (const struct
551 GNUNET_RECLAIM_Credential *credential,
552 struct GNUNET_TIME_Absolute*exp)
553{
554 unsigned int i;
555 struct Plugin *plugin;
556 init ();
557 for (i = 0; i < num_plugins; i++)
558 {
559 plugin = credential_plugins[i];
560 if (GNUNET_OK != plugin->api->get_expiration (plugin->api->cls,
561 credential,
562 exp))
563 continue;
564 return GNUNET_OK;
565 }
566 return GNUNET_SYSERR;
567}
568
569
570/**
571 * Convert an presentation type name to the corresponding number
572 *
573 * @param typename name to convert
574 * @return corresponding number, UINT32_MAX on error
575 */
576uint32_t
577GNUNET_RECLAIM_presentation_typename_to_number (const char *typename)
578{
579 unsigned int i;
580 struct Plugin *plugin;
581 uint32_t ret;
582 init ();
583 for (i = 0; i < num_plugins; i++)
584 {
585 plugin = credential_plugins[i];
586 if (UINT32_MAX !=
587 (ret = plugin->api->typename_to_number_p (plugin->api->cls,
588 typename)))
589 return ret;
590 }
591 return UINT32_MAX;
592}
593
594
595const char *
596GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type)
597{
598 unsigned int i;
599 struct Plugin *plugin;
600 const char *ret;
601
602 init ();
603 for (i = 0; i < num_plugins; i++)
604 {
605 plugin = credential_plugins[i];
606 if (NULL !=
607 (ret = plugin->api->number_to_typename_p (plugin->api->cls, type)))
608 return ret;
609 }
610 return NULL;
611}
612
613
614/**
615 * Convert human-readable version of a 'claim' of an presentation to the binary
616 * representation
617 *
618 * @param type type of the claim
619 * @param s human-readable string
620 * @param data set to value in binary encoding (will be allocated)
621 * @param data_size set to number of bytes in @a data
622 * @return #GNUNET_OK on success
623 */
624int
625GNUNET_RECLAIM_presentation_string_to_value (uint32_t type,
626 const char *s,
627 void **data,
628 size_t *data_size)
629{
630 unsigned int i;
631 struct Plugin *plugin;
632
633 init ();
634 for (i = 0; i < num_plugins; i++)
635 {
636 plugin = credential_plugins[i];
637 if (GNUNET_OK == plugin->api->string_to_value_p (plugin->api->cls,
638 type,
639 s,
640 data,
641 data_size))
642 return GNUNET_OK;
643 }
644 return GNUNET_SYSERR;
645}
646
647
648/**
649 * Convert the 'claim' of an presentation to a string
650 *
651 * @param type the type of presentation
652 * @param data claim in binary encoding
653 * @param data_size number of bytes in @a data
654 * @return NULL on error, otherwise human-readable representation of the claim
655 */
656char *
657GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
658 const void *data,
659 size_t data_size)
660{
661 unsigned int i;
662 struct Plugin *plugin;
663 char *ret;
664
665 init ();
666 for (i = 0; i < num_plugins; i++)
667 {
668 plugin = credential_plugins[i];
669 if (NULL != (ret = plugin->api->value_to_string_p (plugin->api->cls,
670 type,
671 data,
672 data_size)))
673 return ret;
674 }
675 return NULL;
676}
677
678
679struct GNUNET_RECLAIM_Presentation *
680GNUNET_RECLAIM_presentation_new (uint32_t type,
681 const void *data,
682 size_t data_size)
683{
684 struct GNUNET_RECLAIM_Presentation *attr;
685 char *write_ptr;
686
687 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
688 + data_size);
689 attr->type = type;
690 attr->data_size = data_size;
691 write_ptr = (char *) &attr[1];
692 GNUNET_memcpy (write_ptr, data, data_size);
693 attr->data = write_ptr;
694 return attr;
695}
696
697
698/**
699 * Get required size for serialization buffer
700 *
701 * @param attrs the attribute list to serialize
702 * @return the required buffer size
703 */
704size_t
705GNUNET_RECLAIM_presentation_list_serialize_get_size (
706 const struct GNUNET_RECLAIM_PresentationList *presentations)
707{
708 struct GNUNET_RECLAIM_PresentationListEntry *le;
709 size_t len = 0;
710
711 for (le = presentations->list_head; NULL != le; le = le->next)
712 {
713 GNUNET_assert (NULL != le->presentation);
714 len += GNUNET_RECLAIM_presentation_serialize_get_size (le->presentation);
715 }
716 return len;
717}
718
719
720size_t
721GNUNET_RECLAIM_presentation_list_serialize (
722 const struct GNUNET_RECLAIM_PresentationList *presentations,
723 char *result)
724{
725 struct GNUNET_RECLAIM_PresentationListEntry *le;
726 size_t len;
727 size_t total_len;
728 char *write_ptr;
729 write_ptr = result;
730 total_len = 0;
731 for (le = presentations->list_head; NULL != le; le = le->next)
732 {
733 GNUNET_assert (NULL != le->presentation);
734 len = GNUNET_RECLAIM_presentation_serialize (le->presentation, write_ptr);
735 total_len += len;
736 write_ptr += len;
737 }
738 return total_len;
739}
740
741
742/**
743 * Deserialize an presentation list
744 *
745 * @param data the serialized attribute list
746 * @param data_size the length of the serialized data
747 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
748 */
749struct GNUNET_RECLAIM_PresentationList *
750GNUNET_RECLAIM_presentation_list_deserialize (const char *data, size_t
751 data_size)
752{
753 struct GNUNET_RECLAIM_PresentationList *al;
754 struct GNUNET_RECLAIM_PresentationListEntry *ale;
755 size_t att_len;
756 const char *read_ptr;
757
758 al = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
759
760 if (data_size < sizeof(struct Presentation))
761 return al;
762
763 read_ptr = data;
764 while (((data + data_size) - read_ptr) >= sizeof(struct Presentation))
765 {
766 ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
767 ale->presentation =
768 GNUNET_RECLAIM_presentation_deserialize (read_ptr,
769 data_size - (read_ptr - data));
770 if (NULL == ale->presentation)
771 {
772 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
773 "Failed to deserialize malformed presentation.\n");
774 GNUNET_free (ale);
775 return al;
776 }
777 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
778 att_len = GNUNET_RECLAIM_presentation_serialize_get_size (
779 ale->presentation);
780 read_ptr += att_len;
781 }
782 return al;
783}
784
785
786/**
787 * Make a (deep) copy of the presentation list
788 * @param attrs claim list to copy
789 * @return copied claim list
790 */
791struct GNUNET_RECLAIM_PresentationList *
792GNUNET_RECLAIM_presentation_list_dup (
793 const struct GNUNET_RECLAIM_PresentationList *al)
794{
795 struct GNUNET_RECLAIM_PresentationListEntry *ale;
796 struct GNUNET_RECLAIM_PresentationListEntry *result_ale;
797 struct GNUNET_RECLAIM_PresentationList *result;
798
799 result = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
800 for (ale = al->list_head; NULL != ale; ale = ale->next)
801 {
802 result_ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
803 GNUNET_assert (NULL != ale->presentation);
804 result_ale->presentation =
805 GNUNET_RECLAIM_presentation_new (ale->presentation->type,
806 ale->presentation->data,
807 ale->presentation->data_size);
808 result_ale->presentation->credential_id = ale->presentation->credential_id;
809 GNUNET_CONTAINER_DLL_insert (result->list_head,
810 result->list_tail,
811 result_ale);
812 }
813 return result;
814}
815
816
817void
818GNUNET_RECLAIM_presentation_list_destroy (
819 struct GNUNET_RECLAIM_PresentationList *presentations)
820{
821 struct GNUNET_RECLAIM_PresentationListEntry *ale;
822 struct GNUNET_RECLAIM_PresentationListEntry *tmp_ale;
823
824 for (ale = presentations->list_head; NULL != ale;)
825 {
826 if (NULL != ale->presentation)
827 GNUNET_free (ale->presentation);
828 tmp_ale = ale;
829 ale = ale->next;
830 GNUNET_free (tmp_ale);
831 }
832 GNUNET_free (presentations);
833}
834
835
836/**
837 * Get required size for serialization buffer
838 *
839 * @param attr the presentation to serialize
840 * @return the required buffer size
841 */
842size_t
843GNUNET_RECLAIM_presentation_serialize_get_size (
844 const struct GNUNET_RECLAIM_Presentation *presentation)
845{
846 return sizeof(struct Presentation) + presentation->data_size;
847}
848
849
850size_t
851GNUNET_RECLAIM_presentation_serialize (
852 const struct GNUNET_RECLAIM_Presentation *presentation,
853 char *result)
854{
855 struct Presentation *atts;
856 char *write_ptr;
857
858 atts = (struct Presentation *) result;
859 atts->presentation_type = htonl (presentation->type);
860 atts->credential_id = presentation->credential_id;
861 write_ptr = (char *) &atts[1];
862 GNUNET_memcpy (write_ptr, presentation->data, presentation->data_size);
863 atts->data_size = htons (presentation->data_size);
864
865 return sizeof(struct Presentation) + presentation->data_size;
866}
867
868
869/**
870 * Deserialize an presentation
871 *
872 * @param data the serialized presentation
873 * @param data_size the length of the serialized data
874 *
875 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
876 */
877struct GNUNET_RECLAIM_Presentation *
878GNUNET_RECLAIM_presentation_deserialize (const char *data, size_t data_size)
879{
880 struct GNUNET_RECLAIM_Presentation *presentation;
881 struct Presentation *atts;
882 size_t data_len;
883 char *write_ptr;
884
885 if (data_size < sizeof(struct Presentation))
886 return NULL;
887
888 atts = (struct Presentation *) data;
889 data_len = ntohs (atts->data_size);
890 if (data_size < sizeof(struct Presentation) + data_len)
891 {
892 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
893 "Buffer too small to deserialize\n");
894 return NULL;
895 }
896 presentation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
897 + data_len);
898 presentation->type = ntohl (atts->presentation_type);
899 presentation->credential_id = atts->credential_id;
900 presentation->data_size = data_len;
901
902 write_ptr = (char *) &presentation[1];
903 GNUNET_memcpy (write_ptr, &atts[1], data_len);
904 presentation->data = write_ptr;
905 return presentation;
906}
907
908
909struct GNUNET_RECLAIM_AttributeList*
910GNUNET_RECLAIM_presentation_get_attributes (const struct
911 GNUNET_RECLAIM_Presentation *
912 presentation)
913{
914 unsigned int i;
915 struct Plugin *plugin;
916 struct GNUNET_RECLAIM_AttributeList *ret;
917 init ();
918 for (i = 0; i < num_plugins; i++)
919 {
920 plugin = credential_plugins[i];
921 if (NULL !=
922 (ret = plugin->api->get_attributes_p (plugin->api->cls,
923 presentation)))
924 return ret;
925 }
926 return NULL;
927}
928
929
930char*
931GNUNET_RECLAIM_presentation_get_issuer (const struct
932 GNUNET_RECLAIM_Presentation *
933 presentation)
934{
935 unsigned int i;
936 struct Plugin *plugin;
937 char *ret;
938 init ();
939 for (i = 0; i < num_plugins; i++)
940 {
941 plugin = credential_plugins[i];
942 if (NULL !=
943 (ret = plugin->api->get_issuer_p (plugin->api->cls,
944 presentation)))
945 return ret;
946 }
947 return NULL;
948}
949
950
951int
952GNUNET_RECLAIM_presentation_get_expiration (const struct
953 GNUNET_RECLAIM_Presentation *
954 presentation,
955 struct GNUNET_TIME_Absolute*exp)
956{
957 unsigned int i;
958 struct Plugin *plugin;
959 init ();
960 for (i = 0; i < num_plugins; i++)
961 {
962 plugin = credential_plugins[i];
963 if (GNUNET_OK != plugin->api->get_expiration_p (plugin->api->cls,
964 presentation,
965 exp))
966 continue;
967 return GNUNET_OK;
968 }
969 return GNUNET_SYSERR;
970}
971
972
973/**
974 * Create a presentation from a credential and a lift of (selected)
975 * attributes in the credential.
976 *
977 * @param cred the credential to use
978 * @param attrs the attributes to present from the credential
979 * @return the credential presentation presenting the attributes according
980 * to the presentation mechanism of the credential
981 * or NULL on error.
982 */
983int
984GNUNET_RECLAIM_credential_get_presentation (
985 const struct GNUNET_RECLAIM_Credential *cred,
986 const struct GNUNET_RECLAIM_AttributeList *attrs,
987 struct GNUNET_RECLAIM_Presentation **presentation)
988{
989 unsigned int i;
990 struct Plugin *plugin;
991 init ();
992 for (i = 0; i < num_plugins; i++)
993 {
994 plugin = credential_plugins[i];
995 if (GNUNET_OK != plugin->api->create_presentation (plugin->api->cls,
996 cred,
997 attrs,
998 presentation))
999 continue;
1000 (*presentation)->credential_id = cred->id;
1001 return GNUNET_OK;
1002 }
1003 return GNUNET_SYSERR;
1004}
diff --git a/src/reclaim/reclaim_credential.h b/src/reclaim/reclaim_credential.h
deleted file mode 100644
index ffec15445..000000000
--- a/src/reclaim/reclaim_credential.h
+++ /dev/null
@@ -1,119 +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 * Reserved (alignment)
53 */
54 uint16_t nl_reserved;
55
56 /**
57 * Name length
58 */
59 uint16_t name_len;
60
61 /**
62 * Reserved (alignment)
63 */
64 uint16_t dl_reserved;
65
66 /**
67 * Data size
68 */
69 uint16_t data_size;
70
71 // followed by data_size Credential value data
72};
73
74
75/**
76 * Serialized presentation claim
77 */
78struct Presentation
79{
80 /**
81 * Presentation type
82 */
83 uint32_t presentation_type;
84
85 /**
86 * Presentation flag
87 */
88 uint32_t presentation_flag;
89
90 /**
91 * Credential ID
92 */
93 struct GNUNET_RECLAIM_Identifier credential_id;
94
95 /**
96 * Reserved (alignment)
97 */
98 uint16_t reserved_nl GNUNET_PACKED;
99
100 /**
101 * Name length
102 */
103 uint16_t name_len GNUNET_PACKED;
104
105 /**
106 * Reserved (alignment)
107 */
108 uint16_t reserved_ds GNUNET_PACKED;
109
110 /**
111 * Data size
112 */
113 uint16_t data_size GNUNET_PACKED;
114
115 // followed by data_size Presentation value data
116};
117
118
119#endif
diff --git a/src/reclaim/test_did_helper.c b/src/reclaim/test_did_helper.c
deleted file mode 100644
index c11f47540..000000000
--- a/src/reclaim/test_did_helper.c
+++ /dev/null
@@ -1,137 +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/test_did_helper.c
23 * @brief Unit tests for the helper library for DID related functions
24 * @author Tristan Schwieren
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_gns_service.h"
31#include "gnunet_gnsrecord_lib.h"
32#include "did_helper.h"
33#include "jansson.h"
34
35static const char test_skey_bytes[32] = {
36 0x9b, 0x93, 0x7b, 0x81, 0x32, 0x2d, 0x81, 0x6c,
37 0xfa, 0xb9, 0xd5, 0xa3, 0xba, 0xac, 0xc9, 0xb2,
38 0xa5, 0xfe, 0xbe, 0x4b, 0x14, 0x9f, 0x12, 0x6b,
39 0x36, 0x30, 0xf9, 0x3a, 0x29, 0x52, 0x70, 0x17
40};
41
42// TODO: Create a did manual from private key / independet of implementation
43static const char *test_did =
44 "did:gns:000G0509BYD1MPAXVSTNV0KRD1JAT0YZMPJFQNM869B66S72PSF17K4Y8G";
45
46static const char *test_multibase_key =
47 "u7QEJX5oaWV3edV2CeGhkrQPfpaT71ogyVmNk4rZeE8yeRA";
48
49static const char *test_did_document_format_str =
50 "{\"@context\":[\"https://www.w3.org/ns/did/v1\",\
51 \"https://w3id.org/security/suites/ed25519-2020/v1\"],\
52 \"id\":\"%s\",\
53 \"verificationMethod\":[{\
54 \"id\":\"%s#key-1\",\
55 \"type\":\"Ed25519VerificationKey2020\",\
56 \"controller\":\"%s\",\
57 \"publicKeyMultibase\":\"%s\"}],\
58 \"authentication\":[\"#key-1\"],\
59 \"assertionMethod\":[\"#key-1\"]}";
60
61static struct GNUNET_CRYPTO_PrivateKey test_skey;
62static struct GNUNET_CRYPTO_PublicKey test_pkey;
63static struct json_t *test_did_document;
64static char *test_did_document_str;
65
66void
67test_GNUNET_DID_pkey_to_did ()
68{
69 char *str_did;
70 str_did = DID_pkey_to_did (&test_pkey);
71 GNUNET_assert (strcmp ((char *) test_did, str_did) == 0);
72 GNUNET_free (str_did);
73}
74
75void
76test_GNUNET_DID_did_to_pkey ()
77{
78 struct GNUNET_CRYPTO_PublicKey pkey;
79 DID_did_to_pkey ((char *) test_did, &pkey);
80
81 GNUNET_assert (test_pkey.type = pkey.type);
82 GNUNET_assert (memcmp (&pkey.eddsa_key,
83 &test_pkey.eddsa_key,
84 sizeof (test_pkey.eddsa_key)) == 0);
85}
86
87// void
88// test_GNUNET_DID_key_convert_multibase_base64_to_gnunet ();
89
90void
91test_GNUNET_DID_key_convert_gnunet_to_multibase_base64 ()
92{
93 char *multibase_key;
94 multibase_key = DID_key_convert_gnunet_to_multibase_base64 (&test_pkey);
95
96 GNUNET_assert (strcmp (test_multibase_key, multibase_key) == 0);
97 GNUNET_free (multibase_key);
98}
99
100void
101test_GNUNET_DID_pkey_to_did_document ()
102{
103 struct json_t *did_document;
104 char *did_document_str = DID_pkey_to_did_document (&test_pkey);
105 did_document = json_loads (did_document_str, JSON_DECODE_ANY, NULL);
106 GNUNET_assert (json_equal (test_did_document, did_document) == 1);
107 json_decref (did_document);
108 GNUNET_free (did_document_str);
109}
110
111int
112main ()
113{
114 // Setup key
115 test_skey.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
116 memcpy (&(test_skey.eddsa_key),
117 test_skey_bytes,
118 sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
119 GNUNET_CRYPTO_key_get_public (&test_skey, &test_pkey);
120
121 // Setup did document
122 GNUNET_asprintf (&test_did_document_str,
123 test_did_document_format_str,
124 test_did,
125 test_did,
126 test_did,
127 test_multibase_key);
128 test_did_document = json_loads (test_did_document_str, JSON_DECODE_ANY, NULL);
129
130 // Do tests
131 test_GNUNET_DID_pkey_to_did ();
132 test_GNUNET_DID_did_to_pkey ();
133 test_GNUNET_DID_pkey_to_did_document ();
134 test_GNUNET_DID_key_convert_gnunet_to_multibase_base64 ();
135 json_decref (test_did_document);
136 return 0;
137}
diff --git a/src/reclaim/test_reclaim.conf b/src/reclaim/test_reclaim.conf
deleted file mode 100644
index faa195ae1..000000000
--- a/src/reclaim/test_reclaim.conf
+++ /dev/null
@@ -1,38 +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[zonemaster]
17START_ON_DEMAND = YES
18IMMEDIATE_START = YES
19
20[reclaim]
21START_ON_DEMAND = YES
22TICKET_REFRESH_INTERVAL = 1 h
23#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=$GNUNET_TMP/idplog
24
25[gns]
26#PREFIX = valgrind --leak-check=full --track-origins=yes
27START_ON_DEMAND = YES
28AUTO_IMPORT_PKEY = YES
29MAX_PARALLEL_BACKGROUND_QUERIES = 10
30DEFAULT_LOOKUP_TIMEOUT = 15 s
31RECORD_PUT_INTERVAL = 1 h
32ZONE_PUBLISH_TIME_WINDOW = 1 h
33DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
34
35[reclaim-rest-plugin]
36address = http://localhost:8000/#/login
37psw = mysupersecretpassword
38expiration_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 acbcda62d..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
5int
6main (int argc, char *argv[])
7{
8 struct GNUNET_RECLAIM_AttributeList *al;
9 struct GNUNET_RECLAIM_AttributeList *al_two;
10 struct GNUNET_RECLAIM_AttributeListEntry *ale;
11 char attrname[100];
12 char attrdata[100];
13 size_t ser_len_claimed;
14 size_t ser_len_actual;
15 char *ser_data;
16 int count = 0;
17
18 al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
19 for (int i = 0; i < 12; i++)
20 {
21 memset (attrname, 0, 100);
22 memset (attrdata, 0, 100);
23 sprintf (attrname, "attr%d", i);
24 sprintf (attrdata, "%d", i);
25 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
26 ale->attribute = GNUNET_RECLAIM_attribute_new (attrname,
27 &GNUNET_RECLAIM_ID_ZERO,
28 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
29 attrdata,
30 strlen (attrdata));
31 GNUNET_CONTAINER_DLL_insert (al->list_head,
32 al->list_tail,
33 ale);
34 }
35 ser_len_claimed = GNUNET_RECLAIM_attribute_list_serialize_get_size (al);
36 ser_data = GNUNET_malloc (ser_len_claimed);
37 ser_len_actual = GNUNET_RECLAIM_attribute_list_serialize (al,
38 ser_data);
39 GNUNET_assert (ser_len_claimed == ser_len_actual);
40 al_two = GNUNET_RECLAIM_attribute_list_deserialize (ser_data,
41 ser_len_actual);
42 for (ale = al_two->list_head; NULL != ale; ale = ale->next)
43 count++;
44 GNUNET_assert (12 == count);
45 //GNUNET_assert (-1 != deser_len);
46 GNUNET_free (ser_data);
47 GNUNET_RECLAIM_attribute_list_destroy (al);
48 GNUNET_RECLAIM_attribute_list_destroy (al_two);
49}
diff --git a/src/reclaim/test_reclaim_attribute.sh b/src/reclaim/test_reclaim_attribute.sh
deleted file mode 100755
index 17f7863d4..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
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 8a88136c6..000000000
--- a/src/reclaim/test_reclaim_consume.sh
+++ /dev/null
@@ -1,49 +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 2>&1 && 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-arm -I
29gnunet-identity -C testego -c test_reclaim.conf
30gnunet-identity -C rpego -c test_reclaim.conf
31SUBJECT_KEY=$(gnunet-identity -d -e rpego -q -c test_reclaim.conf)
32TEST_KEY=$(gnunet-identity -d -e testego -q -c test_reclaim.conf)
33gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
34gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf
35TICKET=$(gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf | awk '{print $1}')
36gnunet-namestore -z testego -D -c test_reclaim.conf
37gnunet-identity -d -c test_reclaim.conf
38sleep 1
39gnunet-reclaim -e rpego -C $TICKET -c test_reclaim.conf
40
41RES=$?
42gnunet-identity -D testego -c test_reclaim.conf
43gnunet-identity -D rpego -c test_reclaim.conf
44gnunet-arm -e -c test_reclaim.conf
45if test $RES != 0
46then
47 echo "Failed."
48fi
49
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 63140e54c..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 2>&1 && 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
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 da091a1ee..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 2&>1 && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_reclaim.conf >/dev/null 2&>1
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 >/dev/null 2&>1
55
56gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf
57#gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf >/dev/null 2&>1
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
diff --git a/src/reclaim/test_w3c_ed25519_2020.c b/src/reclaim/test_w3c_ed25519_2020.c
deleted file mode 100644
index e2534e6ab..000000000
--- a/src/reclaim/test_w3c_ed25519_2020.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2021 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/**
23 * @file src/did/test_w3c_ed25519_2020.c
24 * @brief Testcases for the w3c Ed25519 formats for SSIs https://w3c-ccg.github.io/lds-ed25519-2020
25 * @author Martin Schanzenbach
26 */
27
28#include "platform.h"
29#include "gnunet_crypto_lib.h"
30#include "gnunet_strings_lib.h"
31
32static char test_privkey[32] = {
33 0x9b, 0x93, 0x7b, 0x81, 0x32, 0x2d, 0x81, 0x6c,
34 0xfa, 0xb9, 0xd5, 0xa3, 0xba, 0xac, 0xc9, 0xb2,
35 0xa5, 0xfe, 0xbe, 0x4b, 0x14, 0x9f, 0x12, 0x6b,
36 0x36, 0x30, 0xf9, 0x3a, 0x29, 0x52, 0x70, 0x17
37};
38
39static char *targetPublicKeyMultibase = "u7QEJX5oaWV3edV2CeGhkrQPfpaT71ogyVmNk4rZeE8yeRA";
40
41int
42main ()
43{
44 struct GNUNET_CRYPTO_EddsaPrivateKey privkey;
45 struct GNUNET_CRYPTO_EddsaPublicKey pubkey;
46
47 memcpy (&privkey, test_privkey, sizeof (privkey));
48 GNUNET_CRYPTO_eddsa_key_get_public (&privkey, &pubkey);
49
50 //This is how to convert out pubkeys to W3c Ed25519-2020 multibase (base64url no padding)
51 char *b64;
52 char pkx[34];
53 pkx[0] = 0xed;
54 pkx[1] = 0x01;
55 memcpy (pkx+2, &pubkey, sizeof (pubkey));
56 GNUNET_STRINGS_base64url_encode (pkx,
57 sizeof (pkx),
58 &b64);
59 printf ("u%s\n%s\n", b64, targetPublicKeyMultibase);
60 // FIXME convert pubkey to target
61 char *res;
62 GNUNET_asprintf (&res, "u%s", b64);
63 GNUNET_assert (0 == strcmp (res,
64 targetPublicKeyMultibase));
65
66 GNUNET_free (b64);
67 GNUNET_free (res);
68 return 0;
69}