aboutsummaryrefslogtreecommitdiff
path: root/src/service/reclaim
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/reclaim')
-rw-r--r--src/service/reclaim/.gitignore5
-rw-r--r--src/service/reclaim/Makefile.am102
-rw-r--r--src/service/reclaim/did.h49
-rw-r--r--src/service/reclaim/did_core.c270
-rw-r--r--src/service/reclaim/did_core.h138
-rw-r--r--src/service/reclaim/did_helper.c203
-rw-r--r--src/service/reclaim/did_helper.h74
-rw-r--r--src/service/reclaim/did_misc.c70
-rw-r--r--src/service/reclaim/gnunet-service-reclaim.c2782
-rw-r--r--src/service/reclaim/gnunet-service-reclaim_tickets.c1915
-rw-r--r--src/service/reclaim/gnunet-service-reclaim_tickets.h282
-rw-r--r--src/service/reclaim/meson.build65
-rw-r--r--src/service/reclaim/reclaim.conf22
-rw-r--r--src/service/reclaim/reclaim.h606
-rw-r--r--src/service/reclaim/reclaim_api.c1736
-rw-r--r--src/service/reclaim/reclaim_attribute.c547
-rw-r--r--src/service/reclaim/reclaim_attribute.h83
-rw-r--r--src/service/reclaim/reclaim_credential.c1003
-rw-r--r--src/service/reclaim/reclaim_credential.h119
-rw-r--r--src/service/reclaim/test_did_helper.c137
-rw-r--r--src/service/reclaim/test_reclaim_attribute.c49
-rw-r--r--src/service/reclaim/test_w3c_ed25519_2020.c69
22 files changed, 10326 insertions, 0 deletions
diff --git a/src/service/reclaim/.gitignore b/src/service/reclaim/.gitignore
new file mode 100644
index 000000000..e22aa5011
--- /dev/null
+++ b/src/service/reclaim/.gitignore
@@ -0,0 +1,5 @@
1gnunet-reclaim
2gnunet-service-reclaim
3gnunet-did
4test_did_helper
5test_reclaim_attribute
diff --git a/src/service/reclaim/Makefile.am b/src/service/reclaim/Makefile.am
new file mode 100644
index 000000000..4b745cb37
--- /dev/null
+++ b/src/service/reclaim/Makefile.am
@@ -0,0 +1,102 @@
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
12EXTRA_DIST = \
13 reclaim.conf
14
15pkgcfgdir= $(pkgdatadir)/config.d/
16
17libexecdir= $(pkglibdir)/libexec/
18
19pkgcfg_DATA = \
20 reclaim.conf
21
22lib_LTLIBRARIES = \
23 libgnunetreclaim.la \
24 libgnunetdid.la
25
26libexec_PROGRAMS = \
27 gnunet-service-reclaim
28
29gnunet_service_reclaim_SOURCES = \
30 gnunet-service-reclaim.c \
31 gnunet-service-reclaim_tickets.c \
32 gnunet-service-reclaim_tickets.h
33gnunet_service_reclaim_LDADD = \
34 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
35 $(top_builddir)/src/service/identity/libgnunetidentity.la \
36 $(top_builddir)/src/lib/util/libgnunetutil.la \
37 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
38 $(top_builddir)/src/service/statistics/libgnunetstatistics.la \
39 libgnunetreclaim.la \
40 $(top_builddir)/src/service/gns/libgnunetgns.la \
41 $(GN_LIBINTL)
42
43libgnunetreclaim_la_SOURCES = \
44 reclaim_api.c \
45 reclaim.h \
46 reclaim_attribute.c \
47 reclaim_attribute.h \
48 reclaim_credential.c \
49 reclaim_credential.h
50libgnunetreclaim_la_LIBADD = \
51 $(top_builddir)/src/lib/util/libgnunetutil.la \
52 $(top_builddir)/src/service/identity/libgnunetidentity.la \
53 $(GN_LIBINTL) $(XLIB)
54libgnunetreclaim_la_LDFLAGS = \
55 $(GN_LIB_LDFLAGS) \
56 -version-info 0:0:0
57
58libgnunetdid_la_SOURCES = \
59 did_helper.c \
60 did_helper.h \
61 did_core.h \
62 did_core.c
63libgnunetdid_la_LIBADD = \
64 $(top_builddir)/src/lib/util/libgnunetutil.la \
65 $(top_builddir)/src/service/gns/libgnunetgns.la \
66 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
67 $(top_builddir)/src/service/identity/libgnunetidentity.la \
68 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
69 -ljansson \
70 $(GN_LIBINTL) $(XLIB)
71libgnunetdid_la_LDFLAGS = \
72 $(GN_LIB_LDFLAGS) \
73 -version-info 0:0:0
74
75test_reclaim_attribute_SOURCES = \
76 test_reclaim_attribute.c
77test_reclaim_attribute_LDADD = \
78 $(top_builddir)/src/lib/util/libgnunetutil.la \
79 libgnunetreclaim.la \
80 $(GN_LIBINTL)
81
82test_did_helper_SOURCES = \
83 test_did_helper.c
84test_did_helper_LDADD = \
85 $(top_builddir)/src/lib/util/libgnunetutil.la \
86 $(top_builddir)/src/service/gns/libgnunetgns.la \
87 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
88 $(top_builddir)/src/service/identity/libgnunetidentity.la \
89 $(top_builddir)/src/service/namestore/libgnunetnamestore.la \
90 libgnunetdid.la \
91 -ljansson
92
93check_PROGRAMS = \
94 test_reclaim_attribute \
95 test_did_helper
96
97if ENABLE_TEST_RUN
98 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
99 TESTS = \
100 $(check_SCRIPTS) \
101 $(check_PROGRAMS)
102endif
diff --git a/src/service/reclaim/did.h b/src/service/reclaim/did.h
new file mode 100644
index 000000000..ab1b65925
--- /dev/null
+++ b/src/service/reclaim/did.h
@@ -0,0 +1,49 @@
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/service/reclaim/did_core.c b/src/service/reclaim/did_core.c
new file mode 100644
index 000000000..5804a0d7e
--- /dev/null
+++ b/src/service/reclaim/did_core.c
@@ -0,0 +1,270 @@
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 "did_core.h"
31
32struct DID_resolve_return
33{
34 DID_resolve_callback *cb;
35 void *cls;
36};
37
38struct DID_action_return
39{
40 DID_action_callback *cb;
41 void *cls;
42};
43
44// ------------------------------------------------ //
45// -------------------- Resolve ------------------- //
46// ------------------------------------------------ //
47
48/**
49 * @brief GNS lookup callback. Calls the given callback function
50 * and gives it the DID Document.
51 * Fails if there is more than one DID record.
52 *
53 * @param cls closure
54 * @param rd_count number of records in rd
55 * @param rd the records in the reply
56 */
57static void
58DID_resolve_gns_lookup_cb (
59 void *cls,
60 uint32_t rd_count,
61 const struct GNUNET_GNSRECORD_Data *rd)
62{
63 char *did_document;
64 DID_resolve_callback *cb = ((struct DID_resolve_return *) cls)->cb;
65 void *cls_did_resolve_cb = ((struct DID_resolve_return *) cls)->cls;
66 free (cls);
67
68 for (int i = 0; i < rd_count; i++)
69 {
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/**
82 * @brief Resolve a DID.
83 * Calls the given callback function with the resolved DID Document and the given closure.
84 * If the did can not be resolved did_document is NULL.
85 *
86 * @param did DID that is resolve
87 */
88enum GNUNET_GenericReturnValue
89DID_resolve (const char *did,
90 struct GNUNET_GNS_Handle *gns_handle,
91 DID_resolve_callback *cont,
92 void *cls)
93{
94 struct GNUNET_CRYPTO_PublicKey pkey;
95
96 // did, gns_handle and cont must me set
97 if ((did == NULL) || (gns_handle == NULL) || (cont == NULL))
98 return GNUNET_NO;
99
100 if (GNUNET_OK != DID_did_to_pkey (did, &pkey))
101 return GNUNET_NO;
102
103 // Create closure for lookup callback
104 struct DID_resolve_return *cls_gns_lookup_cb
105 = malloc (sizeof(struct DID_resolve_return));
106 cls_gns_lookup_cb->cb = cont;
107 cls_gns_lookup_cb->cls = cls;
108
109 GNUNET_GNS_lookup (gns_handle,
110 DID_DOCUMENT_LABEL,
111 &pkey,
112 GNUNET_GNSRECORD_TYPE_DID_DOCUMENT,
113 GNUNET_GNS_LO_DEFAULT,
114 &DID_resolve_gns_lookup_cb,
115 cls_gns_lookup_cb);
116
117 return GNUNET_OK;
118}
119
120
121// ------------------------------------------------ //
122// -------------------- Create -------------------- //
123// ------------------------------------------------ //
124
125static void
126DID_create_did_store_cb (void *cls,
127 enum GNUNET_ErrorCode ec)
128{
129 DID_action_callback *cb = ((struct DID_action_return *) cls)->cb;
130 void *cls_did_create_cb = ((struct DID_action_return *) cls)->cls;
131 free (cls);
132
133 if (GNUNET_EC_NONE == ec)
134 {
135 cb (GNUNET_OK, (void *) cls_did_create_cb);
136 }
137 else
138 {
139 // TODO: Log emsg. Not writing it to STDOUT
140 printf ("%s\n", GNUNET_ErrorCode_get_hint (ec));
141 cb (GNUNET_NO, (void *) cls_did_create_cb);
142 }
143}
144
145
146struct DID_create_namestore_lookup_closure
147{
148 const char *did_document;
149 struct GNUNET_TIME_Relative expire_time;
150 struct GNUNET_NAMESTORE_Handle *namestore_handle;
151 struct DID_action_return *ret;
152};
153
154static void
155DID_create_namestore_lookup_cb (void *cls,
156 const struct
157 GNUNET_CRYPTO_PrivateKey *zone,
158 const char *label,
159 unsigned int rd_count,
160 const struct GNUNET_GNSRECORD_Data *rd)
161{
162 struct GNUNET_GNSRECORD_Data record_data;
163 struct GNUNET_CRYPTO_PublicKey pkey;
164
165 const char *did_document
166 = ((struct DID_create_namestore_lookup_closure *) cls)->did_document;
167
168 const struct GNUNET_TIME_Relative expire_time
169 = ((struct DID_create_namestore_lookup_closure *) cls)->expire_time;
170
171 struct GNUNET_NAMESTORE_Handle *namestore_handle
172 = ((struct DID_create_namestore_lookup_closure *) cls)->namestore_handle;
173
174 struct DID_action_return *cls_record_store_cb
175 = ((struct DID_create_namestore_lookup_closure *) cls)->ret;
176
177 free (cls);
178
179 if (rd_count > 0)
180 {
181 printf ("Ego already has a DID Document. Abort.\n");
182 cls_record_store_cb->cb (GNUNET_NO, cls_record_store_cb->cls);
183 }
184 else
185 {
186 // Get public key
187 GNUNET_CRYPTO_key_get_public (zone, &pkey);
188
189 // If no DID Document is given a default one is created
190 if (did_document != NULL)
191 printf (
192 "DID Docuement is read from \"DID-document\" argument (EXPERIMENTAL)\n");
193 else
194 did_document = DID_pkey_to_did_document (&pkey);
195
196 // Create record
197 record_data.data = did_document;
198 record_data.expiration_time = expire_time.rel_value_us;
199 record_data.data_size = strlen (did_document) + 1;
200 record_data.record_type = GNUNET_GNSRECORD_typename_to_number ("TXT"),
201 record_data.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
202
203 // Store record
204 GNUNET_NAMESTORE_record_set_store (namestore_handle,
205 zone,
206 DID_DOCUMENT_LABEL,
207 1, // FIXME what if GNUNET_GNS_EMPTY_LABEL_AT has records
208 &record_data,
209 &DID_create_did_store_cb,
210 (void *) cls_record_store_cb);
211 }
212}
213
214
215/**
216 * @brief Creates a DID and saves DID Document in Namestore.
217 *
218 * @param ego ego for which the DID should be created.
219 * @param did_document did_document that should be saved in namestore.
220 * If did_document==NULL -> Default DID document is created.
221 * @param namestore_handle
222 * @param cont callback function
223 * @param cls closure
224 */
225enum GNUNET_GenericReturnValue
226DID_create (const struct GNUNET_IDENTITY_Ego *ego,
227 const char *did_document,
228 const struct GNUNET_TIME_Relative *expire_time,
229 struct GNUNET_NAMESTORE_Handle *namestore_handle,
230 DID_action_callback *cont,
231 void *cls)
232{
233 struct GNUNET_CRYPTO_PublicKey pkey;
234
235 // Ego, namestore_handle and cont must be set
236 if ((ego == NULL) || (namestore_handle == NULL) || (cont == NULL))
237 return GNUNET_NO;
238
239 // Check if ego has EdDSA key
240 GNUNET_IDENTITY_ego_get_public_key ((struct GNUNET_IDENTITY_Ego *) ego,
241 &pkey);
242 if (ntohl (pkey.type) != GNUNET_GNSRECORD_TYPE_EDKEY)
243 {
244 printf ("The EGO has to have an EdDSA key pair\n");
245 return GNUNET_NO;
246 }
247
248 struct DID_action_return *ret
249 = malloc (sizeof(struct DID_action_return));
250 ret->cb = cont;
251 ret->cls = cls;
252
253 struct DID_create_namestore_lookup_closure *cls_name_store_lookup_cb
254 = malloc (sizeof(struct DID_create_namestore_lookup_closure));
255 cls_name_store_lookup_cb->did_document = did_document;
256 cls_name_store_lookup_cb->expire_time = (*expire_time);
257 cls_name_store_lookup_cb->namestore_handle = namestore_handle;
258 cls_name_store_lookup_cb->ret = ret;
259
260 // Check if ego already has a DID Document
261 GNUNET_NAMESTORE_records_lookup (namestore_handle,
262 GNUNET_IDENTITY_ego_get_private_key (ego),
263 DID_DOCUMENT_LABEL,
264 NULL,
265 NULL,
266 DID_create_namestore_lookup_cb,
267 (void *) cls_name_store_lookup_cb);
268
269 return GNUNET_OK;
270}
diff --git a/src/service/reclaim/did_core.h b/src/service/reclaim/did_core.h
new file mode 100644
index 000000000..842424e14
--- /dev/null
+++ b/src/service/reclaim/did_core.h
@@ -0,0 +1,138 @@
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/service/reclaim/did_helper.c b/src/service/reclaim/did_helper.c
new file mode 100644
index 000000000..3aac027ee
--- /dev/null
+++ b/src/service/reclaim/did_helper.c
@@ -0,0 +1,203 @@
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/service/reclaim/did_helper.h b/src/service/reclaim/did_helper.h
new file mode 100644
index 000000000..d61992c68
--- /dev/null
+++ b/src/service/reclaim/did_helper.h
@@ -0,0 +1,74 @@
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/service/reclaim/did_misc.c b/src/service/reclaim/did_misc.c
new file mode 100644
index 000000000..32b127b2b
--- /dev/null
+++ b/src/service/reclaim/did_misc.c
@@ -0,0 +1,70 @@
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/service/reclaim/gnunet-service-reclaim.c b/src/service/reclaim/gnunet-service-reclaim.c
new file mode 100644
index 000000000..c381a5aaf
--- /dev/null
+++ b/src/service/reclaim/gnunet-service-reclaim.c
@@ -0,0 +1,2782 @@
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#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet-service-reclaim_tickets.h"
28#include "gnunet_gnsrecord_lib.h"
29#include "gnunet_protocols.h"
30#include "gnunet_reclaim_lib.h"
31#include "gnunet_reclaim_service.h"
32#include "reclaim.h"
33
34
35/**
36 * Namestore handle
37 */
38static struct GNUNET_NAMESTORE_Handle *nsh;
39
40/**
41 * Timeout task
42 */
43static struct GNUNET_SCHEDULER_Task *timeout_task;
44
45/**
46 * Our configuration.
47 */
48static const struct GNUNET_CONFIGURATION_Handle *cfg;
49
50/**
51 * An idp client
52 */
53struct IdpClient;
54
55/**
56 * A ticket iteration operation.
57 */
58struct TicketIteration
59{
60 /**
61 * DLL
62 */
63 struct TicketIteration *next;
64
65 /**
66 * DLL
67 */
68 struct TicketIteration *prev;
69
70 /**
71 * Client which intiated this zone iteration
72 */
73 struct IdpClient *client;
74
75 /**
76 * The operation id for the iteration in the response for the client
77 */
78 uint32_t r_id;
79
80 /**
81 * The ticket iterator
82 */
83 struct RECLAIM_TICKETS_Iterator *iter;
84};
85
86
87/**
88 * An attribute iteration operation.
89 */
90struct Iterator
91{
92 /**
93 * Next element in the DLL
94 */
95 struct Iterator *next;
96
97 /**
98 * Previous element in the DLL
99 */
100 struct Iterator *prev;
101
102 /**
103 * IDP client which intiated this zone iteration
104 */
105 struct IdpClient *client;
106
107 /**
108 * Key of the zone we are iterating over.
109 */
110 struct GNUNET_CRYPTO_PrivateKey identity;
111
112 /**
113 * Namestore iterator
114 */
115 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
116
117 /**
118 * The operation id for the zone iteration in the response for the client
119 */
120 uint32_t request_id;
121
122 /**
123 * Context
124 */
125 void *ctx;
126};
127
128
129/**
130 * An idp client
131 */
132struct IdpClient
133{
134 /**
135 * DLL
136 */
137 struct IdpClient *prev;
138
139 /**
140 * DLL
141 */
142 struct IdpClient *next;
143
144 /**
145 * The client
146 */
147 struct GNUNET_SERVICE_Client *client;
148
149 /**
150 * Message queue for transmission to @e client
151 */
152 struct GNUNET_MQ_Handle *mq;
153
154 /**
155 * Head of the DLL of
156 * Attribute iteration operations in
157 * progress initiated by this client
158 */
159 struct Iterator *attr_iter_head;
160
161 /**
162 * Tail of the DLL of
163 * Attribute iteration operations
164 * in progress initiated by this client
165 */
166 struct Iterator *attr_iter_tail;
167
168 /**
169 * Head of the DLL of
170 * Credential iteration operations in
171 * progress initiated by this client
172 */
173 struct Iterator *cred_iter_head;
174
175 /**
176 * Tail of the DLL of
177 * Credential iteration operations
178 * in progress initiated by this client
179 */
180 struct Iterator *cred_iter_tail;
181
182 /**
183 * Head of DLL of ticket iteration ops
184 */
185 struct TicketIteration *ticket_iter_head;
186
187 /**
188 * Tail of DLL of ticket iteration ops
189 */
190 struct TicketIteration *ticket_iter_tail;
191
192 /**
193 * Head of DLL of ticket revocation ops
194 */
195 struct TicketRevocationOperation *revoke_op_head;
196
197 /**
198 * Tail of DLL of ticket revocation ops
199 */
200 struct TicketRevocationOperation *revoke_op_tail;
201
202 /**
203 * Head of DLL of ticket issue ops
204 */
205 struct TicketIssueOperation *issue_op_head;
206
207 /**
208 * Tail of DLL of ticket issue ops
209 */
210 struct TicketIssueOperation *issue_op_tail;
211
212 /**
213 * Head of DLL of ticket consume ops
214 */
215 struct ConsumeTicketOperation *consume_op_head;
216
217 /**
218 * Tail of DLL of ticket consume ops
219 */
220 struct ConsumeTicketOperation *consume_op_tail;
221
222 /**
223 * Head of DLL of attribute store ops
224 */
225 struct AttributeStoreHandle *store_op_head;
226
227 /**
228 * Tail of DLL of attribute store ops
229 */
230 struct AttributeStoreHandle *store_op_tail;
231 /**
232 * Head of DLL of attribute delete ops
233 */
234 struct AttributeDeleteHandle *delete_op_head;
235
236 /**
237 * Tail of DLL of attribute delete ops
238 */
239 struct AttributeDeleteHandle *delete_op_tail;
240};
241
242
243/**
244 * Handle for attribute deletion request
245 */
246struct AttributeDeleteHandle
247{
248 /**
249 * DLL
250 */
251 struct AttributeDeleteHandle *next;
252
253 /**
254 * DLL
255 */
256 struct AttributeDeleteHandle *prev;
257
258 /**
259 * Client connection
260 */
261 struct IdpClient *client;
262
263 /**
264 * Identity
265 */
266 struct GNUNET_CRYPTO_PrivateKey identity;
267
268
269 /**
270 * QueueEntry
271 */
272 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
273
274 /**
275 * Iterator
276 */
277 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
278
279 /**
280 * The attribute to delete
281 */
282 struct GNUNET_RECLAIM_Attribute *claim;
283
284 /**
285 * The credential to delete
286 */
287 struct GNUNET_RECLAIM_Credential *credential;
288
289 /**
290 * Tickets to update
291 */
292 struct TicketRecordsEntry *tickets_to_update_head;
293
294 /**
295 * Tickets to update
296 */
297 struct TicketRecordsEntry *tickets_to_update_tail;
298
299 /**
300 * Existing attributes
301 */
302 struct GNUNET_RECLAIM_AttributeList *existing_attributes;
303
304 /**
305 * Existing credentials
306 */
307 struct GNUNET_RECLAIM_CredentialList *existing_credentials;
308
309 /**
310 * Attribute label
311 */
312 char *label;
313
314 /**
315 * request id
316 */
317 uint32_t r_id;
318};
319
320
321/**
322 * Handle for attribute store request
323 */
324struct AttributeStoreHandle
325{
326 /**
327 * DLL
328 */
329 struct AttributeStoreHandle *next;
330
331 /**
332 * DLL
333 */
334 struct AttributeStoreHandle *prev;
335
336 /**
337 * Client connection
338 */
339 struct IdpClient *client;
340
341 /**
342 * Identity
343 */
344 struct GNUNET_CRYPTO_PrivateKey identity;
345
346 /**
347 * Identity pubkey
348 */
349 struct GNUNET_CRYPTO_PublicKey identity_pkey;
350
351 /**
352 * QueueEntry
353 */
354 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
355
356 /**
357 * The attribute to store
358 */
359 struct GNUNET_RECLAIM_Attribute *claim;
360
361 /**
362 * The credential to store
363 */
364 struct GNUNET_RECLAIM_Credential *credential;
365
366 /**
367 * The attribute expiration interval
368 */
369 struct GNUNET_TIME_Relative exp;
370
371 /**
372 * request id
373 */
374 uint32_t r_id;
375};
376
377
378/**
379 * Handle for ticket consume request
380 */
381struct ConsumeTicketOperation
382{
383 /**
384 * DLL
385 */
386 struct ConsumeTicketOperation *next;
387
388 /**
389 * DLL
390 */
391 struct ConsumeTicketOperation *prev;
392
393 /**
394 * Client connection
395 */
396 struct IdpClient *client;
397
398 /**
399 * request id
400 */
401 uint32_t r_id;
402
403 /**
404 * Ticket consume handle
405 */
406 struct RECLAIM_TICKETS_ConsumeHandle *ch;
407};
408
409
410/**
411 * Ticket revocation request handle
412 */
413struct TicketRevocationOperation
414{
415 /**
416 * DLL
417 */
418 struct TicketRevocationOperation *prev;
419
420 /**
421 * DLL
422 */
423 struct TicketRevocationOperation *next;
424
425 /**
426 * Client connection
427 */
428 struct IdpClient *client;
429
430 /**
431 * Revocation handle
432 */
433 struct RECLAIM_TICKETS_RevokeHandle *rh;
434
435 /**
436 * request id
437 */
438 uint32_t r_id;
439};
440
441
442/**
443 * Ticket issue operation handle
444 */
445struct TicketIssueOperation
446{
447 /**
448 * DLL
449 */
450 struct TicketIssueOperation *prev;
451
452 /**
453 * DLL
454 */
455 struct TicketIssueOperation *next;
456
457 /**
458 * Client connection
459 */
460 struct IdpClient *client;
461
462 /**
463 * request id
464 */
465 uint32_t r_id;
466};
467
468
469/**
470 * Client list
471 */
472static struct IdpClient *client_list_head = NULL;
473
474/**
475 * Client list
476 */
477static struct IdpClient *client_list_tail = NULL;
478
479
480/**
481 * Cleanup attribute delete handle
482 *
483 * @param adh the attribute to cleanup
484 */
485static void
486cleanup_adh (struct AttributeDeleteHandle *adh)
487{
488 struct TicketRecordsEntry *le;
489
490 if (NULL != adh->ns_it)
491 GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
492 if (NULL != adh->ns_qe)
493 GNUNET_NAMESTORE_cancel (adh->ns_qe);
494 if (NULL != adh->label)
495 GNUNET_free (adh->label);
496 if (NULL != adh->claim)
497 GNUNET_free (adh->claim);
498 if (NULL != adh->credential)
499 GNUNET_free (adh->credential);
500 if (NULL != adh->existing_credentials)
501 GNUNET_RECLAIM_credential_list_destroy (adh->existing_credentials);
502 if (NULL != adh->existing_attributes)
503 GNUNET_RECLAIM_attribute_list_destroy (adh->existing_attributes);
504 while (NULL != (le = adh->tickets_to_update_head))
505 {
506 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
507 adh->tickets_to_update_tail,
508 le);
509 if (NULL != le->label)
510 GNUNET_free (le->label);
511 if (NULL != le->data)
512 GNUNET_free (le->data);
513 GNUNET_free (le);
514 }
515 GNUNET_free (adh);
516}
517
518
519/**
520 * Cleanup attribute store handle
521 *
522 * @param ash handle to clean up
523 */
524static void
525cleanup_as_handle (struct AttributeStoreHandle *ash)
526{
527 if (NULL != ash->ns_qe)
528 GNUNET_NAMESTORE_cancel (ash->ns_qe);
529 if (NULL != ash->claim)
530 GNUNET_free (ash->claim);
531 if (NULL != ash->credential)
532 GNUNET_free (ash->credential);
533 GNUNET_free (ash);
534}
535
536
537/**
538 * Cleanup client
539 *
540 * @param idp the client to clean up
541 */
542static void
543cleanup_client (struct IdpClient *idp)
544{
545 struct Iterator *ai;
546 struct TicketIteration *ti;
547 struct TicketRevocationOperation *rop;
548 struct TicketIssueOperation *iss;
549 struct ConsumeTicketOperation *ct;
550 struct AttributeStoreHandle *as;
551 struct AttributeDeleteHandle *adh;
552
553 while (NULL != (iss = idp->issue_op_head))
554 {
555 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
556 GNUNET_free (iss);
557 }
558 while (NULL != (ct = idp->consume_op_head))
559 {
560 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
561 idp->consume_op_tail,
562 ct);
563 if (NULL != ct->ch)
564 RECLAIM_TICKETS_consume_cancel (ct->ch);
565 GNUNET_free (ct);
566 }
567 while (NULL != (as = idp->store_op_head))
568 {
569 GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
570 cleanup_as_handle (as);
571 }
572 while (NULL != (adh = idp->delete_op_head))
573 {
574 GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
575 cleanup_adh (adh);
576 }
577
578 while (NULL != (ai = idp->attr_iter_head))
579 {
580 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
581 GNUNET_free (ai);
582 }
583 while (NULL != (ai = idp->cred_iter_head))
584 {
585 GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
586 ai);
587 GNUNET_free (ai);
588 }
589
590 while (NULL != (rop = idp->revoke_op_head))
591 {
592 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
593 if (NULL != rop->rh)
594 RECLAIM_TICKETS_revoke_cancel (rop->rh);
595 GNUNET_free (rop);
596 }
597 while (NULL != (ti = idp->ticket_iter_head))
598 {
599 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
600 idp->ticket_iter_tail,
601 ti);
602 if (NULL != ti->iter)
603 RECLAIM_TICKETS_iteration_stop (ti->iter);
604 GNUNET_free (ti);
605 }
606 GNUNET_free (idp);
607}
608
609
610/**
611 * Cleanup task
612 */
613static void
614cleanup ()
615{
616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
617
618 RECLAIM_TICKETS_deinit ();
619 if (NULL != timeout_task)
620 GNUNET_SCHEDULER_cancel (timeout_task);
621 if (NULL != nsh)
622 GNUNET_NAMESTORE_disconnect (nsh);
623}
624
625
626/**
627 * Shutdown task
628 *
629 * @param cls NULL
630 */
631static void
632do_shutdown (void *cls)
633{
634 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
635 cleanup ();
636}
637
638
639/**
640 * Sends a ticket result message to the client
641 *
642 * @param client the client to send to
643 * @param r_id the request message ID to reply to
644 * @param ticket the ticket to include (may be NULL)
645 * @param success the success status of the request
646 */
647static void
648send_ticket_result (const struct IdpClient *client,
649 uint32_t r_id,
650 const struct GNUNET_RECLAIM_Ticket *ticket,
651 const struct GNUNET_RECLAIM_PresentationList *presentations,
652 uint32_t success)
653{
654 struct TicketResultMessage *irm;
655 struct GNUNET_MQ_Envelope *env;
656 size_t pres_len = 0;
657 size_t tkt_len = 0;
658 char *buf;
659
660 if (NULL != presentations)
661 {
662 pres_len =
663 GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
664 }
665 if (NULL != ticket)
666 tkt_len = strlen (ticket->gns_name) + 1;
667 env = GNUNET_MQ_msg_extra (irm,
668 pres_len + tkt_len,
669 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
670 buf = (char*) &irm[1];
671 if (NULL != ticket)
672 {
673 memcpy (buf, ticket, tkt_len);
674 buf += tkt_len;
675 }
676 // TODO add success member
677 irm->id = htonl (r_id);
678 irm->tkt_len = htons (tkt_len);
679 irm->rp_uri_len = htons (0);
680 irm->presentations_len = htons (pres_len);
681 if (NULL != presentations)
682 {
683 GNUNET_RECLAIM_presentation_list_serialize (presentations,
684 buf);
685 }
686 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
687 GNUNET_MQ_send (client->mq, env);
688}
689
690
691/**
692 * Issue ticket result
693 *
694 * @param cls out ticket issue operation handle
695 * @param ticket the issued ticket
696 * @param presentations newly created credential presentations (NULL on error)
697 * @param success issue success status (GNUNET_OK if successful)
698 * @param emsg error message (NULL of success is GNUNET_OK)
699 */
700static void
701issue_ticket_result_cb (void *cls,
702 struct GNUNET_RECLAIM_Ticket *ticket,
703 struct GNUNET_RECLAIM_PresentationList *presentations,
704 int32_t success,
705 const char *emsg)
706{
707 struct TicketIssueOperation *tio = cls;
708
709 if (GNUNET_OK != success)
710 {
711 send_ticket_result (tio->client, tio->r_id, NULL, NULL, GNUNET_SYSERR);
712 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
713 tio->client->issue_op_tail,
714 tio);
715 GNUNET_free (tio);
716 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
717 return;
718 }
719 send_ticket_result (tio->client, tio->r_id,
720 ticket, presentations, GNUNET_SYSERR);
721 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
722 tio->client->issue_op_tail,
723 tio);
724 GNUNET_free (tio);
725}
726
727
728/**
729 * Check issue ticket message
730 *
731 * @param cls unused
732 * @param im message to check
733 * @return GNUNET_OK if message is ok
734 */
735static int
736check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
737{
738 uint16_t size;
739 size_t attrs_len;
740 size_t key_len;
741 size_t rp_len;
742
743 size = ntohs (im->header.size);
744 attrs_len = ntohs (im->attr_len);
745 key_len = ntohs (im->key_len);
746 rp_len = ntohs (im->rp_uri_len);
747 if (size != attrs_len + key_len + rp_len + sizeof(struct
748 IssueTicketMessage))
749 {
750 GNUNET_break (0);
751 return GNUNET_SYSERR;
752 }
753 return GNUNET_OK;
754}
755
756
757/**
758 * Handle ticket issue message
759 *
760 * @param cls our client
761 * @param im the message
762 */
763static void
764handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
765{
766 struct TicketIssueOperation *tio;
767 struct IdpClient *idp = cls;
768 struct GNUNET_RECLAIM_AttributeList *attrs;
769 struct GNUNET_RECLAIM_AttributeListEntry *le;
770 struct GNUNET_CRYPTO_PrivateKey identity;
771 const char *rp;
772 size_t attrs_len;
773 size_t key_len;
774 size_t rp_len;
775 size_t read;
776 char *buf;
777
778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
779 key_len = ntohs (im->key_len);
780 buf = (char *) &im[1];
781 if ((GNUNET_SYSERR ==
782 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
783 &identity, &read)) ||
784 (read != key_len))
785 {
786 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
787 "Failed to read private key\n");
788 GNUNET_SERVICE_client_drop (idp->client);
789 return;
790 }
791 buf += read;
792 rp_len = ntohs (im->rp_uri_len);
793 rp = buf;
794 buf += rp_len;
795 tio = GNUNET_new (struct TicketIssueOperation);
796 attrs_len = ntohs (im->attr_len);
797 attrs = GNUNET_RECLAIM_attribute_list_deserialize (buf,
798 attrs_len);
799 for (le = attrs->list_head; NULL != le; le = le->next)
800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
801 "List entry: %s\n", le->attribute->name);
802
803 tio->r_id = ntohl (im->id);
804 tio->client = idp;
805 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
806 RECLAIM_TICKETS_issue (&identity,
807 attrs,
808 rp,
809 &issue_ticket_result_cb,
810 tio);
811 GNUNET_SERVICE_client_continue (idp->client);
812 GNUNET_RECLAIM_attribute_list_destroy (attrs);
813}
814
815
816/**********************************************************
817* Revocation
818**********************************************************/
819
820/**
821 * Handles revocation result
822 *
823 * @param cls our revocation operation handle
824 * @param success revocation result (GNUNET_OK if successful)
825 */
826static void
827revoke_result_cb (void *cls, int32_t success)
828{
829 struct TicketRevocationOperation *rop = cls;
830 struct GNUNET_MQ_Envelope *env;
831 struct RevokeTicketResultMessage *trm;
832
833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
834 "Sending REVOKE_TICKET_RESULT message\n");
835 rop->rh = NULL;
836 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
837 trm->id = htonl (rop->r_id);
838 trm->success = htonl (success);
839 GNUNET_MQ_send (rop->client->mq, env);
840 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
841 rop->client->revoke_op_tail,
842 rop);
843 GNUNET_free (rop);
844}
845
846
847/**
848 * Check revocation message format
849 *
850 * @param cls unused
851 * @param rm the message to check
852 * @return GNUNET_OK if message is ok
853 */
854static int
855check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
856{
857 uint16_t size;
858 size_t key_len;
859 size_t tkt_len;
860
861 size = ntohs (rm->header.size);
862 key_len = ntohs (rm->key_len);
863 tkt_len = ntohs (rm->tkt_len);
864
865 if (size != sizeof(struct RevokeTicketMessage) + key_len + tkt_len)
866 {
867 GNUNET_break (0);
868 return GNUNET_SYSERR;
869 }
870 return GNUNET_OK;
871}
872
873
874/**
875 * Handle a revocation message to a ticket.
876 *
877 * @param cls our client
878 * @param rm the message to handle
879 */
880static void
881handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
882{
883 struct TicketRevocationOperation *rop;
884 struct IdpClient *idp = cls;
885 struct GNUNET_CRYPTO_PrivateKey identity;
886 struct GNUNET_RECLAIM_Ticket *ticket;
887 size_t key_len;
888 size_t read;
889 char *buf;
890
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
892 key_len = ntohs (rm->key_len);
893 buf = (char *) &rm[1];
894 if ((GNUNET_SYSERR ==
895 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
896 &identity, &read)) ||
897 (read != key_len))
898 {
899 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
900 "Failed to read private key\n");
901 GNUNET_SERVICE_client_drop (idp->client);
902 return;
903 }
904 buf += read;
905 ticket = (struct GNUNET_RECLAIM_Ticket *) buf;
906 rop = GNUNET_new (struct TicketRevocationOperation);
907 rop->r_id = ntohl (rm->id);
908 rop->client = idp;
909 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
910 rop->rh
911 = RECLAIM_TICKETS_revoke (ticket, &identity, &revoke_result_cb, rop);
912 GNUNET_SERVICE_client_continue (idp->client);
913}
914
915
916/**
917 * Handle a ticket consume result
918 *
919 * @param cls our consume ticket operation handle
920 * @param identity the attribute authority
921 * @param attrs the attribute/claim list
922 * @param success GNUNET_OK if successful
923 * @param emsg error message (NULL if success=GNUNET_OK)
924 */
925static void
926consume_result_cb (void *cls,
927 const struct GNUNET_CRYPTO_PublicKey *identity,
928 const struct GNUNET_RECLAIM_AttributeList *attrs,
929 const struct GNUNET_RECLAIM_PresentationList *presentations,
930 int32_t success,
931 const char *emsg)
932{
933 struct ConsumeTicketOperation *cop = cls;
934 struct ConsumeTicketResultMessage *crm;
935 struct GNUNET_MQ_Envelope *env;
936 char *data_tmp;
937 size_t attrs_len = 0;
938 size_t pres_len = 0;
939 size_t key_len;
940 ssize_t written;
941
942 if (GNUNET_OK != success)
943 {
944 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
945 }
946 attrs_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
947 pres_len = GNUNET_RECLAIM_presentation_list_serialize_get_size (
948 presentations);
949 key_len = GNUNET_CRYPTO_public_key_get_length (identity);
950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
951 "Sending CONSUME_TICKET_RESULT message\n");
952 env = GNUNET_MQ_msg_extra (crm,
953 attrs_len + pres_len + key_len,
954 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
955 crm->id = htonl (cop->r_id);
956 crm->attrs_len = htons (attrs_len);
957 crm->presentations_len = htons (pres_len);
958 crm->key_len = htons (key_len);
959 crm->result = htons (success);
960 data_tmp = (char *) &crm[1];
961 written = GNUNET_CRYPTO_write_public_key_to_buffer (identity,
962 data_tmp,
963 key_len);
964 GNUNET_assert (0 <= written);
965 data_tmp += written;
966 GNUNET_RECLAIM_attribute_list_serialize (attrs, data_tmp);
967 data_tmp += attrs_len;
968 GNUNET_RECLAIM_presentation_list_serialize (presentations, data_tmp);
969 GNUNET_MQ_send (cop->client->mq, env);
970 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
971 cop->client->consume_op_tail,
972 cop);
973 GNUNET_free (cop);
974}
975
976
977/**
978 * Check a consume ticket message
979 *
980 * @param cls unused
981 * @param cm the message to handle
982 */
983static int
984check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
985{
986 uint16_t size;
987 uint16_t tkt_size;
988 uint16_t rp_uri_size;
989
990 size = ntohs (cm->header.size);
991 tkt_size = ntohs (cm->tkt_len);
992 rp_uri_size = ntohs (cm->rp_uri_len);
993 if (size < sizeof(struct ConsumeTicketMessage) + tkt_size + rp_uri_size)
994 {
995 GNUNET_break (0);
996 return GNUNET_SYSERR;
997 }
998 return GNUNET_OK;
999}
1000
1001
1002/**
1003 * Handle a consume ticket message
1004 *
1005 * @param cls our client handle
1006 * @param cm the message to handle
1007 */
1008static void
1009handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
1010{
1011 struct ConsumeTicketOperation *cop;
1012 struct IdpClient *idp = cls;
1013 struct GNUNET_RECLAIM_Ticket *ticket;
1014 char *buf;
1015 const char *rp_uri;
1016
1017 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
1018 buf = (char*) &cm[1];
1019 ticket = (struct GNUNET_RECLAIM_Ticket *) buf;
1020 rp_uri = buf + ntohs (cm->tkt_len);
1021 cop = GNUNET_new (struct ConsumeTicketOperation);
1022 cop->r_id = ntohl (cm->id);
1023 cop->client = idp;
1024 cop->ch
1025 = RECLAIM_TICKETS_consume (ticket,
1026 rp_uri,
1027 &consume_result_cb,
1028 cop);
1029 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
1030 GNUNET_SERVICE_client_continue (idp->client);
1031}
1032
1033
1034/*****************************************
1035* Attribute store
1036*****************************************/
1037
1038
1039/**
1040 * Attribute store result handler
1041 *
1042 * @param cls our attribute store handle
1043 * @param success GNUNET_OK if successful
1044 * @param emsg error message (NULL if success=GNUNET_OK)
1045 */
1046static void
1047attr_store_cont (void *cls, enum GNUNET_ErrorCode ec)
1048{
1049 struct AttributeStoreHandle *ash = cls;
1050 struct GNUNET_MQ_Envelope *env;
1051 struct SuccessResultMessage *acr_msg;
1052
1053 ash->ns_qe = NULL;
1054 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1055 ash->client->store_op_tail,
1056 ash);
1057
1058 if (GNUNET_EC_NONE != ec)
1059 {
1060 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1061 "Failed to store attribute %s\n",
1062 GNUNET_ErrorCode_get_hint (ec));
1063 cleanup_as_handle (ash);
1064 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1065 return;
1066 }
1067
1068 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1069 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1070 acr_msg->id = htonl (ash->r_id);
1071 acr_msg->op_result = htonl (GNUNET_OK);
1072 GNUNET_MQ_send (ash->client->mq, env);
1073 cleanup_as_handle (ash);
1074}
1075
1076
1077/**
1078 * Add a new attribute
1079 *
1080 * @param cls the AttributeStoreHandle
1081 */
1082static void
1083attr_store_task (void *cls)
1084{
1085 struct AttributeStoreHandle *ash = cls;
1086 struct GNUNET_GNSRECORD_Data rd[1];
1087 char *buf;
1088 char *label;
1089 size_t buf_size;
1090
1091 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
1092 buf_size = GNUNET_RECLAIM_attribute_serialize_get_size (ash->claim);
1093 buf = GNUNET_malloc (buf_size);
1094 // Give the ash a new id if unset
1095 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->claim->id))
1096 GNUNET_RECLAIM_id_generate (&ash->claim->id);
1097 GNUNET_RECLAIM_attribute_serialize (ash->claim, buf);
1098 label
1099 = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id,
1100 sizeof (ash->claim->id));
1101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1102
1103 rd[0].data_size = buf_size;
1104 rd[0].data = buf;
1105 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE;
1106 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1107 rd[0].expiration_time = ash->exp.rel_value_us;
1108 ash->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
1109 &ash->identity,
1110 label,
1111 1,
1112 rd,
1113 &attr_store_cont,
1114 ash);
1115 GNUNET_free (buf);
1116 GNUNET_free (label);
1117}
1118
1119
1120/**
1121 * Check an attribute store message
1122 *
1123 * @param cls unused
1124 * @param sam the message to check
1125 */
1126static int
1127check_attribute_store_message (void *cls,
1128 const struct AttributeStoreMessage *sam)
1129{
1130 uint16_t size;
1131
1132 size = ntohs (sam->header.size);
1133 if (size <= sizeof(struct AttributeStoreMessage))
1134 {
1135 GNUNET_break (0);
1136 return GNUNET_SYSERR;
1137 }
1138 return GNUNET_OK;
1139}
1140
1141
1142/**
1143 * Handle an attribute store message
1144 *
1145 * @param cls our client
1146 * @param sam the message to handle
1147 */
1148static void
1149handle_attribute_store_message (void *cls,
1150 const struct AttributeStoreMessage *sam)
1151{
1152 struct AttributeStoreHandle *ash;
1153 struct IdpClient *idp = cls;
1154 struct GNUNET_CRYPTO_PrivateKey identity;
1155 size_t data_len;
1156 size_t key_len;
1157 size_t read;
1158 char *buf;
1159
1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1161
1162 data_len = ntohs (sam->attr_len);
1163 key_len = ntohs (sam->key_len);
1164 buf = (char *) &sam[1];
1165 if ((GNUNET_SYSERR ==
1166 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1167 &identity, &read)) ||
1168 (read != key_len))
1169 {
1170 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1171 "Failed to read private key\n");
1172 GNUNET_SERVICE_client_drop (idp->client);
1173 return;
1174 }
1175 buf += read;
1176 ash = GNUNET_new (struct AttributeStoreHandle);
1177 GNUNET_RECLAIM_attribute_deserialize (buf,
1178 data_len,
1179 &ash->claim);
1180
1181 ash->r_id = ntohl (sam->id);
1182 ash->identity = identity;
1183 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1184 GNUNET_CRYPTO_key_get_public (&identity, &ash->identity_pkey);
1185
1186 GNUNET_SERVICE_client_continue (idp->client);
1187 ash->client = idp;
1188 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1189 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1190}
1191
1192
1193/**
1194 * Credential store result handler
1195 *
1196 * @param cls our attribute store handle
1197 * @param success GNUNET_OK if successful
1198 * @param emsg error message (NULL if success=GNUNET_OK)
1199 */
1200static void
1201cred_store_cont (void *cls, enum GNUNET_ErrorCode ec)
1202{
1203 struct AttributeStoreHandle *ash = cls;
1204 struct GNUNET_MQ_Envelope *env;
1205 struct SuccessResultMessage *acr_msg;
1206
1207 ash->ns_qe = NULL;
1208 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1209 ash->client->store_op_tail,
1210 ash);
1211
1212 if (GNUNET_EC_NONE != ec)
1213 {
1214 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1215 "Failed to store credential: %s\n",
1216 GNUNET_ErrorCode_get_hint (ec));
1217 cleanup_as_handle (ash);
1218 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1219 return;
1220 }
1221
1222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1223 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1224 acr_msg->id = htonl (ash->r_id);
1225 acr_msg->op_result = htonl (GNUNET_OK);
1226 GNUNET_MQ_send (ash->client->mq, env);
1227 cleanup_as_handle (ash);
1228}
1229
1230
1231/**
1232 * Error looking up potential credential. Abort.
1233 *
1234 * @param cls our attribute store handle
1235 */
1236static void
1237cred_error (void *cls)
1238{
1239 struct AttributeStoreHandle *ash = cls;
1240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1241 "Failed to check for existing credential.\n");
1242 cleanup_as_handle (ash);
1243 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1244 return;
1245}
1246
1247
1248/**
1249* Check for existing record before storing credential
1250*
1251* @param cls our attribute store handle
1252* @param zone zone we are iterating
1253* @param label label of the records
1254* @param rd_count record count
1255* @param rd records
1256*/
1257static void
1258cred_add_cb (void *cls,
1259 const struct GNUNET_CRYPTO_PrivateKey *zone,
1260 const char *label,
1261 unsigned int rd_count,
1262 const struct GNUNET_GNSRECORD_Data *rd)
1263{
1264 struct AttributeStoreHandle *ash = cls;
1265 struct GNUNET_GNSRECORD_Data rd_new[1];
1266 char *buf;
1267 size_t buf_size;
1268
1269 buf_size = GNUNET_RECLAIM_credential_serialize_get_size (ash->credential);
1270 buf = GNUNET_malloc (buf_size);
1271 GNUNET_RECLAIM_credential_serialize (ash->credential, buf);
1272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1273 "Storing new credential under `%s'.\n",
1274 label);
1275 rd_new[0].data_size = buf_size;
1276 rd_new[0].data = buf;
1277 rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL;
1278 rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1279 rd_new[0].expiration_time = ash->exp.rel_value_us;
1280 ash->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
1281 &ash->identity,
1282 label,
1283 1,
1284 rd_new,
1285 &cred_store_cont,
1286 ash);
1287 GNUNET_free (buf);
1288 return;
1289}
1290
1291
1292/**
1293 * Add a new credential
1294 *
1295 * @param cls the AttributeStoreHandle
1296 */
1297static void
1298cred_store_task (void *cls)
1299{
1300 struct AttributeStoreHandle *ash = cls;
1301 char *label;
1302
1303 // Give the ash a new id if unset
1304 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->credential->id))
1305 GNUNET_RECLAIM_id_generate (&ash->credential->id);
1306 label = GNUNET_STRINGS_data_to_string_alloc (&ash->credential->id,
1307 sizeof (ash->credential->id));
1308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1309 "Looking up existing data under label `%s'\n", label);
1310 ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1311 &ash->identity,
1312 label,
1313 &cred_error,
1314 ash,
1315 &cred_add_cb,
1316 ash);
1317 GNUNET_free (label);
1318}
1319
1320
1321/**
1322 * Check an credential store message
1323 *
1324 * @param cls unused
1325 * @param sam the message to check
1326 */
1327static int
1328check_credential_store_message (void *cls,
1329 const struct AttributeStoreMessage *sam)
1330{
1331 uint16_t size;
1332
1333 size = ntohs (sam->header.size);
1334 if (size <= sizeof(struct AttributeStoreMessage))
1335 {
1336 GNUNET_break (0);
1337 return GNUNET_SYSERR;
1338 }
1339 return GNUNET_OK;
1340}
1341
1342
1343/**
1344* Handle a credential store message
1345*
1346* @param cls our client
1347* @param sam the message to handle
1348*/
1349static void
1350handle_credential_store_message (void *cls,
1351 const struct AttributeStoreMessage *sam)
1352{
1353 struct AttributeStoreHandle *ash;
1354 struct IdpClient *idp = cls;
1355 struct GNUNET_CRYPTO_PrivateKey identity;
1356 size_t data_len;
1357 size_t key_len;
1358 size_t read;
1359 char *buf;
1360
1361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_STORE message\n");
1362
1363 data_len = ntohs (sam->attr_len);
1364 key_len = ntohs (sam->key_len);
1365 buf = (char *) &sam[1];
1366 if ((GNUNET_SYSERR ==
1367 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1368 &identity, &read)) ||
1369 (read != key_len))
1370 {
1371 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1372 "Failed to read private key\n");
1373 GNUNET_SERVICE_client_drop (idp->client);
1374 return;
1375 }
1376 buf += read;
1377 ash = GNUNET_new (struct AttributeStoreHandle);
1378 ash->credential = GNUNET_RECLAIM_credential_deserialize (buf,
1379 data_len);
1380
1381 ash->r_id = ntohl (sam->id);
1382 ash->identity = identity;
1383 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1384 GNUNET_CRYPTO_key_get_public (&identity, &ash->identity_pkey);
1385
1386 GNUNET_SERVICE_client_continue (idp->client);
1387 ash->client = idp;
1388 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1389 GNUNET_SCHEDULER_add_now (&cred_store_task, ash);
1390}
1391
1392
1393/**
1394 * Send a deletion success response
1395 *
1396 * @param adh our attribute deletion handle
1397 * @param success the success status
1398 */
1399static void
1400send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1401{
1402 struct GNUNET_MQ_Envelope *env;
1403 struct SuccessResultMessage *acr_msg;
1404
1405 GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1406 adh->client->delete_op_tail,
1407 adh);
1408
1409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1410 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1411 acr_msg->id = htonl (adh->r_id);
1412 acr_msg->op_result = htonl (success);
1413 GNUNET_MQ_send (adh->client->mq, env);
1414}
1415
1416
1417/**
1418 * Namestore iteration within attribute deletion.
1419 * We need to reissue tickets with the deleted attribute removed.
1420 *
1421 * @param cls our attribute deletion handle
1422 * @param zone the private key of the ticket issuer
1423 * @param label the label of the record
1424 * @param rd_count number of records
1425 * @param rd record data
1426 */
1427static void
1428consistency_iter (void *cls,
1429 const struct GNUNET_CRYPTO_PrivateKey *zone,
1430 const char *label,
1431 unsigned int rd_count,
1432 const struct GNUNET_GNSRECORD_Data *rd)
1433{
1434 struct AttributeDeleteHandle *adh = cls;
1435 struct TicketRecordsEntry *le;
1436 struct GNUNET_RECLAIM_AttributeListEntry *ale;
1437 struct GNUNET_RECLAIM_CredentialListEntry *cle;
1438 int is_ticket = GNUNET_NO;
1439 for (int i = 0; i < rd_count; i++)
1440 {
1441 switch (rd[i].record_type)
1442 {
1443 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
1444 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1445 GNUNET_RECLAIM_attribute_deserialize (rd[i].data,
1446 rd[i].data_size,
1447 &ale->attribute);
1448 GNUNET_CONTAINER_DLL_insert (adh->existing_attributes->list_head,
1449 adh->existing_attributes->list_tail,
1450 ale);
1451 break;
1452 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
1453 cle = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
1454 cle->credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
1455 rd[i].data_size);
1456 GNUNET_CONTAINER_DLL_insert (adh->existing_credentials->list_head,
1457 adh->existing_credentials->list_tail,
1458 cle);
1459 break;
1460 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
1461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1462 "Ticket to delete found (%s)\n",
1463 label);
1464 is_ticket = GNUNET_YES;
1465 break;
1466 default:
1467 break;
1468 }
1469 if (GNUNET_YES == is_ticket)
1470 break;
1471 }
1472 if (GNUNET_YES == is_ticket)
1473 {
1474 le = GNUNET_new (struct TicketRecordsEntry);
1475 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1476 le->data = GNUNET_malloc (le->data_size);
1477 le->rd_count = rd_count;
1478 le->label = GNUNET_strdup (label);
1479 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1480 GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1481 adh->tickets_to_update_tail,
1482 le);
1483 }
1484 GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1485}
1486
1487
1488/**
1489 * Recursion prototype for function
1490 * @param cls our deletion handle
1491 */
1492static void
1493update_tickets (void *cls);
1494
1495
1496/**
1497 * Callback called when a ticket was updated
1498 *
1499 * @param cls our attribute deletion handle
1500 * @param success GNUNET_OK if successful
1501 * @param emsg error message (NULL if success=GNUNET_OK)
1502 */
1503static void
1504ticket_updated (void *cls, enum GNUNET_ErrorCode ec)
1505{
1506 struct AttributeDeleteHandle *adh = cls;
1507
1508 adh->ns_qe = NULL;
1509 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1510}
1511
1512
1513/**
1514 * Update tickets: Remove shared attribute which has just been deleted.
1515 * This method is called recursively until all tickets are processed.
1516 * Eventually, the updated tickets are stored using ``update_tickets''.
1517 *
1518 * @param cls our attribute deletion handle
1519 */
1520static void
1521update_tickets (void *cls)
1522{
1523 struct AttributeDeleteHandle *adh = cls;
1524 struct TicketRecordsEntry *le;
1525
1526 if (NULL == adh->tickets_to_update_head)
1527 {
1528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1529 "Finished updating tickets, success\n");
1530 send_delete_response (adh, GNUNET_OK);
1531 cleanup_adh (adh);
1532 return;
1533 }
1534 le = adh->tickets_to_update_head;
1535 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1536 adh->tickets_to_update_tail,
1537 le);
1538 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1539 struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1540 if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
1541 le->data,
1542 le->rd_count,
1543 rd))
1544 {
1545 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1546 "Unable to deserialize record data!\n");
1547 send_delete_response (adh, GNUNET_SYSERR);
1548 cleanup_adh (adh);
1549 return;
1550 }
1551 int j = 0;
1552 int i = 0;
1553 struct GNUNET_RECLAIM_AttributeListEntry *ale;
1554 struct GNUNET_RECLAIM_CredentialListEntry *cle;
1555 struct GNUNET_RECLAIM_Presentation *presentation;
1556 for (i = 0; i < le->rd_count; i++)
1557 {
1558 switch (rd[i].record_type)
1559 {
1560 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
1561 for (ale = adh->existing_attributes->list_head; NULL != ale; ale =
1562 ale->next)
1563 {
1564 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1565 &ale->attribute->id))
1566 {
1567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1568 "Found attribute %s, readding...\n",
1569 ale->attribute->name);
1570 rd_new[j] = rd[i];
1571 j++;
1572 break; // Found and added
1573 }
1574 }
1575 break;
1576 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
1577 presentation = GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1578 rd[i].data_size);
1579 for (cle = adh->existing_credentials->list_head; NULL != cle; cle =
1580 cle->next)
1581 {
1582 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (
1583 &presentation->credential_id,
1584 &cle->credential->id))
1585 {
1586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1587 "Found presentation for credential %s, readding...\n",
1588 cle->credential->name);
1589 rd_new[j] = rd[i];
1590 j++;
1591 break; // Found and added
1592 }
1593 }
1594 GNUNET_free (presentation);
1595 break;
1596 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
1597 rd_new[j] = rd[i];
1598 j++;
1599 break; // Found and added
1600 default:
1601 GNUNET_break (0);
1602 }
1603 }
1604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1605 "Updating ticket with %d entries (%d before)...\n",
1606 j, i);
1607 adh->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
1608 &adh->identity,
1609 le->label,
1610 j,
1611 rd_new,
1612 &ticket_updated,
1613 adh);
1614 GNUNET_free (le->label);
1615 GNUNET_free (le->data);
1616 GNUNET_free (le);
1617}
1618
1619
1620/**
1621 * Delete all attributes which reference credentials
1622 * that no longer exist
1623 */
1624static void
1625purge_attributes (void *cls);;
1626
1627static void
1628offending_attr_delete_cont (void *cls, enum GNUNET_ErrorCode ec)
1629{
1630 struct AttributeDeleteHandle *adh = cls;
1631
1632 adh->ns_qe = NULL;
1633 if (GNUNET_EC_NONE != ec)
1634 {
1635 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1636 "Error deleting attribute %s\n",
1637 adh->label);
1638 send_delete_response (adh, GNUNET_SYSERR);
1639 cleanup_adh (adh);
1640 return;
1641 }
1642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Continuing consistency check...\n");
1643 GNUNET_SCHEDULER_add_now (&purge_attributes, adh);
1644}
1645
1646
1647/**
1648 * Delete all attributes which reference credentials
1649 * that no longer exist
1650 */
1651static void
1652purge_attributes (void *cls)
1653{
1654 struct AttributeDeleteHandle *adh = cls;
1655 struct GNUNET_RECLAIM_AttributeListEntry *ale;
1656 struct GNUNET_RECLAIM_CredentialListEntry *cle;
1657
1658 for (ale = adh->existing_attributes->list_head; NULL != ale; ale = ale->next)
1659 {
1660 if (GNUNET_YES ==
1661 GNUNET_RECLAIM_id_is_zero (&ale->attribute->credential))
1662 continue;
1663
1664 for (cle = adh->existing_credentials->list_head;
1665 NULL != cle; cle = cle->next)
1666 {
1667 if (GNUNET_YES !=
1668 GNUNET_RECLAIM_id_is_equal (&cle->credential->id,
1669 &ale->attribute->credential))
1670 continue;
1671 break;
1672 }
1673 if (NULL == cle)
1674 {
1675 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1676 "Found attribute with missing credential\n");
1677 break;
1678 }
1679 }
1680 if (NULL == ale)
1681 {
1682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1683 "Attributes consistent, updating tickets.\n");
1684 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1685 return;
1686 }
1687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1688 "Attributes inconsistent, deleting offending attribute.\n");
1689 char *label
1690 = GNUNET_STRINGS_data_to_string_alloc (&ale->attribute->id,
1691 sizeof(ale->attribute->id));
1692
1693 adh->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
1694 &adh->identity,
1695 label,
1696 0,
1697 NULL,
1698 &offending_attr_delete_cont,
1699 adh);
1700 GNUNET_CONTAINER_DLL_remove (adh->existing_attributes->list_head,
1701 adh->existing_attributes->list_tail,
1702 ale);
1703 GNUNET_free (ale);
1704 GNUNET_free (label);
1705}
1706
1707
1708/**
1709 * Done collecting affected tickets, start updating.
1710 *
1711 * @param cls our attribute deletion handle
1712 */
1713static void
1714consistency_iter_fin (void *cls)
1715{
1716 struct AttributeDeleteHandle *adh = cls;
1717 adh->ns_it = NULL;
1718 GNUNET_SCHEDULER_add_now (&purge_attributes, adh);
1719}
1720
1721
1722/**
1723 * Error collecting affected tickets. Abort.
1724 *
1725 * @param cls our attribute deletion handle
1726 */
1727static void
1728consistency_iter_err (void *cls)
1729{
1730 struct AttributeDeleteHandle *adh = cls;
1731
1732 adh->ns_it = NULL;
1733 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1734 "Namestore error on consistency check\n");
1735 send_delete_response (adh, GNUNET_SYSERR);
1736 cleanup_adh (adh);
1737}
1738
1739
1740/**
1741 * Start processing tickets which may still contain reference to deleted
1742 * attribute.
1743 *
1744 * @param cls attribute deletion handle
1745 */
1746static void
1747start_consistency_update (void *cls)
1748{
1749 struct AttributeDeleteHandle *adh = cls;
1750
1751 adh->existing_attributes = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1752 adh->existing_credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1753
1754 adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1755 &adh->identity,
1756 &consistency_iter_err,
1757 adh,
1758 &consistency_iter,
1759 adh,
1760 &consistency_iter_fin,
1761 adh);
1762}
1763
1764
1765/**
1766 * Attribute deleted callback
1767 *
1768 * @param cls our handle
1769 * @param success success status
1770 * @param emsg error message (NULL if success=GNUNET_OK)
1771 */
1772static void
1773attr_delete_cont (void *cls, enum GNUNET_ErrorCode ec)
1774{
1775 struct AttributeDeleteHandle *adh = cls;
1776
1777 adh->ns_qe = NULL;
1778 if (GNUNET_EC_NONE != ec)
1779 {
1780 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1781 "Error deleting attribute %s\n",
1782 adh->label);
1783 send_delete_response (adh, GNUNET_SYSERR);
1784 cleanup_adh (adh);
1785 return;
1786 }
1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1788 GNUNET_SCHEDULER_add_now (&start_consistency_update, adh);
1789}
1790
1791
1792/**
1793 * Check attribute delete message format
1794 *
1795 * @param cls unused
1796 * @param dam message to check
1797 */
1798static int
1799check_attribute_delete_message (void *cls,
1800 const struct AttributeDeleteMessage *dam)
1801{
1802 uint16_t size;
1803
1804 size = ntohs (dam->header.size);
1805 if (size <= sizeof(struct AttributeDeleteMessage))
1806 {
1807 GNUNET_break (0);
1808 return GNUNET_SYSERR;
1809 }
1810 return GNUNET_OK;
1811}
1812
1813
1814/**
1815 * Handle attribute deletion
1816 *
1817 * @param cls our client
1818 * @param dam deletion message
1819 */
1820static void
1821handle_attribute_delete_message (void *cls,
1822 const struct AttributeDeleteMessage *dam)
1823{
1824 struct AttributeDeleteHandle *adh;
1825 struct IdpClient *idp = cls;
1826 struct GNUNET_CRYPTO_PrivateKey identity;
1827 size_t data_len;
1828 size_t key_len;
1829 size_t read;
1830 char *buf;
1831
1832 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1833
1834 data_len = ntohs (dam->attr_len);
1835 key_len = ntohs (dam->key_len);
1836 buf = (char *) &dam[1];
1837 if ((GNUNET_SYSERR ==
1838 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1839 &identity, &read)) ||
1840 (read != key_len))
1841 {
1842 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1843 "Failed to read private key\n");
1844 GNUNET_SERVICE_client_drop (idp->client);
1845 return;
1846 }
1847 buf += read;
1848 adh = GNUNET_new (struct AttributeDeleteHandle);
1849 GNUNET_RECLAIM_attribute_deserialize (buf,
1850 data_len,
1851 &adh->claim);
1852 adh->credential = NULL;
1853
1854 adh->r_id = ntohl (dam->id);
1855 adh->identity = identity;
1856 adh->label
1857 = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id,
1858 sizeof(adh->claim->id));
1859 GNUNET_SERVICE_client_continue (idp->client);
1860 adh->client = idp;
1861 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1862 adh->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
1863 &adh->identity,
1864 adh->label,
1865 0,
1866 NULL,
1867 &attr_delete_cont,
1868 adh);
1869}
1870
1871
1872/**
1873 * Credential deleted callback
1874 *
1875 * @param cls our handle
1876 * @param success success status
1877 * @param emsg error message (NULL if success=GNUNET_OK)
1878 */
1879static void
1880cred_delete_cont (void *cls, enum GNUNET_ErrorCode ec)
1881{
1882 struct AttributeDeleteHandle *adh = cls;
1883
1884 adh->ns_qe = NULL;
1885 if (GNUNET_EC_NONE != ec)
1886 {
1887 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1888 "Error deleting credential `%s'\n",
1889 adh->label);
1890 send_delete_response (adh, GNUNET_SYSERR);
1891 cleanup_adh (adh);
1892 return;
1893 }
1894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1895 GNUNET_SCHEDULER_add_now (&start_consistency_update, adh);
1896}
1897
1898
1899/**
1900 * Check credential delete message format
1901 *
1902 * @param cls unused
1903 * @param dam message to check
1904 */
1905static int
1906check_credential_delete_message (void *cls,
1907 const struct AttributeDeleteMessage *dam)
1908{
1909 uint16_t size;
1910
1911 size = ntohs (dam->header.size);
1912 if (size <= sizeof(struct AttributeDeleteMessage))
1913 {
1914 GNUNET_break (0);
1915 return GNUNET_SYSERR;
1916 }
1917 return GNUNET_OK;
1918}
1919
1920
1921/**
1922 * Handle credential deletion
1923 *
1924 * @param cls our client
1925 * @param dam deletion message
1926 */
1927static void
1928handle_credential_delete_message (void *cls,
1929 const struct AttributeDeleteMessage *dam)
1930{
1931 struct AttributeDeleteHandle *adh;
1932 struct IdpClient *idp = cls;
1933 struct GNUNET_CRYPTO_PrivateKey identity;
1934 size_t data_len;
1935 size_t key_len;
1936 size_t read;
1937 char *buf;
1938
1939 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_DELETE message\n");
1940
1941 data_len = ntohs (dam->attr_len);
1942 key_len = ntohs (dam->key_len);
1943 buf = (char *) &dam[1];
1944 if ((GNUNET_SYSERR ==
1945 GNUNET_CRYPTO_read_private_key_from_buffer (buf, key_len,
1946 &identity, &read)) ||
1947 (read != key_len))
1948 {
1949 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1950 "Failed to read private key\n");
1951 GNUNET_SERVICE_client_drop (idp->client);
1952 return;
1953 }
1954 buf += read;
1955 adh = GNUNET_new (struct AttributeDeleteHandle);
1956 adh->credential = GNUNET_RECLAIM_credential_deserialize (buf,
1957 data_len);
1958 adh->claim = NULL;
1959
1960 adh->r_id = ntohl (dam->id);
1961 adh->identity = identity;
1962 adh->label
1963 = GNUNET_STRINGS_data_to_string_alloc (&adh->credential->id,
1964 sizeof(adh->credential->id));
1965 GNUNET_SERVICE_client_continue (idp->client);
1966 adh->client = idp;
1967 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1968 adh->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
1969 &adh->identity,
1970 adh->label,
1971 0,
1972 NULL,
1973 &cred_delete_cont,
1974 adh);
1975}
1976
1977
1978/*************************************************
1979 * Attribute iteration
1980 *************************************************/
1981
1982
1983/**
1984 * Done iterating over attributes
1985 *
1986 * @param cls our iterator handle
1987 */
1988static void
1989attr_iter_finished (void *cls)
1990{
1991 struct Iterator *ai = cls;
1992 struct GNUNET_MQ_Envelope *env;
1993 struct AttributeResultMessage *arm;
1994
1995 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1996 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1997 arm->id = htonl (ai->request_id);
1998 arm->attr_len = htons (0);
1999 arm->pkey_len = htons (0);
2000 GNUNET_MQ_send (ai->client->mq, env);
2001 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
2002 ai->client->attr_iter_tail,
2003 ai);
2004 GNUNET_free (ai);
2005}
2006
2007
2008/**
2009 * Error iterating over attributes. Abort.
2010 *
2011 * @param cls our attribute iteration handle
2012 */
2013static void
2014attr_iter_error (void *cls)
2015{
2016 struct Iterator *ai = cls;
2017
2018 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
2019 attr_iter_finished (ai);
2020}
2021
2022
2023/**
2024 * Got record. Return if it is an attribute.
2025 *
2026 * @param cls our attribute iterator
2027 * @param zone zone we are iterating
2028 * @param label label of the records
2029 * @param rd_count record count
2030 * @param rd records
2031 */
2032static void
2033attr_iter_cb (void *cls,
2034 const struct GNUNET_CRYPTO_PrivateKey *zone,
2035 const char *label,
2036 unsigned int rd_count,
2037 const struct GNUNET_GNSRECORD_Data *rd)
2038{
2039 struct Iterator *ai = cls;
2040 struct GNUNET_MQ_Envelope *env;
2041 struct GNUNET_CRYPTO_PublicKey identity;
2042 char *data_tmp;
2043 size_t key_len;
2044 ssize_t written;
2045
2046 if ((rd_count != 1) ||
2047 (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd->record_type))
2048 {
2049 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2050 return;
2051 }
2052 struct AttributeResultMessage *arm;
2053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
2054 label);
2055 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2056 "Sending ATTRIBUTE_RESULT message\n");
2057 GNUNET_CRYPTO_key_get_public (zone, &identity);
2058 key_len = GNUNET_CRYPTO_public_key_get_length (&identity);
2059 env = GNUNET_MQ_msg_extra (arm,
2060 rd->data_size + key_len,
2061 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2062 arm->id = htonl (ai->request_id);
2063 arm->attr_len = htons (rd->data_size);
2064 data_tmp = (char *) &arm[1];
2065 arm->pkey_len = htons (key_len);
2066 written = GNUNET_CRYPTO_write_public_key_to_buffer (&identity,
2067 data_tmp,
2068 key_len);
2069 GNUNET_assert (0 <= written);
2070 data_tmp += written;
2071 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
2072 GNUNET_MQ_send (ai->client->mq, env);
2073}
2074
2075
2076static enum GNUNET_GenericReturnValue
2077check_iteration_start (
2078 void *cls,
2079 const struct AttributeIterationStartMessage *ais_msg)
2080{
2081 uint16_t size;
2082 size_t key_len;
2083
2084 size = ntohs (ais_msg->header.size);
2085 key_len = ntohs (ais_msg->key_len);
2086
2087 if (size < key_len + sizeof(*ais_msg))
2088 {
2089 GNUNET_break (0);
2090 return GNUNET_SYSERR;
2091 }
2092 return GNUNET_OK;
2093}
2094
2095
2096/**
2097 * Iterate over zone to get attributes
2098 *
2099 * @param cls our client
2100 * @param ais_msg the iteration message to start
2101 */
2102static void
2103handle_iteration_start (void *cls,
2104 const struct AttributeIterationStartMessage *ais_msg)
2105{
2106 struct IdpClient *idp = cls;
2107 struct Iterator *ai;
2108 struct GNUNET_CRYPTO_PrivateKey identity;
2109 size_t key_len;
2110 size_t read;
2111
2112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2113 "Received ATTRIBUTE_ITERATION_START message\n");
2114 key_len = ntohs (ais_msg->key_len);
2115 if ((GNUNET_SYSERR ==
2116 GNUNET_CRYPTO_read_private_key_from_buffer (&ais_msg[1],
2117 key_len,
2118 &identity,
2119 &read)) ||
2120 (read != key_len))
2121 {
2122 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2123 "Failed to read private key.\n");
2124 GNUNET_SERVICE_client_drop (idp->client);
2125 return;
2126 }
2127 ai = GNUNET_new (struct Iterator);
2128 ai->request_id = ntohl (ais_msg->id);
2129 ai->client = idp;
2130 ai->identity = identity;
2131
2132 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
2133 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
2134 &ai->identity,
2135 &attr_iter_error,
2136 ai,
2137 &attr_iter_cb,
2138 ai,
2139 &attr_iter_finished,
2140 ai);
2141 GNUNET_SERVICE_client_continue (idp->client);
2142}
2143
2144
2145/**
2146 * Handle iteration stop message from client
2147 *
2148 * @param cls the client
2149 * @param ais_msg the stop message
2150 */
2151static void
2152handle_iteration_stop (void *cls,
2153 const struct AttributeIterationStopMessage *ais_msg)
2154{
2155 struct IdpClient *idp = cls;
2156 struct Iterator *ai;
2157 uint32_t rid;
2158
2159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2160 "Received `%s' message\n",
2161 "ATTRIBUTE_ITERATION_STOP");
2162 rid = ntohl (ais_msg->id);
2163 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2164 if (ai->request_id == rid)
2165 break;
2166 if (NULL == ai)
2167 {
2168 GNUNET_break (0);
2169 GNUNET_SERVICE_client_drop (idp->client);
2170 return;
2171 }
2172 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
2173 GNUNET_free (ai);
2174 GNUNET_SERVICE_client_continue (idp->client);
2175}
2176
2177
2178/**
2179 * Client requests next attribute from iterator
2180 *
2181 * @param cls the client
2182 * @param ais_msg the message
2183 */
2184static void
2185handle_iteration_next (void *cls,
2186 const struct AttributeIterationNextMessage *ais_msg)
2187{
2188 struct IdpClient *idp = cls;
2189 struct Iterator *ai;
2190 uint32_t rid;
2191
2192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2193 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2194 rid = ntohl (ais_msg->id);
2195 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
2196 if (ai->request_id == rid)
2197 break;
2198 if (NULL == ai)
2199 {
2200 GNUNET_break (0);
2201 GNUNET_SERVICE_client_drop (idp->client);
2202 return;
2203 }
2204 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2205 GNUNET_SERVICE_client_continue (idp->client);
2206}
2207
2208
2209/*************************************************
2210 * Credential iteration
2211 *************************************************/
2212
2213
2214/**
2215 * Done iterating over credentials
2216 *
2217 * @param cls our iterator handle
2218 */
2219static void
2220cred_iter_finished (void *cls)
2221{
2222 struct Iterator *ai = cls;
2223 struct GNUNET_MQ_Envelope *env;
2224 struct CredentialResultMessage *arm;
2225
2226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CREDENTIAL_RESULT message\n");
2227 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
2228 arm->id = htonl (ai->request_id);
2229 arm->credential_len = htons (0);
2230 arm->key_len = htons (0);
2231 GNUNET_MQ_send (ai->client->mq, env);
2232 GNUNET_CONTAINER_DLL_remove (ai->client->cred_iter_head,
2233 ai->client->cred_iter_tail,
2234 ai);
2235 GNUNET_free (ai);
2236}
2237
2238
2239/**
2240 * Error iterating over credentials. Abort.
2241 *
2242 * @param cls our attribute iteration handle
2243 */
2244static void
2245cred_iter_error (void *cls)
2246{
2247 struct Iterator *ai = cls;
2248
2249 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over credentials\n");
2250 cred_iter_finished (ai);
2251}
2252
2253
2254/**
2255 * Got record. Return credential.
2256 *
2257 * @param cls our attribute iterator
2258 * @param zone zone we are iterating
2259 * @param label label of the records
2260 * @param rd_count record count
2261 * @param rd records
2262 */
2263static void
2264cred_iter_cb (void *cls,
2265 const struct GNUNET_CRYPTO_PrivateKey *zone,
2266 const char *label,
2267 unsigned int rd_count,
2268 const struct GNUNET_GNSRECORD_Data *rd)
2269{
2270 struct Iterator *ai = cls;
2271 struct GNUNET_MQ_Envelope *env;
2272 struct CredentialResultMessage *arm;
2273 struct GNUNET_CRYPTO_PublicKey identity;
2274 char *data_tmp;
2275 size_t key_len;
2276 ssize_t written;
2277
2278 if ((rd_count != 1) ||
2279 (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL != rd->record_type))
2280 {
2281 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2282 return;
2283 }
2284 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found credential under: %s\n",
2285 label);
2286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2287 "Sending CREDENTIAL_RESULT message\n");
2288 GNUNET_CRYPTO_key_get_public (zone, &identity);
2289 key_len = GNUNET_CRYPTO_public_key_get_length (&identity);
2290 env = GNUNET_MQ_msg_extra (arm,
2291 rd->data_size + key_len,
2292 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
2293 arm->id = htonl (ai->request_id);
2294 arm->credential_len = htons (rd->data_size);
2295 arm->key_len = htons (key_len);
2296 data_tmp = (char *) &arm[1];
2297 written = GNUNET_CRYPTO_write_public_key_to_buffer (&identity,
2298 data_tmp,
2299 key_len);
2300 GNUNET_assert (written >= 0);
2301 data_tmp += written;
2302 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
2303 GNUNET_MQ_send (ai->client->mq, env);
2304}
2305
2306
2307static enum GNUNET_GenericReturnValue
2308check_credential_iteration_start (
2309 void *cls,
2310 const struct CredentialIterationStartMessage *cis_msg)
2311{
2312 uint16_t size;
2313 size_t key_len;
2314
2315 size = ntohs (cis_msg->header.size);
2316 key_len = ntohs (cis_msg->key_len);
2317
2318 if (size < key_len + sizeof(*cis_msg))
2319 {
2320 GNUNET_break (0);
2321 return GNUNET_SYSERR;
2322 }
2323 return GNUNET_OK;
2324}
2325
2326
2327/**
2328 * Iterate over zone to get attributes
2329 *
2330 * @param cls our client
2331 * @param ais_msg the iteration message to start
2332 */
2333static void
2334handle_credential_iteration_start (void *cls,
2335 const struct
2336 CredentialIterationStartMessage *ais_msg)
2337{
2338 struct IdpClient *idp = cls;
2339 struct Iterator *ai;
2340 struct GNUNET_CRYPTO_PrivateKey identity;
2341 size_t key_len;
2342 size_t read;
2343
2344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2345 "Received CREDENTIAL_ITERATION_START message\n");
2346 key_len = ntohs (ais_msg->key_len);
2347 if ((GNUNET_SYSERR ==
2348 GNUNET_CRYPTO_read_private_key_from_buffer (&ais_msg[1],
2349 key_len,
2350 &identity,
2351 &read)) ||
2352 (read != key_len))
2353 {
2354 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2355 "Failed to read private key.\n");
2356 GNUNET_SERVICE_client_drop (idp->client);
2357 return;
2358 }
2359 ai = GNUNET_new (struct Iterator);
2360 ai->request_id = ntohl (ais_msg->id);
2361 ai->client = idp;
2362 ai->identity = identity;
2363
2364 GNUNET_CONTAINER_DLL_insert (idp->cred_iter_head, idp->cred_iter_tail,
2365 ai);
2366 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
2367 &ai->identity,
2368 &cred_iter_error,
2369 ai,
2370 &cred_iter_cb,
2371 ai,
2372 &cred_iter_finished,
2373 ai);
2374 GNUNET_SERVICE_client_continue (idp->client);
2375}
2376
2377
2378/**
2379 * Handle iteration stop message from client
2380 *
2381 * @param cls the client
2382 * @param ais_msg the stop message
2383 */
2384static void
2385handle_credential_iteration_stop (void *cls,
2386 const struct
2387 CredentialIterationStopMessage *ais_msg)
2388{
2389 struct IdpClient *idp = cls;
2390 struct Iterator *ai;
2391 uint32_t rid;
2392
2393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2394 "Received `%s' message\n",
2395 "CREDENTIAL_ITERATION_STOP");
2396 rid = ntohl (ais_msg->id);
2397 for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
2398 if (ai->request_id == rid)
2399 break;
2400 if (NULL == ai)
2401 {
2402 GNUNET_break (0);
2403 GNUNET_SERVICE_client_drop (idp->client);
2404 return;
2405 }
2406 GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
2407 ai);
2408 GNUNET_free (ai);
2409 GNUNET_SERVICE_client_continue (idp->client);
2410}
2411
2412
2413/**
2414 * Client requests next credential from iterator
2415 *
2416 * @param cls the client
2417 * @param ais_msg the message
2418 */
2419static void
2420handle_credential_iteration_next (void *cls,
2421 const struct
2422 CredentialIterationNextMessage *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 CREDENTIAL_ITERATION_NEXT message\n");
2430 rid = ntohl (ais_msg->id);
2431 for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
2432 if (ai->request_id == rid)
2433 break;
2434 if (NULL == ai)
2435 {
2436 GNUNET_break (0);
2437 GNUNET_SERVICE_client_drop (idp->client);
2438 return;
2439 }
2440 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2441 GNUNET_SERVICE_client_continue (idp->client);
2442}
2443
2444
2445/******************************************************
2446 * Ticket iteration
2447 ******************************************************/
2448
2449static void
2450ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket, const char*
2451 rp_uri)
2452{
2453 struct TicketIteration *ti = cls;
2454 struct GNUNET_MQ_Envelope *env;
2455 struct TicketResultMessage *trm;
2456 size_t tkt_len;
2457 size_t rp_uri_len;
2458
2459 if (NULL == ticket)
2460 tkt_len = 0;
2461 else
2462 tkt_len = strlen (ticket->gns_name) + 1;
2463
2464 if (NULL == rp_uri)
2465 rp_uri_len = 0;
2466 else
2467 rp_uri_len = strlen (rp_uri) + 1;
2468 env = GNUNET_MQ_msg_extra (trm,
2469 tkt_len + rp_uri_len,
2470 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
2471 if (NULL == ticket)
2472 {
2473 /* send empty response to indicate end of list */
2474 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2475 ti->client->ticket_iter_tail,
2476 ti);
2477 }
2478 else
2479 {
2480 memcpy (&trm[1], ticket, tkt_len);
2481 }
2482 memcpy ((char*) &trm[1] + tkt_len, rp_uri, rp_uri_len);
2483 trm->id = htonl (ti->r_id);
2484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
2485 trm->tkt_len = htons (tkt_len);
2486 trm->rp_uri_len = htons (rp_uri_len);
2487 trm->presentations_len = htons (0);
2488 GNUNET_MQ_send (ti->client->mq, env);
2489 if (NULL == ticket)
2490 GNUNET_free (ti);
2491}
2492
2493
2494static enum GNUNET_GenericReturnValue
2495check_ticket_iteration_start (
2496 void *cls,
2497 const struct TicketIterationStartMessage *tis_msg)
2498{
2499 uint16_t size;
2500 size_t key_len;
2501
2502 size = ntohs (tis_msg->header.size);
2503 key_len = ntohs (tis_msg->key_len);
2504
2505 if (size < key_len + sizeof(*tis_msg))
2506 {
2507 GNUNET_break (0);
2508 return GNUNET_SYSERR;
2509 }
2510 return GNUNET_OK;
2511}
2512
2513
2514/**
2515 * Client requests a ticket iteration
2516 *
2517 * @param cls the client
2518 * @param tis_msg the iteration request message
2519 */
2520static void
2521handle_ticket_iteration_start (
2522 void *cls,
2523 const struct TicketIterationStartMessage *tis_msg)
2524{
2525 struct GNUNET_CRYPTO_PrivateKey identity;
2526 struct IdpClient *client = cls;
2527 struct TicketIteration *ti;
2528 size_t key_len;
2529 size_t read;
2530
2531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2532 "Received TICKET_ITERATION_START message\n");
2533 key_len = ntohs (tis_msg->key_len);
2534 if ((GNUNET_SYSERR ==
2535 GNUNET_CRYPTO_read_private_key_from_buffer (&tis_msg[1],
2536 key_len,
2537 &identity,
2538 &read)) ||
2539 (read != key_len))
2540 {
2541 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2542 "Failed to read private key\n");
2543 GNUNET_SERVICE_client_drop (client->client);
2544 return;
2545 }
2546 ti = GNUNET_new (struct TicketIteration);
2547 ti->r_id = ntohl (tis_msg->id);
2548 ti->client = client;
2549 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2550 client->ticket_iter_tail,
2551 ti);
2552 ti->iter
2553 = RECLAIM_TICKETS_iteration_start (&identity, &ticket_iter_cb, ti);
2554 GNUNET_SERVICE_client_continue (client->client);
2555}
2556
2557
2558/**
2559 * Client has had enough tickets
2560 *
2561 * @param cls the client
2562 * @param tis_msg the stop message
2563 */
2564static void
2565handle_ticket_iteration_stop (void *cls,
2566 const struct TicketIterationStopMessage *tis_msg)
2567{
2568 struct IdpClient *client = cls;
2569 struct TicketIteration *ti;
2570 uint32_t rid;
2571
2572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2573 "Received `%s' message\n",
2574 "TICKET_ITERATION_STOP");
2575 rid = ntohl (tis_msg->id);
2576 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2577 if (ti->r_id == rid)
2578 break;
2579 if (NULL == ti)
2580 {
2581 GNUNET_break (0);
2582 GNUNET_SERVICE_client_drop (client->client);
2583 return;
2584 }
2585 RECLAIM_TICKETS_iteration_stop (ti->iter);
2586 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2587 client->ticket_iter_tail,
2588 ti);
2589 GNUNET_free (ti);
2590 GNUNET_SERVICE_client_continue (client->client);
2591}
2592
2593
2594/**
2595 * Client requests next result.
2596 *
2597 * @param cls the client
2598 * @param tis_msg the message
2599 */
2600static void
2601handle_ticket_iteration_next (void *cls,
2602 const struct TicketIterationNextMessage *tis_msg)
2603{
2604 struct IdpClient *client = cls;
2605 struct TicketIteration *ti;
2606 uint32_t rid;
2607
2608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2609 "Received TICKET_ITERATION_NEXT message\n");
2610 rid = ntohl (tis_msg->id);
2611 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2612 if (ti->r_id == rid)
2613 break;
2614 if (NULL == ti)
2615 {
2616 GNUNET_break (0);
2617 GNUNET_SERVICE_client_drop (client->client);
2618 return;
2619 }
2620 RECLAIM_TICKETS_iteration_next (ti->iter);
2621 GNUNET_SERVICE_client_continue (client->client);
2622}
2623
2624
2625/**
2626 * Main function that will be run
2627 *
2628 * @param cls closure
2629 * @param c the configuration used
2630 * @param server the service handle
2631 */
2632static void
2633run (void *cls,
2634 const struct GNUNET_CONFIGURATION_Handle *c,
2635 struct GNUNET_SERVICE_Handle *server)
2636{
2637 cfg = c;
2638
2639 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
2640 {
2641 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2642 "Unable to initialize TICKETS subsystem.\n");
2643 GNUNET_SCHEDULER_shutdown ();
2644 return;
2645 }
2646 // Connect to identity and namestore services
2647 nsh = GNUNET_NAMESTORE_connect (cfg);
2648 if (NULL == nsh)
2649 {
2650 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
2651 "error connecting to namestore");
2652 }
2653
2654 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2655}
2656
2657
2658/**
2659 * Called whenever a client is disconnected.
2660 *
2661 * @param cls closure
2662 * @param client identification of the client
2663 * @param app_ctx @a client
2664 */
2665static void
2666client_disconnect_cb (void *cls,
2667 struct GNUNET_SERVICE_Client *client,
2668 void *app_ctx)
2669{
2670 struct IdpClient *idp = app_ctx;
2671
2672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
2673 GNUNET_CONTAINER_DLL_remove (client_list_head,
2674 client_list_tail,
2675 idp);
2676 cleanup_client (idp);
2677}
2678
2679
2680/**
2681 * Add a client to our list of active clients.
2682 *
2683 * @param cls NULL
2684 * @param client client to add
2685 * @param mq message queue for @a client
2686 * @return internal namestore client structure for this client
2687 */
2688static void *
2689client_connect_cb (void *cls,
2690 struct GNUNET_SERVICE_Client *client,
2691 struct GNUNET_MQ_Handle *mq)
2692{
2693 struct IdpClient *idp;
2694
2695 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
2696 idp = GNUNET_new (struct IdpClient);
2697 idp->client = client;
2698 idp->mq = mq;
2699 GNUNET_CONTAINER_DLL_insert (client_list_head,
2700 client_list_tail,
2701 idp);
2702 return idp;
2703}
2704
2705
2706/**
2707 * Define "main" method using service macro.
2708 */
2709GNUNET_SERVICE_MAIN (
2710 "reclaim",
2711 GNUNET_SERVICE_OPTION_NONE,
2712 &run,
2713 &client_connect_cb,
2714 &client_disconnect_cb,
2715 NULL,
2716 GNUNET_MQ_hd_var_size (attribute_store_message,
2717 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2718 struct AttributeStoreMessage,
2719 NULL),
2720 GNUNET_MQ_hd_var_size (credential_store_message,
2721 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE,
2722 struct AttributeStoreMessage,
2723 NULL),
2724 GNUNET_MQ_hd_var_size (attribute_delete_message,
2725 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
2726 struct AttributeDeleteMessage,
2727 NULL),
2728 GNUNET_MQ_hd_var_size (credential_delete_message,
2729 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE,
2730 struct AttributeDeleteMessage,
2731 NULL),
2732 GNUNET_MQ_hd_var_size (iteration_start,
2733 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
2734 struct AttributeIterationStartMessage,
2735 NULL),
2736 GNUNET_MQ_hd_fixed_size (iteration_next,
2737 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
2738 struct AttributeIterationNextMessage,
2739 NULL),
2740 GNUNET_MQ_hd_fixed_size (iteration_stop,
2741 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2742 struct AttributeIterationStopMessage,
2743 NULL),
2744 GNUNET_MQ_hd_var_size (credential_iteration_start,
2745 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START,
2746 struct CredentialIterationStartMessage,
2747 NULL),
2748 GNUNET_MQ_hd_fixed_size (credential_iteration_next,
2749 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT,
2750 struct CredentialIterationNextMessage,
2751 NULL),
2752 GNUNET_MQ_hd_fixed_size (credential_iteration_stop,
2753 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP,
2754 struct CredentialIterationStopMessage,
2755 NULL),
2756
2757 GNUNET_MQ_hd_var_size (issue_ticket_message,
2758 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
2759 struct IssueTicketMessage,
2760 NULL),
2761 GNUNET_MQ_hd_var_size (consume_ticket_message,
2762 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
2763 struct ConsumeTicketMessage,
2764 NULL),
2765 GNUNET_MQ_hd_var_size (ticket_iteration_start,
2766 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
2767 struct TicketIterationStartMessage,
2768 NULL),
2769 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2770 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
2771 struct TicketIterationNextMessage,
2772 NULL),
2773 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2774 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
2775 struct TicketIterationStopMessage,
2776 NULL),
2777 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2778 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
2779 struct RevokeTicketMessage,
2780 NULL),
2781 GNUNET_MQ_handler_end ());
2782/* end of gnunet-service-reclaim.c */
diff --git a/src/service/reclaim/gnunet-service-reclaim_tickets.c b/src/service/reclaim/gnunet-service-reclaim_tickets.c
new file mode 100644
index 000000000..e7e32eec3
--- /dev/null
+++ b/src/service/reclaim/gnunet-service-reclaim_tickets.c
@@ -0,0 +1,1915 @@
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 "gnunet-service-reclaim_tickets.h"
28#include "gnunet_common.h"
29#include "gnunet_gns_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "gnunet_reclaim_service.h"
32#include <string.h>
33
34
35/**
36 * FIXME: the default ticket iteration interval should probably
37 * be the minimim attribute expiration.
38 */
39#define DEFAULT_TICKET_REFRESH_INTERVAL GNUNET_TIME_UNIT_HOURS
40
41/**
42 * Handle for a parallel GNS lookup job
43 * (Declaration further below)
44 */
45struct ParallelLookup;
46
47
48/**
49 * A reference to a ticket stored in GNS
50 */
51struct TicketReference
52{
53 /**
54 * DLL
55 */
56 struct TicketReference *next;
57
58 /**
59 * DLL
60 */
61 struct TicketReference *prev;
62
63 /**
64 * Attributes
65 */
66 struct GNUNET_RECLAIM_AttributeList *attrs;
67
68 /**
69 * Tickets
70 */
71 struct GNUNET_RECLAIM_Ticket ticket;
72};
73
74
75/**
76 * Handle to a consume operation
77 */
78struct RECLAIM_TICKETS_ConsumeHandle
79{
80 /**
81 * Ticket
82 */
83 struct GNUNET_RECLAIM_Ticket ticket;
84
85 /**
86 * LookupRequest
87 */
88 struct GNUNET_GNS_LookupWithTldRequest *lookup_request;
89
90 /**
91 * Lookup DLL
92 */
93 struct ParallelLookup *parallel_lookups_head;
94
95 /**
96 * Lookup DLL
97 */
98 struct ParallelLookup *parallel_lookups_tail;
99
100 /**
101 * Kill task
102 */
103 struct GNUNET_SCHEDULER_Task *kill_task;
104
105 /**
106 * Attributes
107 */
108 struct GNUNET_RECLAIM_AttributeList *attrs;
109
110 /**
111 * Presentations
112 */
113 struct GNUNET_RECLAIM_PresentationList *presentations;
114
115 /**
116 * Lookup time
117 */
118 struct GNUNET_TIME_Absolute lookup_start_time;
119
120 /**
121 * Callback
122 */
123 RECLAIM_TICKETS_ConsumeCallback cb;
124
125 /**
126 * Callback closure
127 */
128 void *cb_cls;
129
130 /**
131 * The ticket audience (= relying party) URI.
132 * 0-terminated string.
133 * Example: "urn:gns:000G002B4RF1XPBXDPGZA0PT16BHQCS427YQK4NC84KZMK7TK8C2Z5GMK8"
134 */
135 char rp_uri[GNUNET_RECLAIM_TICKET_RP_URI_MAX_LEN];
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 * The ticket audience (= relying party) URI.
213 * 0-terminated string.
214 * Example: "urn:gns:000G002B4RF1XPBXDPGZA0PT16BHQCS427YQK4NC84KZMK7TK8C2Z5GMK8"
215 */
216 char rp_uri[GNUNET_RECLAIM_TICKET_RP_URI_MAX_LEN];
217
218 /**
219 * The ticket random identifier
220 */
221 struct GNUNET_RECLAIM_Identifier rnd;
222};
223
224
225/**
226 * Ticket iterator
227 */
228struct RECLAIM_TICKETS_Iterator
229{
230 /**
231 * Namestore queue entry
232 */
233 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
234
235 /**
236 * Iter callback
237 */
238 RECLAIM_TICKETS_TicketIter cb;
239
240 /**
241 * Iter cls
242 */
243 void *cb_cls;
244};
245
246
247struct RevokedAttributeEntry
248{
249 /**
250 * DLL
251 */
252 struct RevokedAttributeEntry *next;
253
254 /**
255 * DLL
256 */
257 struct RevokedAttributeEntry *prev;
258
259 /**
260 * Old ID of the attribute
261 */
262 struct GNUNET_RECLAIM_Identifier old_id;
263
264 /**
265 * New ID of the attribute
266 */
267 struct GNUNET_RECLAIM_Identifier new_id;
268};
269
270
271/**
272 * Ticket revocation request handle
273 */
274struct RECLAIM_TICKETS_RevokeHandle
275{
276 /**
277 * Issuer Key
278 */
279 struct GNUNET_CRYPTO_PrivateKey identity;
280
281 /**
282 * Callback
283 */
284 RECLAIM_TICKETS_RevokeCallback cb;
285
286 /**
287 * Callback cls
288 */
289 void *cb_cls;
290
291 /**
292 * Ticket to issue
293 */
294 struct GNUNET_RECLAIM_Ticket ticket;
295
296 /**
297 * QueueEntry
298 */
299 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
300
301 /**
302 * Namestore iterator
303 */
304 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
305
306 /**
307 * Revoked attributes
308 */
309 struct RevokedAttributeEntry *attrs_head;
310
311 /**
312 * Revoked attributes
313 */
314 struct RevokedAttributeEntry *attrs_tail;
315
316 /**
317 * Current attribute to move
318 */
319 struct RevokedAttributeEntry *move_attr;
320
321 /**
322 * Number of attributes in ticket
323 */
324 unsigned int ticket_attrs;
325
326 /**
327 * Tickets to update
328 */
329 struct TicketRecordsEntry *tickets_to_update_head;
330
331 /**
332 * Tickets to update
333 */
334 struct TicketRecordsEntry *tickets_to_update_tail;
335};
336
337
338/**
339 * Ticket expiration interval
340 */
341static struct GNUNET_TIME_Relative ticket_refresh_interval;
342
343
344/* Namestore handle */
345static struct GNUNET_NAMESTORE_Handle *nsh;
346
347
348/* GNS handle */
349static struct GNUNET_GNS_Handle *gns;
350
351
352/* Handle to the statistics service */
353static struct GNUNET_STATISTICS_Handle *stats;
354
355
356/**
357 * Cleanup revoke handle
358 *
359 * @param rh the ticket revocation handle
360 */
361static void
362cleanup_rvk (struct RECLAIM_TICKETS_RevokeHandle *rh)
363{
364 struct RevokedAttributeEntry *ae;
365 struct TicketRecordsEntry *le;
366
367 if (NULL != rh->ns_qe)
368 GNUNET_NAMESTORE_cancel (rh->ns_qe);
369 if (NULL != rh->ns_it)
370 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
371 while (NULL != (ae = rh->attrs_head))
372 {
373 GNUNET_CONTAINER_DLL_remove (rh->attrs_head, rh->attrs_tail, ae);
374 GNUNET_free (ae);
375 }
376 while (NULL != (le = rh->tickets_to_update_head))
377 {
378 GNUNET_CONTAINER_DLL_remove (rh->tickets_to_update_head,
379 rh->tickets_to_update_head,
380 le);
381 if (NULL != le->data)
382 GNUNET_free (le->data);
383 if (NULL != le->label)
384 GNUNET_free (le->label);
385 GNUNET_free (le);
386 }
387 GNUNET_free (rh);
388}
389
390
391/**
392 * For each ticket, store new, updated attribute references
393 * (Implementation further below)
394 *
395 * @param cls handle to the operation
396 */
397static void
398process_tickets (void *cls);
399
400
401/**
402 * Finished storing updated attribute references.
403 * Abort on error, else continue processing tickets
404 *
405 * @param cls handle to the operation
406 * @param success result of namestore operation
407 * @param emsg (NULL on success)
408 */
409static void
410ticket_processed (void *cls, enum GNUNET_ErrorCode ec)
411{
412 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
413
414 rvk->ns_qe = NULL;
415 GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
416}
417
418
419/**
420 * For each ticket, store new, updated attribute references
421 *
422 * @param cls handle to the operation
423 */
424static void
425process_tickets (void *cls)
426{
427 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
428 struct TicketRecordsEntry *le;
429 struct RevokedAttributeEntry *ae;
430
431 if (NULL == rvk->tickets_to_update_head)
432 {
433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
434 "Finished updatding tickets, success\n");
435 rvk->cb (rvk->cb_cls, GNUNET_OK);
436 cleanup_rvk (rvk);
437 return;
438 }
439 le = rvk->tickets_to_update_head;
440 GNUNET_CONTAINER_DLL_remove (rvk->tickets_to_update_head,
441 rvk->tickets_to_update_tail,
442 le);
443 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
444 if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
445 le->data,
446 le->rd_count,
447 rd))
448 {
449 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
450 "Unable to deserialize ticket record(s)\n");
451 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
452 cleanup_rvk (rvk);
453 return;
454 }
455 for (int i = 0; i < le->rd_count; i++)
456 {
457 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
458 continue;
459 for (ae = rvk->attrs_head; NULL != ae; ae = ae->next)
460 {
461 if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id)))
462 continue;
463 rd[i].data = &ae->new_id;
464 }
465 }
466 rvk->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
467 &rvk->identity,
468 le->label,
469 le->rd_count,
470 rd,
471 &ticket_processed,
472 rvk);
473 GNUNET_free (le->label);
474 GNUNET_free (le->data);
475 GNUNET_free (le);
476}
477
478
479/**
480 * Done collecting tickets. Start processing.
481 *
482 * @param cls handle to the operation
483 */
484static void
485rvk_ticket_update_finished (void *cls)
486{
487 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
488
489 rvk->ns_it = NULL;
490 GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
491}
492
493
494/**
495 * We need to update all other tickets with the new attribute IDs.
496 * We first collect them all. Processing after.
497 *
498 * @param cls handle to the operation
499 * @param zone ticket issuer private key
500 * @param label ticket rnd
501 * @param rd_count size of record set
502 * @param rd record set
503 */
504static void
505rvk_ticket_update (void *cls,
506 const struct GNUNET_CRYPTO_PrivateKey *zone,
507 const char *label,
508 unsigned int rd_count,
509 const struct GNUNET_GNSRECORD_Data *rd)
510{
511 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
512 struct TicketRecordsEntry *le;
513 struct RevokedAttributeEntry *ae;
514 int has_changed = GNUNET_NO;
515
516 /** Let everything point to the old record **/
517 for (int i = 0; i < rd_count; i++)
518 {
519 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
520 continue;
521 for (ae = rvk->attrs_head; NULL != ae; ae = ae->next)
522 {
523 if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id)))
524 continue;
525 has_changed = GNUNET_YES;
526 break;
527 }
528 if (GNUNET_YES == has_changed)
529 break;
530 }
531 if (GNUNET_YES == has_changed)
532 {
533 le = GNUNET_new (struct TicketRecordsEntry);
534 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
535 le->data = GNUNET_malloc (le->data_size);
536 le->rd_count = rd_count;
537 le->label = GNUNET_strdup (label);
538 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
539 GNUNET_CONTAINER_DLL_insert (rvk->tickets_to_update_head,
540 rvk->tickets_to_update_tail,
541 le);
542 }
543 GNUNET_NAMESTORE_zone_iterator_next (rvk->ns_it, 1);
544}
545
546
547/**
548 * Error iterating namestore. Abort.
549 *
550 * @param cls handle to the operation
551 */
552static void
553rvk_ns_iter_err (void *cls)
554{
555 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
556
557 rvk->ns_it = NULL;
558 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
559 cleanup_rvk (rvk);
560}
561
562
563/**
564 * Error storing new attribute in namestore. Abort
565 *
566 * @param cls handle to the operation
567 */
568static void
569rvk_ns_err (void *cls)
570{
571 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
572
573 rvk->ns_qe = NULL;
574 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
575 cleanup_rvk (rvk);
576}
577
578
579/**
580 * We change every attribute ID of the ticket attributes we
581 * want to revoke.
582 * When we are done, we need to update any other ticket which
583 * included references to any of the changed attributes.
584 *
585 * @param rh handle to the operation
586 */
587static void
588move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rh);
589
590
591/**
592 * Delayed continuation for move_attrs
593 *
594 * @param cls handle to the operation.
595 */
596static void
597move_attrs_cont (void *cls)
598{
599 move_attrs ((struct RECLAIM_TICKETS_RevokeHandle *) cls);
600}
601
602
603/**
604 * Done deleting the old record. Abort on error.
605 * Else, continue updating attribute IDs.
606 *
607 * @param cls handle to the operation
608 * @param success result of the namestore operation
609 * @param emsg error message (NULL on success)
610 */
611static void
612del_attr_finished (void *cls, enum GNUNET_ErrorCode ec)
613{
614 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
615
616 rvk->ns_qe = NULL;
617 if (GNUNET_EC_NONE != ec)
618 {
619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
620 "Error removing attribute: %s\n",
621 GNUNET_ErrorCode_get_hint (ec));
622 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
623 cleanup_rvk (rvk);
624 return;
625 }
626 rvk->move_attr = rvk->move_attr->next;
627 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
628}
629
630
631/**
632 * Updated an attribute ID.
633 * Abort on error if namestore operation failed.
634 * Else, we have to delete the old record.
635 *
636 * @param cls handle to the operation
637 * @param success result of the store operation
638 * @param emsg error message (NULL on success)
639 */
640static void
641move_attr_finished (void *cls, enum GNUNET_ErrorCode ec)
642{
643 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
644 char *label;
645
646 rvk->ns_qe = NULL;
647 if (GNUNET_EC_NONE != ec)
648 {
649 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
650 "Error moving attribute: %s\n",
651 GNUNET_ErrorCode_get_hint (ec));
652 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
653 cleanup_rvk (rvk);
654 return;
655 }
656 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
657 sizeof(rvk->move_attr->old_id));
658 GNUNET_assert (NULL != label);
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing attribute %s\n", label);
660 rvk->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
661 &rvk->identity,
662 label,
663 0,
664 NULL,
665 &del_attr_finished,
666 rvk);
667 GNUNET_free (label);
668}
669
670
671/**
672 * Got the referenced attribute. Updating the ID
673 *
674 * @param cls handle to the operation
675 * @param zone issuer identity
676 * @param label attribute ID
677 * @param rd_count size of record set (should be 1)
678 * @param rd record set (the attribute)
679 */
680static void
681rvk_move_attr_cb (void *cls,
682 const struct GNUNET_CRYPTO_PrivateKey *zone,
683 const char *label,
684 unsigned int rd_count,
685 const struct GNUNET_GNSRECORD_Data *rd)
686{
687 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
688 struct GNUNET_GNSRECORD_Data new_rd[rd_count];
689 struct RevokedAttributeEntry *le;
690 char *new_label;
691 char *attr_data;
692
693 rvk->ns_qe = NULL;
694 if (0 == rd_count)
695 {
696 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
697 "The claim %s no longer exists!\n",
698 label);
699 le = rvk->move_attr;
700 rvk->move_attr = le->next;
701 GNUNET_CONTAINER_DLL_remove (rvk->attrs_head, rvk->attrs_tail, le);
702 GNUNET_free (le);
703 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
704 return;
705 }
706 GNUNET_RECLAIM_id_generate (&rvk->move_attr->new_id);
707 new_label =
708 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
709 sizeof (rvk->move_attr->new_id));
710
711 attr_data = NULL;
712 // new_rd = *rd;
713 for (int i = 0; i < rd_count; i++)
714 {
715 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type)
716 {
717 /** find a new place for this attribute **/
718 struct GNUNET_RECLAIM_Attribute *claim;
719 GNUNET_RECLAIM_attribute_deserialize (rd[i].data,
720 rd[i].data_size,
721 &claim);
722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
723 "Attribute to update: Name=%s\n",
724 claim->name);
725 claim->id = rvk->move_attr->new_id;
726 new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize_get_size (claim);
727 attr_data = GNUNET_malloc (rd[i].data_size);
728 new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize (claim,
729 attr_data);
730 new_rd[i].data = attr_data;
731 new_rd[i].record_type = rd[i].record_type;
732 new_rd[i].flags = rd[i].flags;
733 new_rd[i].expiration_time = rd[i].expiration_time;
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
735 GNUNET_free (claim);
736 }
737 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
738 {
739 struct GNUNET_RECLAIM_Credential *credential;
740 credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
741 rd[i].data_size);
742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
743 "Credential to update: Name=%s\n",
744 credential->name);
745 credential->id = rvk->move_attr->new_id;
746 new_rd[i].data_size =
747 GNUNET_RECLAIM_credential_serialize_get_size (credential);
748 attr_data = GNUNET_malloc (rd[i].data_size);
749 new_rd[i].data_size = GNUNET_RECLAIM_credential_serialize (credential,
750 attr_data);
751 new_rd[i].data = attr_data;
752 new_rd[i].record_type = rd[i].record_type;
753 new_rd[i].flags = rd[i].flags;
754 new_rd[i].expiration_time = rd[i].expiration_time;
755 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n",
756 new_label);
757 GNUNET_free (credential);
758 }
759 else
760 {
761 memcpy (&new_rd[i], &rd[i], sizeof (struct GNUNET_GNSRECORD_Data));
762 }
763 }
764 rvk->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
765 &rvk->identity,
766 new_label,
767 rd_count,
768 new_rd,
769 &move_attr_finished,
770 rvk);
771 GNUNET_free (new_label);
772 GNUNET_free (attr_data);
773}
774
775
776static void
777move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk)
778{
779 char *label;
780
781 if (NULL == rvk->move_attr)
782 {
783 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished moving attributes\n");
784 rvk->ns_it =
785 GNUNET_NAMESTORE_zone_iteration_start (nsh,
786 &rvk->identity,
787 &rvk_ns_iter_err,
788 rvk,
789 &rvk_ticket_update,
790 rvk,
791 &rvk_ticket_update_finished,
792 rvk);
793 return;
794 }
795 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
796 sizeof (rvk->move_attr->old_id));
797 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving claim %s\n", label);
798
799 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
800 &rvk->identity,
801 label,
802 &rvk_ns_err,
803 rvk,
804 &rvk_move_attr_cb,
805 rvk);
806 GNUNET_free (label);
807}
808
809
810/**
811 * Finished deleting ticket and attribute references.
812 * Abort on failure.
813 * Else, we start changing every attribute ID in the
814 * found attribute references so that access is no longer
815 * possible.
816 *
817 * @param cls handle to the operation
818 * @param success Namestore operation return value
819 * @param emsg error message (NULL on success)
820 */
821static void
822remove_ticket_cont (void *cls, enum GNUNET_ErrorCode ec)
823{
824 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
825
826 rvk->ns_qe = NULL;
827 if (GNUNET_EC_NONE != ec)
828 {
829 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
830 GNUNET_ErrorCode_get_hint (ec));
831 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
832 cleanup_rvk (rvk);
833 return;
834 }
835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted ticket\n");
836 if (0 == rvk->ticket_attrs)
837 {
838 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
839 "No attributes to move... strange\n");
840 rvk->cb (rvk->cb_cls, GNUNET_OK);
841 cleanup_rvk (rvk);
842 return;
843 }
844 rvk->move_attr = rvk->attrs_head;
845 move_attrs (rvk);
846}
847
848
849/**
850 * We found the attribute references.
851 * Store them for later and remove the record set.
852 *
853 * @param cls handle to the operation
854 * @param zone the issuer key
855 * @param label ticket rnd
856 * @param rd_count size of record set
857 * @param rd record set
858 */
859static void
860revoke_attrs_cb (void *cls,
861 const struct GNUNET_CRYPTO_PrivateKey *zone,
862 const char *label,
863 unsigned int rd_count,
864 const struct GNUNET_GNSRECORD_Data *rd)
865
866{
867 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
868 struct RevokedAttributeEntry *le;
869
870 rvk->ns_qe = NULL;
871 /**
872 * Temporarily store attribute references.
873 * We need it later.
874 */
875 for (int i = 0; i < rd_count; i++)
876 {
877 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
878 continue;
879 le = GNUNET_new (struct RevokedAttributeEntry);
880 le->old_id = *((struct GNUNET_RECLAIM_Identifier *) rd[i].data);
881 GNUNET_CONTAINER_DLL_insert (rvk->attrs_head, rvk->attrs_tail, le);
882 rvk->ticket_attrs++;
883 }
884
885 /** Remove attribute references **/
886 rvk->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
887 &rvk->identity,
888 label,
889 0,
890 NULL,
891 &remove_ticket_cont,
892 rvk);
893}
894
895
896/**
897 * Failed to query namestore. Abort operation
898 *
899 * @param cls handle to the operation
900 */
901static void
902rvk_attrs_err_cb (void *cls)
903{
904 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
905
906 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
907 cleanup_rvk (rvk);
908}
909
910
911/**
912 * Revoke a ticket.
913 * We start by looking up attribute references in order
914 * to change attribute IDs.
915 *
916 * @param ticket ticket to revoke
917 * @param identity private key of issuer
918 * @param cb revocation status callback
919 * @param cb_cls callback closure
920 * @return handle to the operation
921 */
922struct RECLAIM_TICKETS_RevokeHandle *
923RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket,
924 const struct GNUNET_CRYPTO_PrivateKey *identity,
925 RECLAIM_TICKETS_RevokeCallback cb,
926 void *cb_cls)
927{
928 struct RECLAIM_TICKETS_RevokeHandle *rvk;
929 char *label;
930 char *tmp;
931
932 rvk = GNUNET_new (struct RECLAIM_TICKETS_RevokeHandle);
933 rvk->cb = cb;
934 rvk->cb_cls = cb_cls;
935 rvk->identity = *identity;
936 rvk->ticket = *ticket;
937 tmp = GNUNET_strdup (ticket->gns_name);
938 label = strtok (tmp, ".");
939 GNUNET_assert (NULL != label);
940 /** Get shared attributes **/
941 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
942 identity,
943 label,
944 &rvk_attrs_err_cb,
945 rvk,
946 &revoke_attrs_cb,
947 rvk);
948 GNUNET_free (tmp);
949 return rvk;
950}
951
952
953/**
954 * Cancel a revocation.
955 *
956 * @param rh handle to the operation
957 */
958void
959RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh)
960{
961 GNUNET_assert (NULL != rh);
962 cleanup_rvk (rh);
963}
964
965
966/*******************************
967* Ticket consume
968*******************************/
969
970/**
971 * Cleanup ticket consume handle
972 *
973 * @param cth the handle to clean up
974 */
975static void
976cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
977{
978 struct ParallelLookup *lu;
979
980 if (NULL != cth->lookup_request)
981 GNUNET_GNS_lookup_with_tld_cancel (cth->lookup_request);
982 if (NULL != cth->kill_task)
983 GNUNET_SCHEDULER_cancel (cth->kill_task);
984 while (NULL != (lu = cth->parallel_lookups_head))
985 {
986 if (NULL != lu->lookup_request)
987 GNUNET_GNS_lookup_cancel (lu->lookup_request);
988 GNUNET_free (lu->label);
989 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
990 cth->parallel_lookups_tail,
991 lu);
992 GNUNET_free (lu);
993 }
994
995 if (NULL != cth->attrs)
996 GNUNET_RECLAIM_attribute_list_destroy (cth->attrs);
997 if (NULL != cth->presentations)
998 GNUNET_RECLAIM_presentation_list_destroy (cth->presentations);
999 GNUNET_free (cth);
1000}
1001
1002
1003static void
1004process_parallel_lookup_result (void *cls,
1005 uint32_t rd_count,
1006 const struct GNUNET_GNSRECORD_Data *rd)
1007{
1008 struct ParallelLookup *parallel_lookup = cls;
1009 struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle;
1010 struct GNUNET_RECLAIM_AttributeListEntry *attr_le;
1011 struct GNUNET_CRYPTO_PublicKey iss;
1012
1013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1014 "Parallel lookup finished (count=%u)\n",
1015 rd_count);
1016
1017 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
1018 cth->parallel_lookups_tail,
1019 parallel_lookup);
1020 GNUNET_free (parallel_lookup->label);
1021
1022 GNUNET_STATISTICS_update (stats,
1023 "attribute_lookup_time_total",
1024 GNUNET_TIME_absolute_get_duration (
1025 parallel_lookup->lookup_start_time)
1026 .rel_value_us,
1027 GNUNET_YES);
1028 GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES);
1029
1030
1031 GNUNET_free (parallel_lookup);
1032 if (0 == rd_count)
1033 GNUNET_break (0);
1034 // REMARK: It is possible now to find rd_count > 1
1035 for (int i = 0; i < rd_count; i++)
1036 {
1037 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type)
1038 continue;
1039 attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1040 GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size,
1041 &attr_le->attribute);
1042 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
1043 cth->attrs->list_tail,
1044 attr_le);
1045 }
1046 if (NULL != cth->parallel_lookups_head)
1047 return; // Wait for more
1048 /* Else we are done */
1049 GNUNET_assert (GNUNET_OK == GNUNET_GNS_parse_ztld (cth->ticket.gns_name, &iss)
1050 );
1051 cth->cb (cth->cb_cls, &iss,
1052 cth->attrs, cth->presentations, GNUNET_OK, NULL);
1053 cleanup_cth (cth);
1054}
1055
1056
1057/**
1058 * Cancel the lookups for attribute records
1059 *
1060 * @param cls handle to the operation
1061 */
1062static void
1063abort_parallel_lookups (void *cls)
1064{
1065 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
1066 struct ParallelLookup *lu;
1067 struct ParallelLookup *tmp;
1068
1069 cth->kill_task = NULL;
1070 for (lu = cth->parallel_lookups_head; NULL != lu;)
1071 {
1072 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1073 GNUNET_free (lu->label);
1074 tmp = lu->next;
1075 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
1076 cth->parallel_lookups_tail,
1077 lu);
1078 GNUNET_free (lu);
1079 lu = tmp;
1080 }
1081 cth->cb (cth->cb_cls, NULL, NULL, NULL, GNUNET_SYSERR, "Aborted");
1082}
1083
1084
1085static void
1086lookup_authz_cb (void *cls,
1087 int is_gns,
1088 uint32_t rd_count,
1089 const struct GNUNET_GNSRECORD_Data *rd)
1090{
1091 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
1092 struct GNUNET_CRYPTO_PublicKey iss;
1093 struct ParallelLookup *parallel_lookup;
1094 const char *rp_uri = NULL;
1095 char *lbl;
1096 struct GNUNET_RECLAIM_PresentationListEntry *ale;
1097
1098 cth->lookup_request = NULL;
1099
1100 GNUNET_assert (GNUNET_YES == is_gns);
1101 GNUNET_STATISTICS_update (stats,
1102 "reclaim_authz_lookup_time_total",
1103 GNUNET_TIME_absolute_get_duration (
1104 cth->lookup_start_time)
1105 .rel_value_us,
1106 GNUNET_YES);
1107 GNUNET_STATISTICS_update (stats,
1108 "reclaim_authz_lookups_count",
1109 1,
1110 GNUNET_YES);
1111
1112 GNUNET_assert (GNUNET_OK
1113 == GNUNET_GNS_parse_ztld (cth->ticket.gns_name, &iss));
1114 for (int i = 0; i < rd_count; i++)
1115 {
1116 /**
1117 * Check if record is a credential presentation or an attribute
1118 * reference.
1119 */
1120 switch (rd[i].record_type)
1121 {
1122 case GNUNET_DNSPARSER_TYPE_TXT:
1123 rp_uri = rd[i].data;
1124 break;
1125 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
1126 ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1127 ale->presentation =
1128 GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1129 rd[i].data_size);
1130 GNUNET_CONTAINER_DLL_insert (cth->presentations->list_head,
1131 cth->presentations->list_tail,
1132 ale);
1133 break;
1134 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
1135 lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
1136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl);
1137 parallel_lookup = GNUNET_new (struct ParallelLookup);
1138 parallel_lookup->handle = cth;
1139 parallel_lookup->label = lbl;
1140 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
1141 parallel_lookup->lookup_request =
1142 GNUNET_GNS_lookup (gns,
1143 lbl,
1144 &iss,
1145 GNUNET_GNSRECORD_TYPE_ANY,
1146 GNUNET_GNS_LO_DEFAULT,
1147 &process_parallel_lookup_result,
1148 parallel_lookup);
1149 GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
1150 cth->parallel_lookups_tail,
1151 parallel_lookup);
1152 break;
1153 default:
1154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155 "Ignoring unknown record type %d", rd[i].record_type);
1156 }
1157 }
1158 if (NULL == rp_uri)
1159 {
1160 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1161 "RP URI not found along references, ignoring...\n");
1162 /**
1163 * Return error
1164 */
1165 cth->cb (cth->cb_cls, &iss,
1166 cth->attrs, NULL, GNUNET_NO, NULL);
1167 cleanup_cth (cth);
1168 return;
1169 }
1170 if (0 != strcmp (rp_uri, cth->rp_uri))
1171 {
1172 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1173 "RP URI does not match consume request: `%s' != `%s'\n",
1174 rp_uri, cth->rp_uri);
1175 /**
1176 * Return error
1177 */
1178 cth->cb (cth->cb_cls, &iss,
1179 cth->attrs, NULL, GNUNET_NO, NULL);
1180 cleanup_cth (cth);
1181 return;
1182 }
1183 /**
1184 * We started lookups. Add a timeout task.
1185 * FIXME: Really needed here?
1186 */
1187 if (NULL != cth->parallel_lookups_head)
1188 {
1189 cth->kill_task = GNUNET_SCHEDULER_add_delayed (
1190 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3),
1191 &abort_parallel_lookups,
1192 cth);
1193 return;
1194 }
1195 /**
1196 * No references found, return empty attribute list
1197 */
1198 cth->cb (cth->cb_cls, &iss,
1199 cth->attrs, NULL, GNUNET_OK, NULL);
1200 cleanup_cth (cth);
1201}
1202
1203
1204/**
1205 * Consume a ticket.
1206 * We first looking attribute references under the label
1207 * ticket.rnd in GNS.
1208 *
1209 * @param id the audience of the ticket
1210 * @param ticket the ticket to consume
1211 * @param cb callback to call with attributes of ticket
1212 * @param cb_cls callback closure
1213 * @return handle to the operation
1214 */
1215struct RECLAIM_TICKETS_ConsumeHandle *
1216RECLAIM_TICKETS_consume (const struct GNUNET_RECLAIM_Ticket *ticket,
1217 const char *rp_uri,
1218 RECLAIM_TICKETS_ConsumeCallback cb,
1219 void *cb_cls)
1220{
1221 struct RECLAIM_TICKETS_ConsumeHandle *cth;
1222
1223 cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle);
1224
1225 cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1226 cth->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1227 cth->ticket = *ticket;
1228 memcpy (cth->rp_uri, rp_uri, strlen (rp_uri) + 1);
1229 cth->cb = cb;
1230 cth->cb_cls = cb_cls;
1231 cth->lookup_start_time = GNUNET_TIME_absolute_get ();
1232 cth->lookup_request =
1233 GNUNET_GNS_lookup_with_tld (gns,
1234 ticket->gns_name,
1235 GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF,
1236 GNUNET_GNS_LO_DEFAULT,
1237 &lookup_authz_cb,
1238 cth);
1239 return cth;
1240}
1241
1242
1243/**
1244 * Cancel a consume operation
1245 *
1246 * @param cth the operation to cancel
1247 */
1248void
1249RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
1250{
1251 cleanup_cth (cth);
1252 return;
1253}
1254
1255
1256/*******************************
1257 * Ticket issue
1258 *******************************/
1259
1260/**
1261 * Cleanup ticket consume handle
1262 * @param handle the handle to clean up
1263 */
1264static void
1265cleanup_issue_handle (struct TicketIssueHandle *handle)
1266{
1267 if (NULL != handle->ns_qe)
1268 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1269 GNUNET_free (handle);
1270}
1271
1272
1273/**
1274 * Store finished, abort on error.
1275 * Else, return new ticket to caller.
1276 *
1277 * @param cls handle to the operation
1278 * @param success store operation result
1279 * @param emsg error message (or NULL on success)
1280 */
1281static void
1282store_ticket_issue_cont (void *cls, enum GNUNET_ErrorCode ec)
1283{
1284 struct TicketIssueHandle *handle = cls;
1285
1286 handle->ns_qe = NULL;
1287 if (GNUNET_EC_NONE != ec)
1288 {
1289 handle->cb (handle->cb_cls,
1290 &handle->ticket,
1291 NULL,
1292 GNUNET_SYSERR,
1293 "Error storing AuthZ ticket in GNS");
1294 return;
1295 }
1296 handle->cb (handle->cb_cls,
1297 &handle->ticket,
1298 handle->presentations,
1299 GNUNET_OK, NULL);
1300 cleanup_issue_handle (handle);
1301}
1302
1303
1304/**
1305 * Issue a new ticket.
1306 * We store references to attribute record labels and the ticket itself
1307 * under the label base64(ticket.rnd).
1308 *
1309 * @param ih handle to the operation containing relevant metadata
1310 */
1311static void
1312issue_ticket (struct TicketIssueHandle *ih)
1313{
1314 struct GNUNET_RECLAIM_AttributeListEntry *le;
1315 struct GNUNET_RECLAIM_PresentationListEntry *ple;
1316 struct GNUNET_GNSRECORD_Data *attrs_record;
1317 char *label;
1318 char *tkt_data;
1319 int i;
1320 int j;
1321 int attrs_count = 0;
1322
1323 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1324 attrs_count++;
1325
1326 // Worst case we have one presentation per attribute plus the ticket
1327 // plus the RP URI record
1328 attrs_record =
1329 GNUNET_malloc ((2 * attrs_count + 2) * sizeof(struct GNUNET_GNSRECORD_Data))
1330 ;
1331 i = 0;
1332 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1333 {
1334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1335 "Adding list entry: %s\n", le->attribute->name);
1336
1337 attrs_record[i].data = &le->attribute->id;
1338 attrs_record[i].data_size = sizeof(le->attribute->id);
1339 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1340 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF;
1341 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1342 i++;
1343 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
1344 {
1345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1346 "Attribute is backed by credential. Adding...\n");
1347 struct GNUNET_RECLAIM_Presentation *presentation = NULL;
1348 for (j = 0; j < i; j++)
1349 {
1350 if (attrs_record[j].record_type
1351 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
1352 continue;
1353 presentation = GNUNET_RECLAIM_presentation_deserialize (
1354 attrs_record[j].data,
1355 attrs_record[j].
1356 data_size);
1357 if (NULL == presentation)
1358 {
1359 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1360 "Failed to deserialize presentation\n");
1361 continue;
1362 }
1363 if (0 == memcmp (&presentation->credential_id,
1364 &le->attribute->credential,
1365 sizeof (le->attribute->credential)))
1366 break;
1367 GNUNET_free (presentation);
1368 presentation = NULL;
1369 }
1370 if (NULL != presentation)
1371 {
1372 GNUNET_free (presentation);
1373 continue; // Skip as we have already added this credential presentation.
1374 }
1375 for (ple = ih->presentations->list_head; NULL != ple; ple = ple->next)
1376 {
1377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1378 "Checking presentation....\n");
1379
1380 if (0 != memcmp (&le->attribute->credential,
1381 &ple->presentation->credential_id,
1382 sizeof (le->attribute->credential)))
1383 {
1384 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1385 "Presentation does not match credential ID.\n");
1386 continue;
1387 }
1388 char *pres_buf;
1389 size_t pres_size;
1390
1391 pres_size =
1392 GNUNET_RECLAIM_presentation_serialize_get_size (ple->presentation);
1393 pres_buf = GNUNET_malloc (pres_size);
1394 GNUNET_RECLAIM_presentation_serialize (ple->presentation,
1395 pres_buf);
1396 attrs_record[i].data = pres_buf;
1397 attrs_record[i].data_size = pres_size;
1398 attrs_record[i].expiration_time =
1399 ticket_refresh_interval.rel_value_us;
1400 attrs_record[i].record_type =
1401 GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION;
1402 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1403 i++;
1404 break;
1405 }
1406 }
1407 }
1408
1409 label =
1410 GNUNET_STRINGS_data_to_string_alloc (&ih->rnd,
1411 sizeof(ih->rnd));
1412 struct GNUNET_CRYPTO_PublicKey pub;
1413 GNUNET_CRYPTO_key_get_public (&ih->identity,
1414 &pub);
1415 char *str = GNUNET_CRYPTO_public_key_to_string (&pub);
1416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1417 "Storing AuthZ information under %s in %s\n", label, str);
1418 sprintf (ih->ticket.gns_name, "%s.%s", label, str);
1419 GNUNET_free (str);
1420
1421 attrs_record[i].data_size =
1422 strlen (ih->ticket.gns_name) + 1;
1423 tkt_data = GNUNET_malloc (attrs_record[i].data_size);
1424 memcpy (tkt_data, &ih->ticket, attrs_record[i].data_size);
1425 // The ticket: Could be removed?
1426 attrs_record[i].data = tkt_data;
1427 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1428 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET;
1429 attrs_record[i].flags =
1430 GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
1431 i++;
1432 // The RP URI
1433 attrs_record[i].data_size = strlen (ih->rp_uri);
1434 attrs_record[i].data = ih->rp_uri;
1435 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1436 attrs_record[i].record_type = GNUNET_DNSPARSER_TYPE_TXT;
1437 attrs_record[i].flags =
1438 GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1439 i++;
1440
1441 // Publish record
1442 ih->ns_qe = GNUNET_NAMESTORE_record_set_store (nsh,
1443 &ih->identity,
1444 label,
1445 i,
1446 attrs_record,
1447 &store_ticket_issue_cont,
1448 ih);
1449 for (j = 0; j < i; j++)
1450 {
1451 if (attrs_record[j].record_type
1452 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
1453 continue;
1454 // Yes, we are allowed to do this because we allocated it above
1455 char *ptr = (char*) attrs_record[j].data;
1456 GNUNET_free (ptr);
1457 }
1458 GNUNET_free (tkt_data);
1459 GNUNET_free (attrs_record);
1460 GNUNET_free (label);
1461}
1462
1463
1464/*************************************************
1465 * Ticket iteration (finding a specific ticket)
1466 *************************************************/
1467
1468
1469/**
1470 * Namestore error on issue. Abort.
1471 *
1472 * @param cls handle to the operation
1473 */
1474static void
1475filter_tickets_error_cb (void *cls)
1476{
1477 struct TicketIssueHandle *tih = cls;
1478
1479 tih->ns_it = NULL;
1480 tih->cb (tih->cb_cls,
1481 &tih->ticket,
1482 NULL,
1483 GNUNET_SYSERR,
1484 "Error storing AuthZ ticket in GNS");
1485 cleanup_issue_handle (tih);
1486}
1487
1488
1489/**
1490 * Iterator over records.
1491 * Check if any previously issued ticket already
1492 * matches what we need to prevent duplicates and
1493 * improve resolution synergy.
1494 *
1495 * @param cls handle to the operation
1496 * @param zone issuer identity
1497 * @param label ticket rnd
1498 * @param rd_count size of record set
1499 * @param rd record set
1500 */
1501static void
1502filter_tickets_cb (void *cls,
1503 const struct GNUNET_CRYPTO_PrivateKey *zone,
1504 const char *label,
1505 unsigned int rd_count,
1506 const struct GNUNET_GNSRECORD_Data *rd)
1507{
1508 struct TicketIssueHandle *tih = cls;
1509 struct GNUNET_RECLAIM_Ticket *ticket;
1510 struct GNUNET_RECLAIM_Presentation *presentation;
1511 struct GNUNET_RECLAIM_PresentationList *ticket_presentations;
1512 struct GNUNET_RECLAIM_Credential *cred;
1513 struct GNUNET_RECLAIM_PresentationListEntry *ple;
1514 struct GNUNET_RECLAIM_AttributeListEntry *le;
1515 unsigned int attr_cnt = 0;
1516 unsigned int pres_cnt = 0;
1517 int ticket_found = GNUNET_NO;
1518 int rp_uri_matches = GNUNET_NO;
1519
1520 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1521 {
1522 attr_cnt++;
1523 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
1524 pres_cnt++;
1525 }
1526
1527 // ticket search
1528 unsigned int found_attrs_cnt = 0;
1529 unsigned int found_pres_cnt = 0;
1530 ticket_presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1531
1532 for (int i = 0; i < rd_count; i++)
1533 {
1534 // found ticket
1535 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET == rd[i].record_type)
1536 {
1537 ticket = (struct GNUNET_RECLAIM_Ticket *) rd[i].data;
1538 tih->ticket = *ticket;
1539 ticket_found = GNUNET_YES;
1540 }
1541 if (GNUNET_DNSPARSER_TYPE_TXT == rd[i].record_type)
1542 {
1543 // cmp audience
1544 if (0 != strncmp (tih->rp_uri,
1545 rd[i].data,
1546 rd[i].data_size))
1547 continue;
1548 rp_uri_matches = GNUNET_YES;
1549 }
1550 // cmp requested attributes with ticket attributes
1551 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1552 {
1553 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1554 {
1555 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1556 &le->attribute->id))
1557 found_attrs_cnt++;
1558 }
1559 }
1560 if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
1561 {
1562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1563 "Found credential...\n");
1564
1565 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1566 {
1567 cred = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
1568 rd[i].data_size);
1569 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (&cred->id,
1570 &le->attribute->credential
1571 ))
1572 {
1573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1574 "No match.\n");
1575 GNUNET_free (cred);
1576 continue;
1577 }
1578 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1579 "Match, creating presentation...\n");
1580 if (GNUNET_OK != GNUNET_RECLAIM_credential_get_presentation (
1581 cred,
1582 tih->attrs,
1583 &presentation))
1584 {
1585 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1586 "Unable to retrieve presentation from credential\n");
1587 GNUNET_free (cred);
1588 continue;
1589 }
1590 ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1591 ple->presentation = presentation;
1592 GNUNET_CONTAINER_DLL_insert (tih->presentations->list_head,
1593 tih->presentations->list_tail,
1594 ple);
1595 GNUNET_free (cred);
1596 break;
1597 }
1598 }
1599 if (GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION == rd[i].record_type)
1600 {
1601 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1602 {
1603 presentation = GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1604 rd[i].data_size)
1605 ;
1606 if (NULL == presentation)
1607 {
1608 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1609 "Failed to deserialize presentation\n");
1610 continue;
1611 }
1612 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (
1613 &presentation->credential_id,
1614 &le->attribute->credential))
1615 {
1616 found_pres_cnt++;
1617 ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1618 ple->presentation = presentation;
1619 GNUNET_CONTAINER_DLL_insert (ticket_presentations->list_head,
1620 ticket_presentations->list_tail,
1621 ple);
1622 }
1623 }
1624 }
1625 }
1626
1627 /**
1628 * If we found a matching ticket, return that to the caller and
1629 * we are done.
1630 */
1631 if ((attr_cnt == found_attrs_cnt) &&
1632 (pres_cnt == found_pres_cnt) &&
1633 (GNUNET_YES == ticket_found) &&
1634 (GNUNET_YES == rp_uri_matches))
1635 {
1636 GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it);
1637 tih->cb (tih->cb_cls, &tih->ticket, ticket_presentations, GNUNET_OK, NULL);
1638 GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
1639 cleanup_issue_handle (tih);
1640 return;
1641 }
1642 GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
1643 // ticket not found in current record, checking next record set
1644 GNUNET_NAMESTORE_zone_iterator_next (tih->ns_it, 1);
1645}
1646
1647
1648/**
1649 * Done iterating over tickets and we apparently did
1650 * not find an existing, matching ticket.
1651 * Continue by issuing a new ticket.
1652 *
1653 * @param cls handle to the operation
1654 */
1655static void
1656filter_tickets_finished_cb (void *cls)
1657{
1658 struct TicketIssueHandle *tih = cls;
1659
1660 GNUNET_RECLAIM_id_generate (&tih->rnd);
1661 issue_ticket (tih);
1662}
1663
1664
1665/**
1666 * Issue a new reclaim ticket, thereby authorizing
1667 * the audience to access the set of provided attributes.
1668 *
1669 * @param identity the issuer
1670 * @param attrs the attributes to share
1671 * @param audience the audience to share the attributes with
1672 * @param cb the callback to call with the ticket result
1673 * @param cb_cls the callback closure
1674 * FIXME: Return handle??
1675 */
1676void
1677RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_PrivateKey *identity,
1678 const struct GNUNET_RECLAIM_AttributeList *attrs,
1679 const char *rp,
1680 RECLAIM_TICKETS_TicketResult cb,
1681 void *cb_cls)
1682{
1683 struct TicketIssueHandle *tih;
1684
1685 tih = GNUNET_new (struct TicketIssueHandle);
1686 tih->cb = cb;
1687 tih->cb_cls = cb_cls;
1688 tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs);
1689 tih->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1690 tih->identity = *identity;
1691 memcpy (tih->rp_uri, rp, strlen (rp) + 1);
1692
1693 // First check whether the ticket has already been issued
1694 tih->ns_it =
1695 GNUNET_NAMESTORE_zone_iteration_start (nsh,
1696 &tih->identity,
1697 &filter_tickets_error_cb,
1698 tih,
1699 &filter_tickets_cb,
1700 tih,
1701 &filter_tickets_finished_cb,
1702 tih);
1703}
1704
1705
1706/************************************
1707 * Ticket iteration
1708 ************************************/
1709
1710/**
1711 * Cleanup ticket iterator
1712 *
1713 * @param iter handle to the iteration
1714 */
1715static void
1716cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter)
1717{
1718 if (NULL != iter->ns_it)
1719 GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it);
1720 GNUNET_free (iter);
1721}
1722
1723
1724/**
1725 * Return each record of type #GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET
1726 * to the caller and proceed with the iteration.
1727 * FIXME: Should we _not_ proceed automatically here?
1728 *
1729 * @param cls handle to the iteration
1730 * @param zone the ticket issuer
1731 * @param label the ticket rnd
1732 * @param rd_count number of records in record set
1733 * @param rd record set containing a ticket
1734 */
1735static void
1736collect_tickets_cb (void *cls,
1737 const struct GNUNET_CRYPTO_PrivateKey *zone,
1738 const char *label,
1739 unsigned int rd_count,
1740 const struct GNUNET_GNSRECORD_Data *rd)
1741{
1742 struct RECLAIM_TICKETS_Iterator *iter = cls;
1743 struct GNUNET_RECLAIM_Ticket *ticket;
1744 int ticket_found = GNUNET_NO;
1745 const char *rp_uri = NULL;
1746
1747 for (int i = 0; i < rd_count; i++)
1748 {
1749 if (GNUNET_DNSPARSER_TYPE_TXT == rd[i].record_type)
1750 rp_uri = rd[i].data;
1751 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET != rd[i].record_type)
1752 continue;
1753 if ((GNUNET_YES == ticket_found) && (NULL != rp_uri))
1754 break;
1755 ticket = (struct GNUNET_RECLAIM_Ticket *) rd[i].data;
1756 ticket_found = GNUNET_YES;
1757 }
1758 if ((GNUNET_YES == ticket_found) && (NULL != rp_uri))
1759 iter->cb (iter->cb_cls, ticket, rp_uri);
1760 GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1);
1761}
1762
1763
1764/**
1765 * Signal ticket iteration has finished
1766 *
1767 * @param cls handle to the iteration
1768 */
1769static void
1770collect_tickets_finished_cb (void *cls)
1771{
1772 struct RECLAIM_TICKETS_Iterator *iter = cls;
1773
1774 iter->ns_it = NULL;
1775 iter->cb (iter->cb_cls, NULL, NULL);
1776 cleanup_iter (iter);
1777}
1778
1779
1780/**
1781 * Cancel ticket iteration on namestore error
1782 *
1783 * @param cls the iteration handle
1784 */
1785static void
1786collect_tickets_error_cb (void *cls)
1787{
1788 struct RECLAIM_TICKETS_Iterator *iter = cls;
1789
1790 iter->ns_it = NULL;
1791 iter->cb (iter->cb_cls, NULL, NULL);
1792 cleanup_iter (iter);
1793}
1794
1795
1796/**
1797 * Continue ticket iteration
1798 *
1799 * @param iter the iteration to continue
1800 */
1801void
1802RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter)
1803{
1804 GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1);
1805}
1806
1807
1808/**
1809 * Stop a running ticket iteration
1810 *
1811 * @param iter iteration to cancel
1812 */
1813void
1814RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter)
1815{
1816 GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it);
1817 cleanup_iter (iter);
1818}
1819
1820
1821/**
1822 * Iterate over all tickets issued by an identity
1823 *
1824 * @param identity the issuing identity
1825 * @param cb ticket callback function
1826 * @param cb_cls callback closure
1827 * @return a handle to the iteration
1828 */
1829struct RECLAIM_TICKETS_Iterator *
1830RECLAIM_TICKETS_iteration_start (
1831 const struct GNUNET_CRYPTO_PrivateKey *identity,
1832 RECLAIM_TICKETS_TicketIter cb,
1833 void *cb_cls)
1834{
1835 struct RECLAIM_TICKETS_Iterator *iter;
1836
1837 iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator);
1838 iter->cb = cb;
1839 iter->cb_cls = cb_cls;
1840 iter->ns_it =
1841 GNUNET_NAMESTORE_zone_iteration_start (nsh,
1842 identity,
1843 &collect_tickets_error_cb,
1844 iter,
1845 &collect_tickets_cb,
1846 iter,
1847 &collect_tickets_finished_cb,
1848 iter);
1849 return iter;
1850}
1851
1852
1853/**
1854 * Initialize tickets component
1855 *
1856 * @param c the configuration
1857 * @return GNUNET_SYSERR on error
1858 */
1859int
1860RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
1861{
1862 // Get ticket expiration time (relative) from config
1863 if (GNUNET_OK ==
1864 GNUNET_CONFIGURATION_get_value_time (c,
1865 "reclaim",
1866 "TICKET_REFRESH_INTERVAL",
1867 &ticket_refresh_interval))
1868 {
1869 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1870 "Configured refresh interval for tickets: %s\n",
1871 GNUNET_STRINGS_relative_time_to_string (ticket_refresh_interval,
1872 GNUNET_YES));
1873 }
1874 else
1875 {
1876 ticket_refresh_interval = DEFAULT_TICKET_REFRESH_INTERVAL;
1877 }
1878 // Connect to identity and namestore services
1879 nsh = GNUNET_NAMESTORE_connect (c);
1880 if (NULL == nsh)
1881 {
1882 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1883 "error connecting to namestore");
1884 return GNUNET_SYSERR;
1885 }
1886 gns = GNUNET_GNS_connect (c);
1887 if (NULL == gns)
1888 {
1889 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1890 return GNUNET_SYSERR;
1891 }
1892 stats = GNUNET_STATISTICS_create ("reclaim", c);
1893 return GNUNET_OK;
1894}
1895
1896
1897/**
1898 * Close handles and clean up.
1899 * FIXME: cancel all pending operations (gns, ns etc)
1900 */
1901void
1902RECLAIM_TICKETS_deinit (void)
1903{
1904 if (NULL != nsh)
1905 GNUNET_NAMESTORE_disconnect (nsh);
1906 nsh = NULL;
1907 if (NULL != gns)
1908 GNUNET_GNS_disconnect (gns);
1909 gns = NULL;
1910 if (NULL != stats)
1911 {
1912 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
1913 stats = NULL;
1914 }
1915}
diff --git a/src/service/reclaim/gnunet-service-reclaim_tickets.h b/src/service/reclaim/gnunet-service-reclaim_tickets.h
new file mode 100644
index 000000000..b425a3dba
--- /dev/null
+++ b/src/service/reclaim/gnunet-service-reclaim_tickets.h
@@ -0,0 +1,282 @@
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 * @param rp_uri the RP URI associated with the ticket
106 */
107typedef void (*RECLAIM_TICKETS_TicketIter) (
108 void *cls,
109 struct GNUNET_RECLAIM_Ticket *ticket,
110 const char* rp_uri);
111
112
113/**
114 * Continuation called with ticket.
115 *
116 * @param cls closure
117 * @param ticket the ticket
118 * @param presentations new presentations for ticket (NULL on error)
119 * @param success #GNUNET_SYSERR on failure (including timeout/queue
120 * drop/failure to validate) #GNUNET_OK on success
121 * @param emsg NULL on success, otherwise an error message
122 */
123typedef void (*RECLAIM_TICKETS_TicketResult) (
124 void *cls,
125 struct GNUNET_RECLAIM_Ticket *ticket,
126 struct GNUNET_RECLAIM_PresentationList *presentations,
127 int32_t success,
128 const char *emsg);
129
130
131/**
132 * Consume callback.
133 *
134 * @param cls closure
135 * @param identity the issuer of the ticket/attributes
136 * @param attributes attribute list retrieved through ticket
137 * @param presentations attribute presentations (may be NULL)
138 * @param success GNUNET_OK on success
139 * @param emsg error message (NULL on success)
140 */
141typedef void (*RECLAIM_TICKETS_ConsumeCallback) (
142 void *cls,
143 const struct GNUNET_CRYPTO_PublicKey *identity,
144 const struct GNUNET_RECLAIM_AttributeList *attributes,
145 const struct GNUNET_RECLAIM_PresentationList *presentations,
146 int32_t success,
147 const char *emsg);
148
149
150/**
151 * Revocation callback.
152 *
153 * @param cls closure
154 * @param success GNUNET_OK on success
155 */
156typedef void (*RECLAIM_TICKETS_RevokeCallback) (void *cls, int32_t success);
157
158
159/**
160 * Revoke a ticket.
161 * We start by looking up attribute references in order
162 * to change attribute IDs.
163 *
164 * @param ticket ticket to revoke
165 * @param identity private key of issuer
166 * @param cb revocation status callback
167 * @param cb_cls callback closure
168 * @return handle to the operation
169 */
170struct RECLAIM_TICKETS_RevokeHandle *
171RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket,
172 const struct GNUNET_CRYPTO_PrivateKey *identity,
173 RECLAIM_TICKETS_RevokeCallback cb,
174 void *cb_cls);
175
176
177/**
178 * Cancel a revocation.
179 *
180 * @param rh handle to the operation
181 */
182void
183RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh);
184
185
186/**
187 * Consume a ticket.
188 * We first looking attribute references under the label
189 * ticket.rnd in GNS.
190 *
191 * @param ticket the ticket to consume
192 * @param rp_uri the expected RP URI
193 * @param cb callback to call with attributes of ticket
194 * @param cb_cls callback closure
195 * @return handle to the operation
196 */
197struct RECLAIM_TICKETS_ConsumeHandle *
198RECLAIM_TICKETS_consume (const struct GNUNET_RECLAIM_Ticket *ticket,
199 const char *rp_uri,
200 RECLAIM_TICKETS_ConsumeCallback cb,
201 void *cb_cls);
202
203
204/**
205 * Cancel a consume operation
206 *
207 * @param cth the operation to cancel
208 */
209void
210RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth);
211
212
213/**
214 * Issue a new reclaim ticket, thereby authorizing
215 * the audience to access the set of provided attributes.
216 *
217 * @param identity the issuer
218 * @param attrs the attributes to share
219 * @param rp the RP URI
220 * @param cb the callback to call with the ticket result
221 * @param cb_cls the callback closure
222 * FIXME: Return handle??
223 */
224void
225RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_PrivateKey *identity,
226 const struct GNUNET_RECLAIM_AttributeList *attrs,
227 const char *rp,
228 RECLAIM_TICKETS_TicketResult cb,
229 void *cb_cls);
230
231
232/**
233 * Continue ticket iteration
234 *
235 * @param iter the iteration to continue
236 */
237void
238RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter);
239
240
241/**
242 * Stop a running ticket iteration
243 *
244 * @param iter iteration to cancel
245 */
246void
247RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter);
248
249
250/**
251 * Iterate over all tickets issued by an identity
252 *
253 * @param identity the issuing identity
254 * @param cb ticket callback function
255 * @param cb_cls callback closure
256 * @return a handle to the iteration
257 */
258struct RECLAIM_TICKETS_Iterator *
259RECLAIM_TICKETS_iteration_start (
260 const struct GNUNET_CRYPTO_PrivateKey *identity,
261 RECLAIM_TICKETS_TicketIter cb,
262 void *cb_cls);
263
264
265/**
266 * Initialize tickets component
267 *
268 * @param c the configuration
269 * @return GNUNET_SYSERR on error
270 */
271int
272RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c);
273
274
275/**
276 * Close handles and clean up.
277 * FIXME: cancel all pending operations (gns, ns etc)
278 */
279void
280RECLAIM_TICKETS_deinit (void);
281
282#endif
diff --git a/src/service/reclaim/meson.build b/src/service/reclaim/meson.build
new file mode 100644
index 000000000..17f83f204
--- /dev/null
+++ b/src/service/reclaim/meson.build
@@ -0,0 +1,65 @@
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
21endif
22
23libgnunetreclaim = library('gnunetreclaim',
24 libgnunetreclaim_src,
25 soversion: '0',
26 version: '0.0.0',
27 dependencies: [libgnunetutil_dep,
28 libgnunetidentity_dep],
29 include_directories: [incdir, configuration_inc],
30 install: true,
31 install_dir: get_option('libdir'))
32libgnunetreclaim_dep = declare_dependency(link_with : libgnunetreclaim)
33pkg.generate(libgnunetreclaim, url: 'https://www.gnunet.org',
34 description : 'Provides API to access reclaimID')
35
36libgnunetdid = library('gnunetdid',
37 libgnunetdid_src,
38 soversion: '0',
39 version: '0.0.0',
40 dependencies: [libgnunetutil_dep,
41 libgnunetnamestore_dep,
42 libgnunetgnsrecord_dep,
43 libgnunetgns_dep,
44 json_dep,
45 libgnunetidentity_dep],
46 include_directories: [incdir, configuration_inc],
47 install: true,
48 install_dir: get_option('libdir'))
49libgnunetdid_dep = declare_dependency(link_with : libgnunetdid)
50pkg.generate(libgnunetdid, url: 'https://www.gnunet.org',
51 description : 'Provides API to manipulate DID')
52
53executable ('gnunet-service-reclaim',
54 gnunetservicereclaim_src,
55 dependencies: [libgnunetreclaim_dep,
56 libgnunetutil_dep,
57 libgnunetstatistics_dep,
58 libgnunetgnsrecord_dep,
59 libgnunetgns_dep,
60 libgnunetidentity_dep,
61 libgnunetnamestore_dep],
62 include_directories: [incdir, configuration_inc],
63 install: true,
64 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
65
diff --git a/src/service/reclaim/reclaim.conf b/src/service/reclaim/reclaim.conf
new file mode 100644
index 000000000..07facc232
--- /dev/null
+++ b/src/service/reclaim/reclaim.conf
@@ -0,0 +1,22 @@
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/service/reclaim/reclaim.h b/src/service/reclaim/reclaim.h
new file mode 100644
index 000000000..1fb50eafe
--- /dev/null
+++ b/src/service/reclaim/reclaim.h
@@ -0,0 +1,606 @@
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 URI
424 */
425 uint16_t rp_uri_len GNUNET_PACKED;
426
427 /**
428 * Followed by the private key.
429 * Followed by the RP URI.
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 * RP URI length
510 */
511 uint16_t rp_uri_len GNUNET_PACKED;
512
513 /**
514 * Length of new presentations created
515 */
516 uint16_t presentations_len GNUNET_PACKED;
517
518 /*
519 * Followed by the serialized ticket
520 * Followed by the RP URI
521 * Followed by the serialized GNUNET_RECLAIM_PresentationList
522 */
523};
524
525/**
526 * Ticket consume message
527 */
528struct ConsumeTicketMessage
529{
530 /**
531 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET
532 */
533 struct GNUNET_MessageHeader header;
534
535 /**
536 * Unique identifier for this request (for key collisions).
537 */
538 uint32_t id GNUNET_PACKED;
539
540 /**
541 * The length of the ticket
542 */
543 uint16_t tkt_len GNUNET_PACKED;
544
545 /**
546 * RP URI length
547 */
548 uint16_t rp_uri_len GNUNET_PACKED;
549
550 /**
551 * Followed by the serialized ticket.
552 * Followed by the RP URI
553 */
554};
555
556/**
557 * Attribute list is returned from the idp.
558 */
559struct ConsumeTicketResultMessage
560{
561 /**
562 * Message header
563 */
564 struct GNUNET_MessageHeader header;
565
566 /**
567 * Unique identifier for this request (for key collisions).
568 */
569 uint32_t id GNUNET_PACKED;
570
571 /**
572 * Result
573 */
574 uint32_t result GNUNET_PACKED;
575
576 /**
577 * Reserved (alignment)
578 */
579 uint16_t reserved GNUNET_PACKED;
580
581 /**
582 * Length of serialized attribute data
583 */
584 uint16_t attrs_len GNUNET_PACKED;
585
586 /**
587 * Length of presentation data
588 */
589 uint16_t presentations_len;
590
591 /**
592 * The length of the identity public key
593 */
594 uint16_t key_len GNUNET_PACKED;
595
596 /**
597 * Followed by the identity public key.
598 * followed by:
599 * serialized attributes data
600 */
601};
602
603
604GNUNET_NETWORK_STRUCT_END
605
606#endif
diff --git a/src/service/reclaim/reclaim_api.c b/src/service/reclaim/reclaim_api.c
new file mode 100644
index 000000000..f1819614c
--- /dev/null
+++ b/src/service/reclaim/reclaim_api.c
@@ -0,0 +1,1736 @@
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_protocols.h"
29#include "gnunet_reclaim_lib.h"
30#include "gnunet_reclaim_service.h"
31#include "reclaim.h"
32
33#define LOG(kind, ...) GNUNET_log_from (kind, "reclaim-api", __VA_ARGS__)
34
35
36/**
37 * Handle for an operation with the service.
38 */
39struct GNUNET_RECLAIM_Operation
40{
41 /**
42 * Main handle.
43 */
44 struct GNUNET_RECLAIM_Handle *h;
45
46 /**
47 * We keep operations in a DLL.
48 */
49 struct GNUNET_RECLAIM_Operation *next;
50
51 /**
52 * We keep operations in a DLL.
53 */
54 struct GNUNET_RECLAIM_Operation *prev;
55
56 /**
57 * Message to send to the service.
58 * Allocated at the end of this struct.
59 */
60 const struct GNUNET_MessageHeader *msg;
61
62 /**
63 * Continuation to invoke after attribute store call
64 */
65 GNUNET_RECLAIM_ContinuationWithStatus as_cb;
66
67 /**
68 * Attribute result callback
69 */
70 GNUNET_RECLAIM_AttributeResult ar_cb;
71
72 /**
73 * Attribute result callback
74 */
75 GNUNET_RECLAIM_AttributeTicketResult atr_cb;
76
77 /**
78 * Credential result callback
79 */
80 GNUNET_RECLAIM_CredentialResult at_cb;
81
82 /**
83 * Revocation result callback
84 */
85 GNUNET_RECLAIM_ContinuationWithStatus rvk_cb;
86
87 /**
88 * Ticket result callback
89 */
90 GNUNET_RECLAIM_TicketCallback tr_cb;
91
92 /**
93 * Ticket issue result callback
94 */
95 GNUNET_RECLAIM_IssueTicketCallback ti_cb;
96
97 /**
98 * Envelope with the message for this queue entry.
99 */
100 struct GNUNET_MQ_Envelope *env;
101
102 /**
103 * request id
104 */
105 uint32_t r_id;
106
107 /**
108 * Closure for @e cont or @e cb.
109 */
110 void *cls;
111};
112
113
114/**
115 * Handle for a ticket iterator operation
116 */
117struct GNUNET_RECLAIM_TicketIterator
118{
119 /**
120 * Kept in a DLL.
121 */
122 struct GNUNET_RECLAIM_TicketIterator *next;
123
124 /**
125 * Kept in a DLL.
126 */
127 struct GNUNET_RECLAIM_TicketIterator *prev;
128
129 /**
130 * Main handle to access the idp.
131 */
132 struct GNUNET_RECLAIM_Handle *h;
133
134 /**
135 * Function to call on completion.
136 */
137 GNUNET_SCHEDULER_TaskCallback finish_cb;
138
139 /**
140 * Closure for @e finish_cb.
141 */
142 void *finish_cb_cls;
143
144 /**
145 * The continuation to call with the results
146 */
147 GNUNET_RECLAIM_TicketCallback tr_cb;
148
149 /**
150 * Closure for @e tr_cb.
151 */
152 void *cls;
153
154 /**
155 * Function to call on errors.
156 */
157 GNUNET_SCHEDULER_TaskCallback error_cb;
158
159 /**
160 * Closure for @e error_cb.
161 */
162 void *error_cb_cls;
163
164 /**
165 * Envelope of the message to send to the service, if not yet
166 * sent.
167 */
168 struct GNUNET_MQ_Envelope *env;
169
170 /**
171 * The operation id this zone iteration operation has
172 */
173 uint32_t r_id;
174};
175
176
177/**
178 * Handle for a attribute iterator operation
179 */
180struct GNUNET_RECLAIM_AttributeIterator
181{
182 /**
183 * Kept in a DLL.
184 */
185 struct GNUNET_RECLAIM_AttributeIterator *next;
186
187 /**
188 * Kept in a DLL.
189 */
190 struct GNUNET_RECLAIM_AttributeIterator *prev;
191
192 /**
193 * Main handle to access the service.
194 */
195 struct GNUNET_RECLAIM_Handle *h;
196
197 /**
198 * Function to call on completion.
199 */
200 GNUNET_SCHEDULER_TaskCallback finish_cb;
201
202 /**
203 * Closure for @e finish_cb.
204 */
205 void *finish_cb_cls;
206
207 /**
208 * The continuation to call with the results
209 */
210 GNUNET_RECLAIM_AttributeResult proc;
211
212 /**
213 * Closure for @e proc.
214 */
215 void *proc_cls;
216
217 /**
218 * Function to call on errors.
219 */
220 GNUNET_SCHEDULER_TaskCallback error_cb;
221
222 /**
223 * Closure for @e error_cb.
224 */
225 void *error_cb_cls;
226
227 /**
228 * Envelope of the message to send to the service, if not yet
229 * sent.
230 */
231 struct GNUNET_MQ_Envelope *env;
232
233 /**
234 * Private key of the zone.
235 */
236 struct GNUNET_CRYPTO_PrivateKey identity;
237
238 /**
239 * The operation id this zone iteration operation has
240 */
241 uint32_t r_id;
242};
243
244/**
245 * Handle for a credential iterator operation
246 */
247struct GNUNET_RECLAIM_CredentialIterator
248{
249 /**
250 * Kept in a DLL.
251 */
252 struct GNUNET_RECLAIM_CredentialIterator *next;
253
254 /**
255 * Kept in a DLL.
256 */
257 struct GNUNET_RECLAIM_CredentialIterator *prev;
258
259 /**
260 * Main handle to access the service.
261 */
262 struct GNUNET_RECLAIM_Handle *h;
263
264 /**
265 * Function to call on completion.
266 */
267 GNUNET_SCHEDULER_TaskCallback finish_cb;
268
269 /**
270 * Closure for @e finish_cb.
271 */
272 void *finish_cb_cls;
273
274 /**
275 * The continuation to call with the results
276 */
277 GNUNET_RECLAIM_CredentialResult proc;
278
279 /**
280 * Closure for @e proc.
281 */
282 void *proc_cls;
283
284 /**
285 * Function to call on errors.
286 */
287 GNUNET_SCHEDULER_TaskCallback error_cb;
288
289 /**
290 * Closure for @e error_cb.
291 */
292 void *error_cb_cls;
293
294 /**
295 * Envelope of the message to send to the service, if not yet
296 * sent.
297 */
298 struct GNUNET_MQ_Envelope *env;
299
300 /**
301 * Private key of the zone.
302 */
303 struct GNUNET_CRYPTO_PrivateKey identity;
304
305 /**
306 * The operation id this zone iteration operation has
307 */
308 uint32_t r_id;
309};
310
311
312/**
313 * Handle to the service.
314 */
315struct GNUNET_RECLAIM_Handle
316{
317 /**
318 * Configuration to use.
319 */
320 const struct GNUNET_CONFIGURATION_Handle *cfg;
321
322 /**
323 * Socket (if available).
324 */
325 struct GNUNET_CLIENT_Connection *client;
326
327 /**
328 * Closure for 'cb'.
329 */
330 void *cb_cls;
331
332 /**
333 * Head of active operations.
334 */
335 struct GNUNET_RECLAIM_Operation *op_head;
336
337 /**
338 * Tail of active operations.
339 */
340 struct GNUNET_RECLAIM_Operation *op_tail;
341
342 /**
343 * Head of active iterations
344 */
345 struct GNUNET_RECLAIM_AttributeIterator *it_head;
346
347 /**
348 * Tail of active iterations
349 */
350 struct GNUNET_RECLAIM_AttributeIterator *it_tail;
351
352 /**
353 * Head of active iterations
354 */
355 struct GNUNET_RECLAIM_CredentialIterator *ait_head;
356
357 /**
358 * Tail of active iterations
359 */
360 struct GNUNET_RECLAIM_CredentialIterator *ait_tail;
361
362 /**
363 * Head of active iterations
364 */
365 struct GNUNET_RECLAIM_TicketIterator *ticket_it_head;
366
367 /**
368 * Tail of active iterations
369 */
370 struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail;
371
372 /**
373 * Currently pending transmission request, or NULL for none.
374 */
375 struct GNUNET_CLIENT_TransmitHandle *th;
376
377 /**
378 * Task doing exponential back-off trying to reconnect.
379 */
380 struct GNUNET_SCHEDULER_Task *reconnect_task;
381
382 /**
383 * Time for next connect retry.
384 */
385 struct GNUNET_TIME_Relative reconnect_backoff;
386
387 /**
388 * Connection to service (if available).
389 */
390 struct GNUNET_MQ_Handle *mq;
391
392 /**
393 * Request Id generator. Incremented by one for each request.
394 */
395 uint32_t r_id_gen;
396
397 /**
398 * Are we polling for incoming messages right now?
399 */
400 int in_receive;
401};
402
403
404/**
405 * Try again to connect to the service.
406 *
407 * @param h handle to the reclaim service.
408 */
409static void
410reconnect (struct GNUNET_RECLAIM_Handle *h);
411
412
413/**
414 * Reconnect
415 *
416 * @param cls the handle
417 */
418static void
419reconnect_task (void *cls)
420{
421 struct GNUNET_RECLAIM_Handle *handle = cls;
422
423 handle->reconnect_task = NULL;
424 reconnect (handle);
425}
426
427
428/**
429 * Disconnect from service and then reconnect.
430 *
431 * @param handle our service
432 */
433static void
434force_reconnect (struct GNUNET_RECLAIM_Handle *handle)
435{
436 GNUNET_MQ_destroy (handle->mq);
437 handle->mq = NULL;
438 handle->reconnect_backoff =
439 GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
440 handle->reconnect_task =
441 GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
442 &reconnect_task,
443 handle);
444}
445
446
447/**
448 * Free @a it.
449 *
450 * @param it entry to free
451 */
452static void
453free_it (struct GNUNET_RECLAIM_AttributeIterator *it)
454{
455 struct GNUNET_RECLAIM_Handle *h = it->h;
456
457 GNUNET_CONTAINER_DLL_remove (h->it_head, h->it_tail, it);
458 if (NULL != it->env)
459 GNUNET_MQ_discard (it->env);
460 GNUNET_free (it);
461}
462
463
464/**
465 * Free @a it.
466 *
467 * @param ait entry to free
468 */
469static void
470free_ait (struct GNUNET_RECLAIM_CredentialIterator *ait)
471{
472 struct GNUNET_RECLAIM_Handle *h = ait->h;
473
474 GNUNET_CONTAINER_DLL_remove (h->ait_head, h->ait_tail, ait);
475 if (NULL != ait->env)
476 GNUNET_MQ_discard (ait->env);
477 GNUNET_free (ait);
478}
479
480
481/**
482 * Free @a op
483 *
484 * @param op the operation to free
485 */
486static void
487free_op (struct GNUNET_RECLAIM_Operation *op)
488{
489 if (NULL == op)
490 return;
491 if (NULL != op->env)
492 GNUNET_MQ_discard (op->env);
493 GNUNET_free (op);
494}
495
496
497/**
498 * Generic error handler, called with the appropriate error code and
499 * the same closure specified at the creation of the message queue.
500 * Not every message queue implementation supports an error handler.
501 *
502 * @param cls closure with the `struct GNUNET_GNS_Handle *`
503 * @param error error code
504 */
505static void
506mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
507{
508 struct GNUNET_RECLAIM_Handle *handle = cls;
509
510 force_reconnect (handle);
511}
512
513
514/**
515 * Handle an incoming message of type
516 * #GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE
517 *
518 * @param cls
519 * @param msg the message we received
520 */
521static void
522handle_success_response (void *cls, const struct SuccessResultMessage *msg)
523{
524 struct GNUNET_RECLAIM_Handle *h = cls;
525 struct GNUNET_RECLAIM_Operation *op;
526 uint32_t r_id = ntohl (msg->id);
527 int res;
528 const char *emsg;
529
530 for (op = h->op_head; NULL != op; op = op->next)
531 if (op->r_id == r_id)
532 break;
533 if (NULL == op)
534 return;
535
536 res = ntohl (msg->op_result);
537 LOG (GNUNET_ERROR_TYPE_DEBUG,
538 "Received SUCCESS_RESPONSE with result %d\n",
539 res);
540
541 /* TODO: add actual error message to response... */
542 if (GNUNET_SYSERR == res)
543 emsg = _ ("failed to store record\n");
544 else
545 emsg = NULL;
546 if (NULL != op->as_cb)
547 op->as_cb (op->cls, res, emsg);
548 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
549 free_op (op);
550}
551
552
553/**
554 * Handle an incoming message of type
555 * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
556 *
557 * @param cls
558 * @param msg the message we received
559 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
560 */
561static int
562check_consume_ticket_result (void *cls,
563 const struct ConsumeTicketResultMessage *msg)
564{
565 size_t msg_len;
566 size_t attrs_len;
567 size_t pl_len;
568 size_t key_len;
569
570 msg_len = ntohs (msg->header.size);
571 attrs_len = ntohs (msg->attrs_len);
572 key_len = ntohs (msg->key_len);
573 pl_len = ntohs (msg->presentations_len);
574 if (msg_len != sizeof(*msg) + attrs_len + pl_len + key_len)
575 {
576 GNUNET_break (0);
577 return GNUNET_SYSERR;
578 }
579 return GNUNET_OK;
580}
581
582
583/**
584 * Handle an incoming message of type
585 * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
586 *
587 * @param cls
588 * @param msg the message we received
589 */
590static void
591handle_consume_ticket_result (void *cls,
592 const struct ConsumeTicketResultMessage *msg)
593{
594 struct GNUNET_CRYPTO_PublicKey identity;
595 struct GNUNET_RECLAIM_Handle *h = cls;
596 struct GNUNET_RECLAIM_Operation *op;
597 size_t attrs_len;
598 size_t pl_len;
599 size_t key_len;
600 size_t read;
601 uint32_t r_id = ntohl (msg->id);
602 char *read_ptr;
603
604 attrs_len = ntohs (msg->attrs_len);
605 key_len = ntohs (msg->key_len);
606 pl_len = ntohs (msg->presentations_len);
607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n");
608
609
610 for (op = h->op_head; NULL != op; op = op->next)
611 if (op->r_id == r_id)
612 break;
613 if (NULL == op)
614 return;
615
616 {
617 struct GNUNET_RECLAIM_AttributeList *attrs;
618 struct GNUNET_RECLAIM_AttributeListEntry *le;
619 struct GNUNET_RECLAIM_PresentationList *pl;
620 struct GNUNET_RECLAIM_PresentationListEntry *ple;
621 read_ptr = (char *) &msg[1];
622 GNUNET_assert (GNUNET_SYSERR !=
623 GNUNET_CRYPTO_read_public_key_from_buffer (read_ptr,
624 key_len,
625 &identity,
626 &read));
627 read_ptr += read;
628 attrs =
629 GNUNET_RECLAIM_attribute_list_deserialize (read_ptr, attrs_len);
630 read_ptr += attrs_len;
631 pl = GNUNET_RECLAIM_presentation_list_deserialize (read_ptr, pl_len);
632 if (NULL != op->atr_cb)
633 {
634 if (NULL == attrs)
635 {
636 op->atr_cb (op->cls, &identity, NULL, NULL);
637 }
638 else
639 {
640 for (le = attrs->list_head; NULL != le; le = le->next)
641 {
642 if (GNUNET_NO ==
643 GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
644 {
645 for (ple = pl->list_head; NULL != ple; ple = ple->next)
646 {
647 if (GNUNET_YES ==
648 GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
649 &ple->presentation->credential_id)
650 )
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 size_t rp_uri_len;
923
924 msg_len = ntohs (msg->header.size);
925 pres_len = ntohs (msg->presentations_len);
926 tkt_len = ntohs (msg->tkt_len);
927 rp_uri_len = ntohs (msg->rp_uri_len);
928 if (msg_len != sizeof(*msg) + pres_len + tkt_len + rp_uri_len)
929 {
930 GNUNET_break (0);
931 return GNUNET_SYSERR;
932 }
933 return GNUNET_OK;
934}
935
936
937/**
938 * Handle an incoming message of type
939 * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
940 *
941 * @param cls
942 * @param msg the message we received
943 */
944static void
945handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
946{
947 struct GNUNET_RECLAIM_Handle *handle = cls;
948 struct GNUNET_RECLAIM_Operation *op;
949 struct GNUNET_RECLAIM_TicketIterator *it;
950 struct GNUNET_RECLAIM_PresentationList *presentation;
951 uint32_t r_id = ntohl (msg->id);
952 struct GNUNET_RECLAIM_Ticket *ticket = NULL;
953 size_t pres_len;
954 size_t tkt_len;
955 size_t rp_uri_len;
956 size_t tb_read = 0;
957 char *buf;
958 char *rp_uri = NULL;
959
960 tkt_len = ntohs (msg->tkt_len);
961 rp_uri_len = ntohs (msg->rp_uri_len);
962 pres_len = ntohs (msg->presentations_len);
963 for (op = handle->op_head; NULL != op; op = op->next)
964 if (op->r_id == r_id)
965 break;
966 for (it = handle->ticket_it_head; NULL != it; it = it->next)
967 if (it->r_id == r_id)
968 break;
969 if ((NULL == op) && (NULL == it))
970 return;
971 buf = (char*) &msg[1];
972 if (0 < tkt_len)
973 {
974 ticket = (struct GNUNET_RECLAIM_Ticket*) buf;
975 buf += tkt_len;
976 tb_read += tkt_len;
977 }
978 if (0 < rp_uri_len)
979 rp_uri = buf;
980 if (NULL != op)
981 {
982 if (0 < pres_len)
983 presentation = GNUNET_RECLAIM_presentation_list_deserialize (
984 buf,
985 pres_len);
986 GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
987 if (0 == tb_read)
988 {
989 if (NULL != op->ti_cb)
990 op->ti_cb (op->cls, NULL, NULL);
991 }
992 else
993 {
994 if (NULL != op->ti_cb)
995 op->ti_cb (op->cls,
996 ticket,
997 (0 < pres_len) ? presentation : NULL);
998 }
999 if (0 < pres_len)
1000 GNUNET_RECLAIM_presentation_list_destroy (presentation);
1001 free_op (op);
1002 return;
1003 }
1004 else if (NULL != it)
1005 {
1006 if (0 == tkt_len)
1007 {
1008 GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
1009 handle->ticket_it_tail,
1010 it);
1011 it->finish_cb (it->finish_cb_cls);
1012 GNUNET_free (it);
1013 }
1014 else
1015 {
1016 if (NULL != it->tr_cb)
1017 it->tr_cb (it->cls, ticket, rp_uri);
1018 }
1019 return;
1020 }
1021 GNUNET_break (0);
1022}
1023
1024
1025/**
1026 * Handle an incoming message of type
1027 * #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
1028 *
1029 * @param cls
1030 * @param msg the message we received
1031 */
1032static void
1033handle_revoke_ticket_result (void *cls,
1034 const struct RevokeTicketResultMessage *msg)
1035{
1036 struct GNUNET_RECLAIM_Handle *h = cls;
1037 struct GNUNET_RECLAIM_Operation *op;
1038 uint32_t r_id = ntohl (msg->id);
1039 int32_t success;
1040
1041 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing revocation result.\n");
1042
1043
1044 for (op = h->op_head; NULL != op; op = op->next)
1045 if (op->r_id == r_id)
1046 break;
1047 if (NULL == op)
1048 return;
1049 success = ntohl (msg->success);
1050 {
1051 if (NULL != op->rvk_cb)
1052 {
1053 op->rvk_cb (op->cls, success, NULL);
1054 }
1055 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
1056 free_op (op);
1057 return;
1058 }
1059 GNUNET_assert (0);
1060}
1061
1062
1063/**
1064 * Try again to connect to the service.
1065 *
1066 * @param h handle to the reclaim service.
1067 */
1068static void
1069reconnect (struct GNUNET_RECLAIM_Handle *h)
1070{
1071 struct GNUNET_MQ_MessageHandler handlers[] =
1072 { GNUNET_MQ_hd_fixed_size (success_response,
1073 GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE,
1074 struct SuccessResultMessage,
1075 h),
1076 GNUNET_MQ_hd_var_size (attribute_result,
1077 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
1078 struct AttributeResultMessage,
1079 h),
1080 GNUNET_MQ_hd_var_size (credential_result,
1081 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT,
1082 struct CredentialResultMessage,
1083 h),
1084 GNUNET_MQ_hd_var_size (ticket_result,
1085 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
1086 struct TicketResultMessage,
1087 h),
1088 GNUNET_MQ_hd_var_size (consume_ticket_result,
1089 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
1090 struct ConsumeTicketResultMessage,
1091 h),
1092 GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
1093 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT,
1094 struct RevokeTicketResultMessage,
1095 h),
1096 GNUNET_MQ_handler_end () };
1097 struct GNUNET_RECLAIM_Operation *op;
1098
1099 GNUNET_assert (NULL == h->mq);
1100 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to reclaim service.\n");
1101
1102 h->mq =
1103 GNUNET_CLIENT_connect (h->cfg, "reclaim", handlers, &mq_error_handler, h);
1104 if (NULL == h->mq)
1105 return;
1106 for (op = h->op_head; NULL != op; op = op->next)
1107 GNUNET_MQ_send_copy (h->mq, op->env);
1108}
1109
1110
1111/**
1112 * Connect to the reclaim service.
1113 *
1114 * @param cfg the configuration to use
1115 * @return handle to use
1116 */
1117struct GNUNET_RECLAIM_Handle *
1118GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
1119{
1120 struct GNUNET_RECLAIM_Handle *h;
1121
1122 h = GNUNET_new (struct GNUNET_RECLAIM_Handle);
1123 h->cfg = cfg;
1124 reconnect (h);
1125 if (NULL == h->mq)
1126 {
1127 GNUNET_free (h);
1128 return NULL;
1129 }
1130 return h;
1131}
1132
1133
1134void
1135GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op)
1136{
1137 struct GNUNET_RECLAIM_Handle *h = op->h;
1138
1139 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
1140 free_op (op);
1141}
1142
1143
1144/**
1145 * Disconnect from service
1146 *
1147 * @param h handle to destroy
1148 */
1149void
1150GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h)
1151{
1152 GNUNET_assert (NULL != h);
1153 if (NULL != h->mq)
1154 {
1155 GNUNET_MQ_destroy (h->mq);
1156 h->mq = NULL;
1157 }
1158 if (NULL != h->reconnect_task)
1159 {
1160 GNUNET_SCHEDULER_cancel (h->reconnect_task);
1161 h->reconnect_task = NULL;
1162 }
1163 GNUNET_assert (NULL == h->op_head);
1164 GNUNET_free (h);
1165}
1166
1167
1168struct GNUNET_RECLAIM_Operation *
1169GNUNET_RECLAIM_attribute_store (
1170 struct GNUNET_RECLAIM_Handle *h,
1171 const struct GNUNET_CRYPTO_PrivateKey *pkey,
1172 const struct GNUNET_RECLAIM_Attribute *attr,
1173 const struct GNUNET_TIME_Relative *exp_interval,
1174 GNUNET_RECLAIM_ContinuationWithStatus cont,
1175 void *cont_cls)
1176{
1177 struct GNUNET_RECLAIM_Operation *op;
1178 struct AttributeStoreMessage *sam;
1179 size_t attr_len;
1180 size_t key_len;
1181 ssize_t written;
1182 char *buf;
1183
1184 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1185 op->h = h;
1186 op->as_cb = cont;
1187 op->cls = cont_cls;
1188 op->r_id = h->r_id_gen++;
1189 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1190 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
1191 attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (attr);
1192 op->env = GNUNET_MQ_msg_extra (sam,
1193 attr_len + key_len,
1194 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE);
1195 sam->key_len = htons (key_len);
1196 buf = (char *) &sam[1];
1197 written = GNUNET_CRYPTO_write_private_key_to_buffer (pkey, buf, key_len);
1198 GNUNET_assert (0 < written);
1199 buf += written;
1200 sam->id = htonl (op->r_id);
1201 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1202
1203 GNUNET_RECLAIM_attribute_serialize (attr, buf);
1204
1205 sam->attr_len = htons (attr_len);
1206 if (NULL != h->mq)
1207 GNUNET_MQ_send_copy (h->mq, op->env);
1208 return op;
1209}
1210
1211
1212struct GNUNET_RECLAIM_Operation *
1213GNUNET_RECLAIM_attribute_delete (
1214 struct GNUNET_RECLAIM_Handle *h,
1215 const struct GNUNET_CRYPTO_PrivateKey *pkey,
1216 const struct GNUNET_RECLAIM_Attribute *attr,
1217 GNUNET_RECLAIM_ContinuationWithStatus cont,
1218 void *cont_cls)
1219{
1220 struct GNUNET_RECLAIM_Operation *op;
1221 struct AttributeDeleteMessage *dam;
1222 size_t attr_len;
1223 size_t key_len;
1224 ssize_t written;
1225 char *buf;
1226
1227 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1228 op->h = h;
1229 op->as_cb = cont;
1230 op->cls = cont_cls;
1231 op->r_id = h->r_id_gen++;
1232 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1233 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
1234 attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (attr);
1235 op->env = GNUNET_MQ_msg_extra (dam,
1236 attr_len + key_len,
1237 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE);
1238 dam->key_len = htons (key_len);
1239 buf = (char *) &dam[1];
1240 written = GNUNET_CRYPTO_write_private_key_to_buffer (pkey, buf, key_len);
1241 GNUNET_assert (0 < written);
1242 buf += written;
1243 dam->id = htonl (op->r_id);
1244 GNUNET_RECLAIM_attribute_serialize (attr, buf);
1245
1246 dam->attr_len = htons (attr_len);
1247 if (NULL != h->mq)
1248 GNUNET_MQ_send_copy (h->mq, op->env);
1249 return op;
1250}
1251
1252
1253struct GNUNET_RECLAIM_Operation *
1254GNUNET_RECLAIM_credential_store (
1255 struct GNUNET_RECLAIM_Handle *h,
1256 const struct GNUNET_CRYPTO_PrivateKey *pkey,
1257 const struct GNUNET_RECLAIM_Credential *credential,
1258 const struct GNUNET_TIME_Relative *exp_interval,
1259 GNUNET_RECLAIM_ContinuationWithStatus cont,
1260 void *cont_cls)
1261{
1262 struct GNUNET_RECLAIM_Operation *op;
1263 struct AttributeStoreMessage *sam;
1264 size_t attr_len;
1265 size_t key_len;
1266 ssize_t written;
1267 char *buf;
1268
1269 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1270 op->h = h;
1271 op->as_cb = cont;
1272 op->cls = cont_cls;
1273 op->r_id = h->r_id_gen++;
1274 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
1275 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1276 attr_len = GNUNET_RECLAIM_credential_serialize_get_size (credential);
1277 op->env = GNUNET_MQ_msg_extra (sam,
1278 attr_len + key_len,
1279 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE);
1280 sam->key_len = htons (key_len);
1281 buf = (char *) &sam[1];
1282 written = GNUNET_CRYPTO_write_private_key_to_buffer (pkey, buf, key_len);
1283 GNUNET_assert (0 <= written);
1284 buf += written;
1285 sam->id = htonl (op->r_id);
1286 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1287
1288 GNUNET_RECLAIM_credential_serialize (credential, buf);
1289
1290 sam->attr_len = htons (attr_len);
1291 if (NULL != h->mq)
1292 GNUNET_MQ_send_copy (h->mq, op->env);
1293 return op;
1294}
1295
1296
1297struct GNUNET_RECLAIM_Operation *
1298GNUNET_RECLAIM_credential_delete (
1299 struct GNUNET_RECLAIM_Handle *h,
1300 const struct GNUNET_CRYPTO_PrivateKey *pkey,
1301 const struct GNUNET_RECLAIM_Credential *attr,
1302 GNUNET_RECLAIM_ContinuationWithStatus cont,
1303 void *cont_cls)
1304{
1305 struct GNUNET_RECLAIM_Operation *op;
1306 struct AttributeDeleteMessage *dam;
1307 size_t attr_len;
1308 size_t key_len;
1309 ssize_t written;
1310 char *buf;
1311
1312 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1313 op->h = h;
1314 op->as_cb = cont;
1315 op->cls = cont_cls;
1316 op->r_id = h->r_id_gen++;
1317 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
1318 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1319 attr_len = GNUNET_RECLAIM_credential_serialize_get_size (attr);
1320 op->env = GNUNET_MQ_msg_extra (dam,
1321 attr_len + key_len,
1322 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE);
1323 dam->key_len = htons (key_len);
1324 buf = (char *) &dam[1];
1325 written = GNUNET_CRYPTO_write_private_key_to_buffer (pkey, buf, key_len);
1326 GNUNET_assert (0 <= written);
1327 buf += written;
1328 dam->id = htonl (op->r_id);
1329 GNUNET_RECLAIM_credential_serialize (attr, buf);
1330
1331 dam->attr_len = htons (attr_len);
1332 if (NULL != h->mq)
1333 GNUNET_MQ_send_copy (h->mq, op->env);
1334 return op;
1335}
1336
1337
1338struct GNUNET_RECLAIM_AttributeIterator *
1339GNUNET_RECLAIM_get_attributes_start (
1340 struct GNUNET_RECLAIM_Handle *h,
1341 const struct GNUNET_CRYPTO_PrivateKey *identity,
1342 GNUNET_SCHEDULER_TaskCallback error_cb,
1343 void *error_cb_cls,
1344 GNUNET_RECLAIM_AttributeResult proc,
1345 void *proc_cls,
1346 GNUNET_SCHEDULER_TaskCallback finish_cb,
1347 void *finish_cb_cls)
1348{
1349 struct GNUNET_RECLAIM_AttributeIterator *it;
1350 struct GNUNET_MQ_Envelope *env;
1351 struct AttributeIterationStartMessage *msg;
1352 uint32_t rid;
1353 size_t key_len;
1354
1355 rid = h->r_id_gen++;
1356 it = GNUNET_new (struct GNUNET_RECLAIM_AttributeIterator);
1357 it->h = h;
1358 it->error_cb = error_cb;
1359 it->error_cb_cls = error_cb_cls;
1360 it->finish_cb = finish_cb;
1361 it->finish_cb_cls = finish_cb_cls;
1362 it->proc = proc;
1363 it->proc_cls = proc_cls;
1364 it->r_id = rid;
1365 it->identity = *identity;
1366 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1367 GNUNET_CONTAINER_DLL_insert_tail (h->it_head, h->it_tail, it);
1368 env =
1369 GNUNET_MQ_msg_extra (msg,
1370 key_len,
1371 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START);
1372 msg->id = htonl (rid);
1373 msg->key_len = htons (key_len);
1374 GNUNET_CRYPTO_write_private_key_to_buffer (identity, &msg[1], key_len);
1375 if (NULL == h->mq)
1376 it->env = env;
1377 else
1378 GNUNET_MQ_send (h->mq, env);
1379 return it;
1380}
1381
1382
1383void
1384GNUNET_RECLAIM_get_attributes_next (struct GNUNET_RECLAIM_AttributeIterator *it)
1385{
1386 struct GNUNET_RECLAIM_Handle *h = it->h;
1387 struct AttributeIterationNextMessage *msg;
1388 struct GNUNET_MQ_Envelope *env;
1389
1390 env =
1391 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT);
1392 msg->id = htonl (it->r_id);
1393 GNUNET_MQ_send (h->mq, env);
1394}
1395
1396
1397void
1398GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
1399{
1400 struct GNUNET_RECLAIM_Handle *h = it->h;
1401 struct GNUNET_MQ_Envelope *env;
1402 struct AttributeIterationStopMessage *msg;
1403
1404 if (NULL != h->mq)
1405 {
1406 env =
1407 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP);
1408 msg->id = htonl (it->r_id);
1409 GNUNET_MQ_send (h->mq, env);
1410 }
1411 free_it (it);
1412}
1413
1414
1415struct GNUNET_RECLAIM_CredentialIterator *
1416GNUNET_RECLAIM_get_credentials_start (
1417 struct GNUNET_RECLAIM_Handle *h,
1418 const struct GNUNET_CRYPTO_PrivateKey *identity,
1419 GNUNET_SCHEDULER_TaskCallback error_cb,
1420 void *error_cb_cls,
1421 GNUNET_RECLAIM_CredentialResult proc,
1422 void *proc_cls,
1423 GNUNET_SCHEDULER_TaskCallback finish_cb,
1424 void *finish_cb_cls)
1425{
1426 struct GNUNET_RECLAIM_CredentialIterator *ait;
1427 struct GNUNET_MQ_Envelope *env;
1428 struct CredentialIterationStartMessage *msg;
1429 uint32_t rid;
1430 size_t key_len;
1431
1432 rid = h->r_id_gen++;
1433 ait = GNUNET_new (struct GNUNET_RECLAIM_CredentialIterator);
1434 ait->h = h;
1435 ait->error_cb = error_cb;
1436 ait->error_cb_cls = error_cb_cls;
1437 ait->finish_cb = finish_cb;
1438 ait->finish_cb_cls = finish_cb_cls;
1439 ait->proc = proc;
1440 ait->proc_cls = proc_cls;
1441 ait->r_id = rid;
1442 ait->identity = *identity;
1443 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1444 GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait);
1445 env =
1446 GNUNET_MQ_msg_extra (msg,
1447 key_len,
1448 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START)
1449 ;
1450 msg->id = htonl (rid);
1451 msg->key_len = htons (key_len);
1452 GNUNET_CRYPTO_write_private_key_to_buffer (identity, &msg[1], key_len);
1453 if (NULL == h->mq)
1454 ait->env = env;
1455 else
1456 GNUNET_MQ_send (h->mq, env);
1457 return ait;
1458}
1459
1460
1461void
1462GNUNET_RECLAIM_get_credentials_next (struct
1463 GNUNET_RECLAIM_CredentialIterator *ait)
1464{
1465 struct GNUNET_RECLAIM_Handle *h = ait->h;
1466 struct CredentialIterationNextMessage *msg;
1467 struct GNUNET_MQ_Envelope *env;
1468
1469 env =
1470 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT);
1471 msg->id = htonl (ait->r_id);
1472 GNUNET_MQ_send (h->mq, env);
1473}
1474
1475
1476void
1477GNUNET_RECLAIM_get_credentials_stop (struct
1478 GNUNET_RECLAIM_CredentialIterator *ait)
1479{
1480 struct GNUNET_RECLAIM_Handle *h = ait->h;
1481 struct GNUNET_MQ_Envelope *env;
1482 struct CredentialIterationStopMessage *msg;
1483
1484 if (NULL != h->mq)
1485 {
1486 env =
1487 GNUNET_MQ_msg (msg,
1488 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP);
1489 msg->id = htonl (ait->r_id);
1490 GNUNET_MQ_send (h->mq, env);
1491 }
1492 free_ait (ait);
1493}
1494
1495
1496struct GNUNET_RECLAIM_Operation *
1497GNUNET_RECLAIM_ticket_issue (
1498 struct GNUNET_RECLAIM_Handle *h,
1499 const struct GNUNET_CRYPTO_PrivateKey *iss,
1500 const char *rp,
1501 const struct GNUNET_RECLAIM_AttributeList *attrs,
1502 GNUNET_RECLAIM_IssueTicketCallback cb,
1503 void *cb_cls)
1504{
1505 struct GNUNET_RECLAIM_Operation *op;
1506 struct IssueTicketMessage *tim;
1507 size_t attr_len;
1508 size_t key_len;
1509 size_t rpk_len;
1510 ssize_t written;
1511 char *buf;
1512
1513 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1514 op->h = h;
1515 op->ti_cb = cb;
1516 op->cls = cb_cls;
1517 op->r_id = h->r_id_gen++;
1518 key_len = GNUNET_CRYPTO_private_key_get_length (iss);
1519 rpk_len = strlen (rp) + 1;
1520 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1521 attr_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
1522 op->env = GNUNET_MQ_msg_extra (tim,
1523 attr_len + key_len + rpk_len,
1524 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET);
1525 tim->key_len = htons (key_len);
1526 tim->rp_uri_len = htons (rpk_len);
1527 buf = (char *) &tim[1];
1528 written = GNUNET_CRYPTO_write_private_key_to_buffer (iss, buf, key_len);
1529 GNUNET_assert (0 <= written);
1530 buf += written;
1531 memcpy (buf, rp, rpk_len);
1532 written = rpk_len;
1533 GNUNET_assert (0 <= written);
1534 buf += written;
1535 tim->id = htonl (op->r_id);
1536
1537 GNUNET_RECLAIM_attribute_list_serialize (attrs, buf);
1538 tim->attr_len = htons (attr_len);
1539 if (NULL != h->mq)
1540 GNUNET_MQ_send_copy (h->mq, op->env);
1541 return op;
1542}
1543
1544
1545struct GNUNET_RECLAIM_Operation *
1546GNUNET_RECLAIM_ticket_consume (
1547 struct GNUNET_RECLAIM_Handle *h,
1548 const struct GNUNET_RECLAIM_Ticket *ticket,
1549 const char *rp_uri,
1550 GNUNET_RECLAIM_AttributeTicketResult cb,
1551 void *cb_cls)
1552{
1553 struct GNUNET_RECLAIM_Operation *op;
1554 struct ConsumeTicketMessage *ctm;
1555 size_t tkt_len;
1556 size_t rp_uri_len;
1557 char *buf;
1558
1559 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1560 op->h = h;
1561 op->atr_cb = cb;
1562 op->cls = cb_cls;
1563 op->r_id = h->r_id_gen++;
1564 tkt_len = strlen (ticket->gns_name) + 1;
1565 rp_uri_len = strlen (rp_uri) + 1;
1566 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1567 op->env = GNUNET_MQ_msg_extra (ctm,
1568 tkt_len + rp_uri_len,
1569 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET);
1570 buf = (char*) &ctm[1];
1571 ctm->rp_uri_len = htons (rp_uri_len);
1572 ctm->tkt_len = htons (tkt_len);
1573 memcpy (buf, ticket, tkt_len);
1574 buf += tkt_len;
1575 memcpy (buf, rp_uri, rp_uri_len);
1576 ctm->id = htonl (op->r_id);
1577 if (NULL != h->mq)
1578 GNUNET_MQ_send_copy (h->mq, op->env);
1579 else
1580 reconnect (h);
1581 return op;
1582}
1583
1584
1585struct GNUNET_RECLAIM_TicketIterator *
1586GNUNET_RECLAIM_ticket_iteration_start (
1587 struct GNUNET_RECLAIM_Handle *h,
1588 const struct GNUNET_CRYPTO_PrivateKey *identity,
1589 GNUNET_SCHEDULER_TaskCallback error_cb,
1590 void *error_cb_cls,
1591 GNUNET_RECLAIM_TicketCallback proc,
1592 void *proc_cls,
1593 GNUNET_SCHEDULER_TaskCallback finish_cb,
1594 void *finish_cb_cls)
1595{
1596 struct GNUNET_RECLAIM_TicketIterator *it;
1597 struct GNUNET_MQ_Envelope *env;
1598 struct TicketIterationStartMessage *msg;
1599 uint32_t rid;
1600 size_t key_len;
1601
1602 rid = h->r_id_gen++;
1603 it = GNUNET_new (struct GNUNET_RECLAIM_TicketIterator);
1604 it->h = h;
1605 it->error_cb = error_cb;
1606 it->error_cb_cls = error_cb_cls;
1607 it->finish_cb = finish_cb;
1608 it->finish_cb_cls = finish_cb_cls;
1609 it->tr_cb = proc;
1610 it->cls = proc_cls;
1611 it->r_id = rid;
1612
1613 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1614 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, h->ticket_it_tail, it);
1615 env = GNUNET_MQ_msg_extra (msg,
1616 key_len,
1617 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START)
1618 ;
1619 msg->id = htonl (rid);
1620 msg->key_len = htons (key_len);
1621 GNUNET_CRYPTO_write_private_key_to_buffer (identity,
1622 &msg[1],
1623 key_len);
1624 if (NULL == h->mq)
1625 it->env = env;
1626 else
1627 GNUNET_MQ_send (h->mq, env);
1628 return it;
1629}
1630
1631
1632/**
1633 * Calls the ticket processor specified in
1634 * #GNUNET_RECLAIM_ticket_iteration_start for the next record.
1635 *
1636 * @param it the iterator
1637 */
1638void
1639GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it)
1640{
1641 struct GNUNET_RECLAIM_Handle *h = it->h;
1642 struct TicketIterationNextMessage *msg;
1643 struct GNUNET_MQ_Envelope *env;
1644
1645 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT);
1646 msg->id = htonl (it->r_id);
1647 GNUNET_MQ_send (h->mq, env);
1648}
1649
1650
1651/**
1652 * Stops iteration and releases the handle for further calls. Must
1653 * be called on any iteration that has not yet completed prior to calling
1654 * #GNUNET_RECLAIM_disconnect.
1655 *
1656 * @param it the iterator
1657 */
1658void
1659GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it)
1660{
1661 struct GNUNET_RECLAIM_Handle *h = it->h;
1662 struct GNUNET_MQ_Envelope *env;
1663 struct TicketIterationStopMessage *msg;
1664
1665 if (NULL != h->mq)
1666 {
1667 env =
1668 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP);
1669 msg->id = htonl (it->r_id);
1670 GNUNET_MQ_send (h->mq, env);
1671 }
1672 GNUNET_free (it);
1673}
1674
1675
1676/**
1677 * Revoked an issued ticket. The relying party will be unable to retrieve
1678 * attributes. Other issued tickets remain unaffected.
1679 * This includes tickets issued to other relying parties as well as to
1680 * other tickets issued to the audience specified in this ticket.
1681 *
1682 * @param h the identity provider to use
1683 * @param identity the issuing identity
1684 * @param ticket the ticket to revoke
1685 * @param cb the callback
1686 * @param cb_cls the callback closure
1687 * @return handle to abort the operation
1688 */
1689struct GNUNET_RECLAIM_Operation *
1690GNUNET_RECLAIM_ticket_revoke (
1691 struct GNUNET_RECLAIM_Handle *h,
1692 const struct GNUNET_CRYPTO_PrivateKey *identity,
1693 const struct GNUNET_RECLAIM_Ticket *ticket,
1694 GNUNET_RECLAIM_ContinuationWithStatus cb,
1695 void *cb_cls)
1696{
1697 struct GNUNET_RECLAIM_Operation *op;
1698 struct RevokeTicketMessage *msg;
1699 uint32_t rid;
1700 size_t key_len;
1701 size_t tkt_len;
1702 ssize_t written;
1703 char *buf;
1704
1705 rid = h->r_id_gen++;
1706 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1707 op->h = h;
1708 op->rvk_cb = cb;
1709 op->cls = cb_cls;
1710 op->r_id = rid;
1711 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1712 key_len = GNUNET_CRYPTO_private_key_get_length (identity);
1713 tkt_len = strlen (ticket->gns_name) + 1;
1714 op->env = GNUNET_MQ_msg_extra (msg,
1715 key_len + tkt_len,
1716 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET);
1717 msg->id = htonl (rid);
1718 msg->key_len = htons (key_len);
1719 msg->tkt_len = htons (tkt_len);
1720 buf = (char*) &msg[1];
1721 written = GNUNET_CRYPTO_write_private_key_to_buffer (identity,
1722 buf,
1723 key_len);
1724 GNUNET_assert (0 <= written);
1725 buf += written;
1726 memcpy (buf, ticket, tkt_len);
1727 if (NULL != h->mq)
1728 {
1729 GNUNET_MQ_send (h->mq, op->env);
1730 op->env = NULL;
1731 }
1732 return op;
1733}
1734
1735
1736/* end of reclaim_api.c */
diff --git a/src/service/reclaim/reclaim_attribute.c b/src/service/reclaim/reclaim_attribute.c
new file mode 100644
index 000000000..b235ed945
--- /dev/null
+++ b/src/service/reclaim/reclaim_attribute.c
@@ -0,0 +1,547 @@
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/service/reclaim/reclaim_attribute.h b/src/service/reclaim/reclaim_attribute.h
new file mode 100644
index 000000000..44d85e61c
--- /dev/null
+++ b/src/service/reclaim/reclaim_attribute.h
@@ -0,0 +1,83 @@
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/service/reclaim/reclaim_credential.c b/src/service/reclaim/reclaim_credential.c
new file mode 100644
index 000000000..a0cb7a62e
--- /dev/null
+++ b/src/service/reclaim/reclaim_credential.c
@@ -0,0 +1,1003 @@
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 "gnunet_util_lib.h"
27#include "gnunet_reclaim_plugin.h"
28#include "reclaim_credential.h"
29
30
31/**
32 * Handle for a plugin
33 */
34struct Plugin
35{
36 /**
37 * Name of the plugin
38 */
39 char *library_name;
40
41 /**
42 * Plugin API
43 */
44 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
45};
46
47
48/**
49 * Plugins
50 */
51static struct Plugin **credential_plugins;
52
53
54/**
55 * Number of plugins
56 */
57static unsigned int num_plugins;
58
59
60/**
61 * Init canary
62 */
63static int initialized;
64
65
66/**
67 * Add a plugin
68 *
69 * @param cls closure
70 * @param library_name name of the API library
71 * @param lib_ret the plugin API pointer
72 */
73static void
74add_plugin (void *cls, const char *library_name, void *lib_ret)
75{
76 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = lib_ret;
77 struct Plugin *plugin;
78
79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
80 "Loading credential plugin `%s'\n",
81 library_name);
82 plugin = GNUNET_new (struct Plugin);
83 plugin->api = api;
84 plugin->library_name = GNUNET_strdup (library_name);
85 GNUNET_array_append (credential_plugins, num_plugins, plugin);
86}
87
88
89/**
90 * Load plugins
91 */
92static void
93init ()
94{
95 if (GNUNET_YES == initialized)
96 return;
97 initialized = GNUNET_YES;
98 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
99 "libgnunet_plugin_reclaim_credential_",
100 NULL,
101 &add_plugin,
102 NULL);
103}
104
105
106/**
107 * Dual function to #init().
108 */
109void __attribute__ ((destructor))
110RECLAIM_CREDENTIAL_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 = credential_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 (credential_plugins);
129
130 if (pd != dpd)
131 GNUNET_OS_init (pd);
132
133 credential_plugins = NULL;
134}
135
136
137/**
138 * Convert an credential type name to the corresponding number
139 *
140 * @param typename name to convert
141 * @return corresponding number, UINT32_MAX on error
142 */
143uint32_t
144GNUNET_RECLAIM_credential_typename_to_number (const char *typename)
145{
146 unsigned int i;
147 struct Plugin *plugin;
148 uint32_t ret;
149 init ();
150 for (i = 0; i < num_plugins; i++)
151 {
152 plugin = credential_plugins[i];
153 if (UINT32_MAX !=
154 (ret = plugin->api->typename_to_number (plugin->api->cls,
155 typename)))
156 return ret;
157 }
158 return UINT32_MAX;
159}
160
161
162/**
163 * Convert an credential type number to the corresponding credential type string
164 *
165 * @param type number of a type
166 * @return corresponding typestring, NULL on error
167 */
168const char *
169GNUNET_RECLAIM_credential_number_to_typename (uint32_t type)
170{
171 unsigned int i;
172 struct Plugin *plugin;
173 const char *ret;
174
175 init ();
176 for (i = 0; i < num_plugins; i++)
177 {
178 plugin = credential_plugins[i];
179 if (NULL !=
180 (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
181 return ret;
182 }
183 return NULL;
184}
185
186
187/**
188 * Convert human-readable version of a 'claim' of an credential to the binary
189 * representation
190 *
191 * @param type type of the claim
192 * @param s human-readable string
193 * @param data set to value in binary encoding (will be allocated)
194 * @param data_size set to number of bytes in @a data
195 * @return #GNUNET_OK on success
196 */
197int
198GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
199 const char *s,
200 void **data,
201 size_t *data_size)
202{
203 unsigned int i;
204 struct Plugin *plugin;
205
206 init ();
207 for (i = 0; i < num_plugins; i++)
208 {
209 plugin = credential_plugins[i];
210 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
211 type,
212 s,
213 data,
214 data_size))
215 return GNUNET_OK;
216 }
217 return GNUNET_SYSERR;
218}
219
220
221/**
222 * Convert the 'claim' of an credential to a string
223 *
224 * @param type the type of credential
225 * @param data claim in binary encoding
226 * @param data_size number of bytes in @a data
227 * @return NULL on error, otherwise human-readable representation of the claim
228 */
229char *
230GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
231 const void *data,
232 size_t data_size)
233{
234 unsigned int i;
235 struct Plugin *plugin;
236 char *ret;
237
238 init ();
239 for (i = 0; i < num_plugins; i++)
240 {
241 plugin = credential_plugins[i];
242 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
243 type,
244 data,
245 data_size)))
246 return ret;
247 }
248 return NULL;
249}
250
251
252struct GNUNET_RECLAIM_Credential *
253GNUNET_RECLAIM_credential_new (const char *attr_name,
254 uint32_t type,
255 const void *data,
256 size_t data_size)
257{
258 struct GNUNET_RECLAIM_Credential *attr;
259 char *write_ptr;
260 char *attr_name_tmp = GNUNET_strdup (attr_name);
261
262 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
263
264 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
265 + strlen (attr_name_tmp) + 1 + data_size);
266 attr->type = type;
267 attr->data_size = data_size;
268 attr->flag = 0;
269 write_ptr = (char *) &attr[1];
270 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
271 attr->name = write_ptr;
272 write_ptr += strlen (attr->name) + 1;
273 GNUNET_memcpy (write_ptr, data, data_size);
274 attr->data = write_ptr;
275 GNUNET_free (attr_name_tmp);
276 return attr;
277}
278
279
280/**
281 * Get required size for serialization buffer
282 *
283 * @param attrs the attribute list to serialize
284 * @return the required buffer size
285 */
286size_t
287GNUNET_RECLAIM_credential_list_serialize_get_size (
288 const struct GNUNET_RECLAIM_CredentialList *credentials)
289{
290 struct GNUNET_RECLAIM_CredentialListEntry *le;
291 size_t len = 0;
292
293 for (le = credentials->list_head; NULL != le; le = le->next)
294 {
295 GNUNET_assert (NULL != le->credential);
296 len += GNUNET_RECLAIM_credential_serialize_get_size (le->credential);
297 len += sizeof(struct GNUNET_RECLAIM_CredentialListEntry);
298 }
299 return len;
300}
301
302
303size_t
304GNUNET_RECLAIM_credential_list_serialize (
305 const struct GNUNET_RECLAIM_CredentialList *credentials,
306 char *result)
307{
308 struct GNUNET_RECLAIM_CredentialListEntry *le;
309 size_t len;
310 size_t total_len;
311 char *write_ptr;
312 write_ptr = result;
313 total_len = 0;
314 for (le = credentials->list_head; NULL != le; le = le->next)
315 {
316 GNUNET_assert (NULL != le->credential);
317 len = GNUNET_RECLAIM_credential_serialize (le->credential, write_ptr);
318 total_len += len;
319 write_ptr += len;
320 }
321 return total_len;
322}
323
324
325struct GNUNET_RECLAIM_CredentialList *
326GNUNET_RECLAIM_credential_list_deserialize (const char *data, size_t data_size)
327{
328 struct GNUNET_RECLAIM_CredentialList *al;
329 struct GNUNET_RECLAIM_CredentialListEntry *ale;
330 size_t att_len;
331 const char *read_ptr;
332
333 al = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
334
335 if ((data_size < sizeof(struct
336 Credential)
337 + sizeof(struct GNUNET_RECLAIM_CredentialListEntry)))
338 return al;
339
340 read_ptr = data;
341 while (((data + data_size) - read_ptr) >= sizeof(struct Credential))
342 {
343 ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
344 ale->credential =
345 GNUNET_RECLAIM_credential_deserialize (read_ptr,
346 data_size - (read_ptr - data));
347 if (NULL == ale->credential)
348 {
349 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
350 "Failed to deserialize malformed credential.\n");
351 GNUNET_free (ale);
352 return al;
353 }
354 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
355 att_len = GNUNET_RECLAIM_credential_serialize_get_size (ale->credential);
356 read_ptr += att_len;
357 }
358 return al;
359}
360
361
362/**
363 * Make a (deep) copy of the credential list
364 * @param attrs claim list to copy
365 * @return copied claim list
366 */
367struct GNUNET_RECLAIM_CredentialList *
368GNUNET_RECLAIM_credential_list_dup (
369 const struct GNUNET_RECLAIM_CredentialList *al)
370{
371 struct GNUNET_RECLAIM_CredentialListEntry *ale;
372 struct GNUNET_RECLAIM_CredentialListEntry *result_ale;
373 struct GNUNET_RECLAIM_CredentialList *result;
374
375 result = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
376 for (ale = al->list_head; NULL != ale; ale = ale->next)
377 {
378 result_ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
379 GNUNET_assert (NULL != ale->credential);
380 result_ale->credential =
381 GNUNET_RECLAIM_credential_new (ale->credential->name,
382 ale->credential->type,
383 ale->credential->data,
384 ale->credential->data_size);
385 result_ale->credential->id = ale->credential->id;
386 GNUNET_CONTAINER_DLL_insert (result->list_head,
387 result->list_tail,
388 result_ale);
389 }
390 return result;
391}
392
393
394void
395GNUNET_RECLAIM_credential_list_destroy (
396 struct GNUNET_RECLAIM_CredentialList *credentials)
397{
398 struct GNUNET_RECLAIM_CredentialListEntry *ale;
399 struct GNUNET_RECLAIM_CredentialListEntry *tmp_ale;
400
401 for (ale = credentials->list_head; NULL != ale;)
402 {
403 if (NULL != ale->credential)
404 GNUNET_free (ale->credential);
405 tmp_ale = ale;
406 ale = ale->next;
407 GNUNET_free (tmp_ale);
408 }
409 GNUNET_free (credentials);
410}
411
412
413/**
414 * Get required size for serialization buffer
415 *
416 * @param attr the credential to serialize
417 * @return the required buffer size
418 */
419size_t
420GNUNET_RECLAIM_credential_serialize_get_size (
421 const struct GNUNET_RECLAIM_Credential *credential)
422{
423 return sizeof(struct Credential) + strlen (credential->name)
424 + credential->data_size;
425}
426
427
428size_t
429GNUNET_RECLAIM_credential_serialize (
430 const struct GNUNET_RECLAIM_Credential *credential,
431 char *result)
432{
433 size_t data_len_ser;
434 size_t name_len;
435 struct Credential *atts;
436 char *write_ptr;
437
438 atts = (struct Credential *) result;
439 atts->credential_type = htonl (credential->type);
440 atts->credential_flag = htonl (credential->flag);
441 atts->credential_id = credential->id;
442 name_len = strlen (credential->name);
443 atts->name_len = htons (name_len);
444 write_ptr = (char *) &atts[1];
445 GNUNET_memcpy (write_ptr, credential->name, name_len);
446 write_ptr += name_len;
447 // TODO plugin-ize
448 // data_len_ser = plugin->serialize_attribute_value (attr,
449 // &attr_ser[1]);
450 data_len_ser = credential->data_size;
451 GNUNET_memcpy (write_ptr, credential->data, credential->data_size);
452 atts->data_size = htons (data_len_ser);
453
454 return sizeof(struct Credential) + strlen (credential->name)
455 + credential->data_size;
456}
457
458
459/**
460 * Deserialize an credential
461 *
462 * @param data the serialized credential
463 * @param data_size the length of the serialized data
464 *
465 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
466 */
467struct GNUNET_RECLAIM_Credential *
468GNUNET_RECLAIM_credential_deserialize (const char *data, size_t data_size)
469{
470 struct GNUNET_RECLAIM_Credential *credential;
471 struct Credential *atts;
472 size_t data_len;
473 size_t name_len;
474 char *write_ptr;
475
476 if (data_size < sizeof(struct Credential))
477 return NULL;
478
479 atts = (struct Credential *) data;
480 data_len = ntohs (atts->data_size);
481 name_len = ntohs (atts->name_len);
482 if (data_size < sizeof(struct Credential) + data_len + name_len)
483 {
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
485 "Buffer too small to deserialize\n");
486 return NULL;
487 }
488 credential = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
489 + data_len + name_len + 1);
490 credential->type = ntohl (atts->credential_type);
491 credential->flag = ntohl (atts->credential_flag);
492 credential->id = atts->credential_id;
493 credential->data_size = data_len;
494
495 write_ptr = (char *) &credential[1];
496 GNUNET_memcpy (write_ptr, &atts[1], name_len);
497 write_ptr[name_len] = '\0';
498 credential->name = write_ptr;
499
500 write_ptr += name_len + 1;
501 GNUNET_memcpy (write_ptr, (char *) &atts[1] + name_len,
502 credential->data_size);
503 credential->data = write_ptr;
504 return credential;
505}
506
507
508struct GNUNET_RECLAIM_AttributeList*
509GNUNET_RECLAIM_credential_get_attributes (const struct
510 GNUNET_RECLAIM_Credential *credential)
511{
512 unsigned int i;
513 struct Plugin *plugin;
514 struct GNUNET_RECLAIM_AttributeList *ret;
515 init ();
516 for (i = 0; i < num_plugins; i++)
517 {
518 plugin = credential_plugins[i];
519 if (NULL !=
520 (ret = plugin->api->get_attributes (plugin->api->cls,
521 credential)))
522 return ret;
523 }
524 return NULL;
525}
526
527
528char*
529GNUNET_RECLAIM_credential_get_issuer (const struct
530 GNUNET_RECLAIM_Credential *credential)
531{
532 unsigned int i;
533 struct Plugin *plugin;
534 char *ret;
535 init ();
536 for (i = 0; i < num_plugins; i++)
537 {
538 plugin = credential_plugins[i];
539 if (NULL !=
540 (ret = plugin->api->get_issuer (plugin->api->cls,
541 credential)))
542 return ret;
543 }
544 return NULL;
545}
546
547
548int
549GNUNET_RECLAIM_credential_get_expiration (const struct
550 GNUNET_RECLAIM_Credential *credential,
551 struct GNUNET_TIME_Absolute*exp)
552{
553 unsigned int i;
554 struct Plugin *plugin;
555 init ();
556 for (i = 0; i < num_plugins; i++)
557 {
558 plugin = credential_plugins[i];
559 if (GNUNET_OK != plugin->api->get_expiration (plugin->api->cls,
560 credential,
561 exp))
562 continue;
563 return GNUNET_OK;
564 }
565 return GNUNET_SYSERR;
566}
567
568
569/**
570 * Convert an presentation type name to the corresponding number
571 *
572 * @param typename name to convert
573 * @return corresponding number, UINT32_MAX on error
574 */
575uint32_t
576GNUNET_RECLAIM_presentation_typename_to_number (const char *typename)
577{
578 unsigned int i;
579 struct Plugin *plugin;
580 uint32_t ret;
581 init ();
582 for (i = 0; i < num_plugins; i++)
583 {
584 plugin = credential_plugins[i];
585 if (UINT32_MAX !=
586 (ret = plugin->api->typename_to_number_p (plugin->api->cls,
587 typename)))
588 return ret;
589 }
590 return UINT32_MAX;
591}
592
593
594const char *
595GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type)
596{
597 unsigned int i;
598 struct Plugin *plugin;
599 const char *ret;
600
601 init ();
602 for (i = 0; i < num_plugins; i++)
603 {
604 plugin = credential_plugins[i];
605 if (NULL !=
606 (ret = plugin->api->number_to_typename_p (plugin->api->cls, type)))
607 return ret;
608 }
609 return NULL;
610}
611
612
613/**
614 * Convert human-readable version of a 'claim' of an presentation to the binary
615 * representation
616 *
617 * @param type type of the claim
618 * @param s human-readable string
619 * @param data set to value in binary encoding (will be allocated)
620 * @param data_size set to number of bytes in @a data
621 * @return #GNUNET_OK on success
622 */
623int
624GNUNET_RECLAIM_presentation_string_to_value (uint32_t type,
625 const char *s,
626 void **data,
627 size_t *data_size)
628{
629 unsigned int i;
630 struct Plugin *plugin;
631
632 init ();
633 for (i = 0; i < num_plugins; i++)
634 {
635 plugin = credential_plugins[i];
636 if (GNUNET_OK == plugin->api->string_to_value_p (plugin->api->cls,
637 type,
638 s,
639 data,
640 data_size))
641 return GNUNET_OK;
642 }
643 return GNUNET_SYSERR;
644}
645
646
647/**
648 * Convert the 'claim' of an presentation to a string
649 *
650 * @param type the type of presentation
651 * @param data claim in binary encoding
652 * @param data_size number of bytes in @a data
653 * @return NULL on error, otherwise human-readable representation of the claim
654 */
655char *
656GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
657 const void *data,
658 size_t data_size)
659{
660 unsigned int i;
661 struct Plugin *plugin;
662 char *ret;
663
664 init ();
665 for (i = 0; i < num_plugins; i++)
666 {
667 plugin = credential_plugins[i];
668 if (NULL != (ret = plugin->api->value_to_string_p (plugin->api->cls,
669 type,
670 data,
671 data_size)))
672 return ret;
673 }
674 return NULL;
675}
676
677
678struct GNUNET_RECLAIM_Presentation *
679GNUNET_RECLAIM_presentation_new (uint32_t type,
680 const void *data,
681 size_t data_size)
682{
683 struct GNUNET_RECLAIM_Presentation *attr;
684 char *write_ptr;
685
686 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
687 + data_size);
688 attr->type = type;
689 attr->data_size = data_size;
690 write_ptr = (char *) &attr[1];
691 GNUNET_memcpy (write_ptr, data, data_size);
692 attr->data = write_ptr;
693 return attr;
694}
695
696
697/**
698 * Get required size for serialization buffer
699 *
700 * @param attrs the attribute list to serialize
701 * @return the required buffer size
702 */
703size_t
704GNUNET_RECLAIM_presentation_list_serialize_get_size (
705 const struct GNUNET_RECLAIM_PresentationList *presentations)
706{
707 struct GNUNET_RECLAIM_PresentationListEntry *le;
708 size_t len = 0;
709
710 for (le = presentations->list_head; NULL != le; le = le->next)
711 {
712 GNUNET_assert (NULL != le->presentation);
713 len += GNUNET_RECLAIM_presentation_serialize_get_size (le->presentation);
714 }
715 return len;
716}
717
718
719size_t
720GNUNET_RECLAIM_presentation_list_serialize (
721 const struct GNUNET_RECLAIM_PresentationList *presentations,
722 char *result)
723{
724 struct GNUNET_RECLAIM_PresentationListEntry *le;
725 size_t len;
726 size_t total_len;
727 char *write_ptr;
728 write_ptr = result;
729 total_len = 0;
730 for (le = presentations->list_head; NULL != le; le = le->next)
731 {
732 GNUNET_assert (NULL != le->presentation);
733 len = GNUNET_RECLAIM_presentation_serialize (le->presentation, write_ptr);
734 total_len += len;
735 write_ptr += len;
736 }
737 return total_len;
738}
739
740
741/**
742 * Deserialize an presentation list
743 *
744 * @param data the serialized attribute list
745 * @param data_size the length of the serialized data
746 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
747 */
748struct GNUNET_RECLAIM_PresentationList *
749GNUNET_RECLAIM_presentation_list_deserialize (const char *data, size_t
750 data_size)
751{
752 struct GNUNET_RECLAIM_PresentationList *al;
753 struct GNUNET_RECLAIM_PresentationListEntry *ale;
754 size_t att_len;
755 const char *read_ptr;
756
757 al = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
758
759 if (data_size < sizeof(struct Presentation))
760 return al;
761
762 read_ptr = data;
763 while (((data + data_size) - read_ptr) >= sizeof(struct Presentation))
764 {
765 ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
766 ale->presentation =
767 GNUNET_RECLAIM_presentation_deserialize (read_ptr,
768 data_size - (read_ptr - data));
769 if (NULL == ale->presentation)
770 {
771 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
772 "Failed to deserialize malformed presentation.\n");
773 GNUNET_free (ale);
774 return al;
775 }
776 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
777 att_len = GNUNET_RECLAIM_presentation_serialize_get_size (
778 ale->presentation);
779 read_ptr += att_len;
780 }
781 return al;
782}
783
784
785/**
786 * Make a (deep) copy of the presentation list
787 * @param attrs claim list to copy
788 * @return copied claim list
789 */
790struct GNUNET_RECLAIM_PresentationList *
791GNUNET_RECLAIM_presentation_list_dup (
792 const struct GNUNET_RECLAIM_PresentationList *al)
793{
794 struct GNUNET_RECLAIM_PresentationListEntry *ale;
795 struct GNUNET_RECLAIM_PresentationListEntry *result_ale;
796 struct GNUNET_RECLAIM_PresentationList *result;
797
798 result = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
799 for (ale = al->list_head; NULL != ale; ale = ale->next)
800 {
801 result_ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
802 GNUNET_assert (NULL != ale->presentation);
803 result_ale->presentation =
804 GNUNET_RECLAIM_presentation_new (ale->presentation->type,
805 ale->presentation->data,
806 ale->presentation->data_size);
807 result_ale->presentation->credential_id = ale->presentation->credential_id;
808 GNUNET_CONTAINER_DLL_insert (result->list_head,
809 result->list_tail,
810 result_ale);
811 }
812 return result;
813}
814
815
816void
817GNUNET_RECLAIM_presentation_list_destroy (
818 struct GNUNET_RECLAIM_PresentationList *presentations)
819{
820 struct GNUNET_RECLAIM_PresentationListEntry *ale;
821 struct GNUNET_RECLAIM_PresentationListEntry *tmp_ale;
822
823 for (ale = presentations->list_head; NULL != ale;)
824 {
825 if (NULL != ale->presentation)
826 GNUNET_free (ale->presentation);
827 tmp_ale = ale;
828 ale = ale->next;
829 GNUNET_free (tmp_ale);
830 }
831 GNUNET_free (presentations);
832}
833
834
835/**
836 * Get required size for serialization buffer
837 *
838 * @param attr the presentation to serialize
839 * @return the required buffer size
840 */
841size_t
842GNUNET_RECLAIM_presentation_serialize_get_size (
843 const struct GNUNET_RECLAIM_Presentation *presentation)
844{
845 return sizeof(struct Presentation) + presentation->data_size;
846}
847
848
849size_t
850GNUNET_RECLAIM_presentation_serialize (
851 const struct GNUNET_RECLAIM_Presentation *presentation,
852 char *result)
853{
854 struct Presentation *atts;
855 char *write_ptr;
856
857 atts = (struct Presentation *) result;
858 atts->presentation_type = htonl (presentation->type);
859 atts->credential_id = presentation->credential_id;
860 write_ptr = (char *) &atts[1];
861 GNUNET_memcpy (write_ptr, presentation->data, presentation->data_size);
862 atts->data_size = htons (presentation->data_size);
863
864 return sizeof(struct Presentation) + presentation->data_size;
865}
866
867
868/**
869 * Deserialize an presentation
870 *
871 * @param data the serialized presentation
872 * @param data_size the length of the serialized data
873 *
874 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
875 */
876struct GNUNET_RECLAIM_Presentation *
877GNUNET_RECLAIM_presentation_deserialize (const char *data, size_t data_size)
878{
879 struct GNUNET_RECLAIM_Presentation *presentation;
880 struct Presentation *atts;
881 size_t data_len;
882 char *write_ptr;
883
884 if (data_size < sizeof(struct Presentation))
885 return NULL;
886
887 atts = (struct Presentation *) data;
888 data_len = ntohs (atts->data_size);
889 if (data_size < sizeof(struct Presentation) + data_len)
890 {
891 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
892 "Buffer too small to deserialize\n");
893 return NULL;
894 }
895 presentation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
896 + data_len);
897 presentation->type = ntohl (atts->presentation_type);
898 presentation->credential_id = atts->credential_id;
899 presentation->data_size = data_len;
900
901 write_ptr = (char *) &presentation[1];
902 GNUNET_memcpy (write_ptr, &atts[1], data_len);
903 presentation->data = write_ptr;
904 return presentation;
905}
906
907
908struct GNUNET_RECLAIM_AttributeList*
909GNUNET_RECLAIM_presentation_get_attributes (const struct
910 GNUNET_RECLAIM_Presentation *
911 presentation)
912{
913 unsigned int i;
914 struct Plugin *plugin;
915 struct GNUNET_RECLAIM_AttributeList *ret;
916 init ();
917 for (i = 0; i < num_plugins; i++)
918 {
919 plugin = credential_plugins[i];
920 if (NULL !=
921 (ret = plugin->api->get_attributes_p (plugin->api->cls,
922 presentation)))
923 return ret;
924 }
925 return NULL;
926}
927
928
929char*
930GNUNET_RECLAIM_presentation_get_issuer (const struct
931 GNUNET_RECLAIM_Presentation *
932 presentation)
933{
934 unsigned int i;
935 struct Plugin *plugin;
936 char *ret;
937 init ();
938 for (i = 0; i < num_plugins; i++)
939 {
940 plugin = credential_plugins[i];
941 if (NULL !=
942 (ret = plugin->api->get_issuer_p (plugin->api->cls,
943 presentation)))
944 return ret;
945 }
946 return NULL;
947}
948
949
950int
951GNUNET_RECLAIM_presentation_get_expiration (const struct
952 GNUNET_RECLAIM_Presentation *
953 presentation,
954 struct GNUNET_TIME_Absolute*exp)
955{
956 unsigned int i;
957 struct Plugin *plugin;
958 init ();
959 for (i = 0; i < num_plugins; i++)
960 {
961 plugin = credential_plugins[i];
962 if (GNUNET_OK != plugin->api->get_expiration_p (plugin->api->cls,
963 presentation,
964 exp))
965 continue;
966 return GNUNET_OK;
967 }
968 return GNUNET_SYSERR;
969}
970
971
972/**
973 * Create a presentation from a credential and a lift of (selected)
974 * attributes in the credential.
975 *
976 * @param cred the credential to use
977 * @param attrs the attributes to present from the credential
978 * @return the credential presentation presenting the attributes according
979 * to the presentation mechanism of the credential
980 * or NULL on error.
981 */
982int
983GNUNET_RECLAIM_credential_get_presentation (
984 const struct GNUNET_RECLAIM_Credential *cred,
985 const struct GNUNET_RECLAIM_AttributeList *attrs,
986 struct GNUNET_RECLAIM_Presentation **presentation)
987{
988 unsigned int i;
989 struct Plugin *plugin;
990 init ();
991 for (i = 0; i < num_plugins; i++)
992 {
993 plugin = credential_plugins[i];
994 if (GNUNET_OK != plugin->api->create_presentation (plugin->api->cls,
995 cred,
996 attrs,
997 presentation))
998 continue;
999 (*presentation)->credential_id = cred->id;
1000 return GNUNET_OK;
1001 }
1002 return GNUNET_SYSERR;
1003}
diff --git a/src/service/reclaim/reclaim_credential.h b/src/service/reclaim/reclaim_credential.h
new file mode 100644
index 000000000..ffec15445
--- /dev/null
+++ b/src/service/reclaim/reclaim_credential.h
@@ -0,0 +1,119 @@
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/service/reclaim/test_did_helper.c b/src/service/reclaim/test_did_helper.c
new file mode 100644
index 000000000..c11f47540
--- /dev/null
+++ b/src/service/reclaim/test_did_helper.c
@@ -0,0 +1,137 @@
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/service/reclaim/test_reclaim_attribute.c b/src/service/reclaim/test_reclaim_attribute.c
new file mode 100644
index 000000000..acbcda62d
--- /dev/null
+++ b/src/service/reclaim/test_reclaim_attribute.c
@@ -0,0 +1,49 @@
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/service/reclaim/test_w3c_ed25519_2020.c b/src/service/reclaim/test_w3c_ed25519_2020.c
new file mode 100644
index 000000000..e2534e6ab
--- /dev/null
+++ b/src/service/reclaim/test_w3c_ed25519_2020.c
@@ -0,0 +1,69 @@
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}