aboutsummaryrefslogtreecommitdiff
path: root/src/plugin/reclaim
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugin/reclaim')
-rw-r--r--src/plugin/reclaim/Makefile.am70
-rw-r--r--src/plugin/reclaim/meson.build28
-rw-r--r--src/plugin/reclaim/pabc_helper.c374
-rw-r--r--src/plugin/reclaim/pabc_helper.h41
-rw-r--r--src/plugin/reclaim/plugin_gnsrecord_reclaim.c195
-rw-r--r--src/plugin/reclaim/plugin_reclaim_attribute_basic.c181
-rw-r--r--src/plugin/reclaim/plugin_reclaim_credential_jwt.c512
-rw-r--r--src/plugin/reclaim/plugin_reclaim_credential_pabc.c572
8 files changed, 1973 insertions, 0 deletions
diff --git a/src/plugin/reclaim/Makefile.am b/src/plugin/reclaim/Makefile.am
new file mode 100644
index 000000000..e8ac2f94d
--- /dev/null
+++ b/src/plugin/reclaim/Makefile.am
@@ -0,0 +1,70 @@
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
12CREDENTIAL_PLUGIN = \
13 libgnunet_plugin_reclaim_credential_jwt.la
14
15if HAVE_PABC
16 CREDENTIAL_PLUGIN += libgnunet_plugin_reclaim_credential_pabc.la
17endif
18
19plugin_LTLIBRARIES = \
20 libgnunet_plugin_gnsrecord_reclaim.la \
21 libgnunet_plugin_reclaim_attribute_basic.la \
22 $(CREDENTIAL_PLUGIN)
23
24pkgcfgdir= $(pkgdatadir)/config.d/
25
26libexecdir= $(pkglibdir)/libexec/
27
28libgnunet_plugin_gnsrecord_reclaim_la_SOURCES = \
29 plugin_gnsrecord_reclaim.c
30libgnunet_plugin_gnsrecord_reclaim_la_LIBADD = \
31 $(top_builddir)/src/lib/util/libgnunetutil.la \
32 $(LTLIBINTL)
33libgnunet_plugin_gnsrecord_reclaim_la_LDFLAGS = \
34 $(GN_PLUGIN_LDFLAGS)
35
36
37libgnunet_plugin_reclaim_attribute_basic_la_SOURCES = \
38 plugin_reclaim_attribute_basic.c
39libgnunet_plugin_reclaim_attribute_basic_la_LIBADD = \
40 $(top_builddir)/src/lib/util/libgnunetutil.la \
41 $(LTLIBINTL)
42libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \
43 $(GN_PLUGIN_LDFLAGS)
44
45if HAVE_PABC
46libgnunet_plugin_reclaim_credential_pabc_la_SOURCES = \
47 plugin_reclaim_credential_pabc.c \
48 pabc_helper.c \
49 pabc_helper.h
50libgnunet_plugin_reclaim_credential_pabc_la_LIBADD = \
51 $(top_builddir)/src/lib/util/libgnunetutil.la \
52 $(top_builddir)/src/service/reclaim/libgnunetreclaim.la \
53 -ljansson\
54 -lpabc \
55 $(LTLIBINTL)
56libgnunet_plugin_reclaim_credential_pabc_la_LDFLAGS = \
57 $(GN_PLUGIN_LDFLAGS)
58endif
59
60
61libgnunet_plugin_reclaim_credential_jwt_la_SOURCES = \
62 plugin_reclaim_credential_jwt.c \
63 $(top_builddir)/src/service/reclaim/reclaim_attribute.c \
64 $(top_builddir)/src/service/reclaim/reclaim_credential.c
65libgnunet_plugin_reclaim_credential_jwt_la_LIBADD = \
66 $(top_builddir)/src/lib/util/libgnunetutil.la \
67 -ljansson\
68 $(LTLIBINTL)
69libgnunet_plugin_reclaim_credential_jwt_la_LDFLAGS = \
70 $(GN_PLUGIN_LDFLAGS)
diff --git a/src/plugin/reclaim/meson.build b/src/plugin/reclaim/meson.build
new file mode 100644
index 000000000..cde9fc726
--- /dev/null
+++ b/src/plugin/reclaim/meson.build
@@ -0,0 +1,28 @@
1shared_module('gnunet_plugin_gnsrecord_reclaim',
2 ['plugin_gnsrecord_reclaim.c'],
3 dependencies: [libgnunetutil_dep, libgnunetgnsrecord_dep],
4 include_directories: [incdir, configuration_inc],
5 install: true,
6 install_dir: get_option('libdir')/'gnunet')
7
8shared_module('gnunet_plugin_reclaim_attribute_basic',
9 ['plugin_reclaim_attribute_basic.c'],
10 dependencies: [
11 libgnunetjson_dep,
12 libgnunetutil_dep,
13 json_dep],
14 include_directories: [incdir, configuration_inc],
15 install: true,
16 install_dir: get_option('libdir') / 'gnunet')
17shared_module('gnunet_plugin_reclaim_credential_jwt',
18 ['plugin_reclaim_credential_jwt.c',
19 '../../service/reclaim/reclaim_attribute.c',
20 '../../service/reclaim/reclaim_credential.c'],
21 dependencies: [
22 libgnunetjson_dep,
23 libgnunetutil_dep,
24 json_dep],
25 include_directories: [incdir, configuration_inc],
26 install: true,
27 install_dir: get_option('libdir') / 'gnunet')
28
diff --git a/src/plugin/reclaim/pabc_helper.c b/src/plugin/reclaim/pabc_helper.c
new file mode 100644
index 000000000..d7688e9e1
--- /dev/null
+++ b/src/plugin/reclaim/pabc_helper.c
@@ -0,0 +1,374 @@
1// maximilian.kaul@aisec.fraunhofer.de
2
3// WIP implementation of
4// https://github.com/ontio/ontology-crypto/wiki/Anonymous-Credential
5// using the relic library https://github.com/relic-toolkit/relic/
6
7#include "platform.h"
8#include "pabc_helper.h"
9#include <pwd.h>
10#include <stdlib.h>
11#include <unistd.h>
12
13static char pabc_dir[PATH_MAX + 1];
14
15static const char *
16get_homedir ()
17{
18 const char *homedir;
19 if ((homedir = getenv ("HOME")) == NULL)
20 {
21 homedir = getpwuid (getuid ())->pw_dir;
22 }
23 return homedir;
24}
25
26
27static enum GNUNET_GenericReturnValue
28write_file (char const *const filename, const char *buffer)
29{
30 struct GNUNET_DISK_FileHandle *fh;
31 fh = GNUNET_DISK_file_open (filename,
32 GNUNET_DISK_OPEN_WRITE
33 | GNUNET_DISK_OPEN_TRUNCATE
34 | GNUNET_DISK_OPEN_CREATE,
35 GNUNET_DISK_PERM_USER_WRITE
36 | GNUNET_DISK_PERM_USER_READ);
37 if (fh == NULL)
38 return GNUNET_SYSERR;
39 if (GNUNET_SYSERR == GNUNET_DISK_file_write (fh,
40 buffer, strlen (buffer) + 1))
41 goto fail;
42 GNUNET_DISK_file_close (fh);
43 return GNUNET_OK;
44
45fail:
46 GNUNET_DISK_file_close (fh);
47 return GNUNET_SYSERR;
48}
49
50
51static enum GNUNET_GenericReturnValue
52init_pabc_dir ()
53{
54 size_t filename_size = strlen (get_homedir ()) + 1 + strlen (".local") + 1
55 + strlen ("pabc-reclaim") + 1;
56 snprintf (pabc_dir, filename_size, "%s/%s/%s",
57 get_homedir (), ".local", "pabc-reclaim");
58 return GNUNET_DISK_directory_create (pabc_dir);
59}
60
61
62static const char *
63get_pabcdir ()
64{
65 init_pabc_dir ();
66 return pabc_dir;
67}
68
69
70enum GNUNET_GenericReturnValue
71read_file (char const *const filename, char **buffer)
72{
73 struct GNUNET_DISK_FileHandle *fh;
74 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
75 return GNUNET_SYSERR;
76
77 fh = GNUNET_DISK_file_open (filename,
78 GNUNET_DISK_OPEN_READ,
79 GNUNET_DISK_PERM_USER_READ);
80 if (fh == NULL)
81 return GNUNET_SYSERR;
82 long lSize = GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_END);
83 if (lSize < 0)
84 goto fail;
85 GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_SET);
86 *buffer = calloc ((size_t) lSize + 1, sizeof(char));
87 if (*buffer == NULL)
88 goto fail;
89
90 // copy the file into the buffer:
91 size_t r = GNUNET_DISK_file_read (fh, *buffer, (size_t) lSize);
92 if (r != (size_t) lSize)
93 goto fail;
94
95 GNUNET_DISK_file_close (fh);
96 return GNUNET_OK;
97
98fail:
99 GNUNET_DISK_file_close (fh);
100 GNUNET_free (*buffer);
101 return GNUNET_SYSERR;
102}
103
104
105struct pabc_public_parameters *
106PABC_read_issuer_ppfile (const char *f, struct pabc_context *const ctx)
107{
108 if (NULL == ctx)
109 {
110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No global context provided\n");
111 return NULL;
112 }
113 struct pabc_public_parameters *pp;
114 char *buffer;
115 int r;
116 r = read_file (f, &buffer);
117 if (GNUNET_OK != r)
118 {
119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading file\n");
120 return NULL;
121 }
122 if (PABC_OK != pabc_decode_and_new_public_parameters (ctx, &pp, buffer))
123 {
124 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
125 "Failed to decode public parameters\n");
126 PABC_FREE_NULL (buffer);
127 return NULL;
128 }
129 PABC_FREE_NULL (buffer);
130 return pp;
131}
132
133
134enum GNUNET_GenericReturnValue
135PABC_load_public_parameters (struct pabc_context *const ctx,
136 char const *const pp_name,
137 struct pabc_public_parameters **pp)
138{
139 char fname[PATH_MAX];
140 char *pp_filename;
141 const char *pdir = get_pabcdir ();
142
143 if (ctx == NULL)
144 return GNUNET_SYSERR;
145 if (pp_name == NULL)
146 return GNUNET_SYSERR;
147
148 GNUNET_STRINGS_urlencode (strlen (pp_name),
149 pp_name,
150 &pp_filename);
151 if (GNUNET_YES != GNUNET_DISK_directory_test (pdir, GNUNET_YES))
152 {
153 GNUNET_free (pp_filename);
154 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading %s\n", pdir);
155 return GNUNET_SYSERR;
156 }
157 snprintf (fname, PATH_MAX, "%s/%s%s", pdir, pp_filename, PABC_PP_EXT);
158 if (GNUNET_YES != GNUNET_DISK_file_test (fname))
159 {
160 GNUNET_free (pp_filename);
161 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error testing %s\n", fname);
162 return GNUNET_SYSERR;
163 }
164 *pp = PABC_read_issuer_ppfile (fname, ctx);
165 if (*pp)
166 return GNUNET_OK;
167 else
168 return GNUNET_SYSERR;
169}
170
171
172enum GNUNET_GenericReturnValue
173PABC_write_public_parameters (char const *const pp_name,
174 struct pabc_public_parameters *const pp)
175{
176 char *json;
177 char *filename;
178 char *pp_filename;
179 enum pabc_status status;
180 struct pabc_context *ctx = NULL;
181
182 GNUNET_STRINGS_urlencode (strlen (pp_name),
183 pp_name,
184 &pp_filename);
185 PABC_ASSERT (pabc_new_ctx (&ctx));
186 // store in json file
187 status = pabc_encode_public_parameters (ctx, pp, &json);
188 if (status != PABC_OK)
189 {
190 GNUNET_free (pp_filename);
191 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
192 "Failed to encode public parameters.\n");
193 pabc_free_ctx (&ctx);
194 return GNUNET_SYSERR;
195 }
196
197 size_t filename_size =
198 strlen (get_pabcdir ()) + 1 + strlen (pp_filename) + strlen (PABC_PP_EXT)
199 + 1;
200 filename = GNUNET_malloc (filename_size);
201 if (! filename)
202 {
203 GNUNET_free (pp_filename);
204 PABC_FREE_NULL (json);
205 pabc_free_ctx (&ctx);
206 return GNUNET_SYSERR;
207 }
208 snprintf (filename, filename_size, "%s/%s%s", get_pabcdir (), pp_filename,
209 PABC_PP_EXT);
210
211 GNUNET_free (pp_filename);
212 if (GNUNET_OK != write_file (filename, json))
213 {
214 PABC_FREE_NULL (filename);
215 PABC_FREE_NULL (json);
216 pabc_free_ctx (&ctx);
217 return GNUNET_SYSERR;
218 }
219 PABC_FREE_NULL (filename);
220 PABC_FREE_NULL (json);
221 pabc_free_ctx (&ctx);
222 return GNUNET_OK;
223}
224
225
226enum GNUNET_GenericReturnValue
227PABC_write_usr_ctx (char const *const usr_name,
228 char const *const pp_name,
229 struct pabc_context const *const ctx,
230 struct pabc_public_parameters const *const pp,
231 struct pabc_user_context *const usr_ctx)
232{
233
234 char *pp_filename;
235 char *json = NULL;
236 enum pabc_status status;
237 char *fname = NULL;
238
239 if (NULL == usr_name)
240 {
241 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n");
242 return GNUNET_SYSERR;
243 }
244 if (NULL == pp_name)
245 {
246 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n");
247 return GNUNET_SYSERR;
248 }
249 if (NULL == ctx)
250 {
251 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n");
252 return GNUNET_SYSERR;
253 }
254 if (NULL == pp)
255 {
256 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n");
257 return GNUNET_SYSERR;
258 }
259 if (NULL == usr_ctx)
260 {
261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n");
262 return GNUNET_SYSERR;
263 }
264
265 GNUNET_STRINGS_urlencode (strlen (pp_name),
266 pp_name,
267 &pp_filename);
268 status = pabc_encode_user_ctx (ctx, pp, usr_ctx, &json);
269 if (PABC_OK != status)
270 {
271 GNUNET_free (pp_filename);
272 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n");
273 return status;
274 }
275
276 size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1
277 + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1;
278 fname = GNUNET_malloc (fname_size);
279
280 snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name,
281 pp_filename,
282 PABC_USR_EXT);
283
284 GNUNET_free (pp_filename);
285 if (GNUNET_OK == write_file (fname, json))
286 {
287 GNUNET_free (fname);
288 GNUNET_free (json);
289 return GNUNET_OK;
290 }
291 else
292 {
293 GNUNET_free (fname);
294 GNUNET_free (json);
295 return GNUNET_SYSERR;
296 }
297}
298
299
300enum GNUNET_GenericReturnValue
301PABC_read_usr_ctx (char const *const usr_name,
302 char const *const pp_name,
303 struct pabc_context const *const ctx,
304 struct pabc_public_parameters const *const pp,
305 struct pabc_user_context **usr_ctx)
306{
307 char *json = NULL;
308 char *pp_filename;
309 enum pabc_status status;
310
311 char *fname = NULL;
312
313 if (NULL == usr_name)
314 {
315 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n");
316 return GNUNET_SYSERR;
317 }
318 if (NULL == pp_name)
319 {
320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n");
321 return GNUNET_SYSERR;
322 }
323 if (NULL == ctx)
324 {
325 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n");
326 return GNUNET_SYSERR;
327 }
328 if (NULL == pp)
329 {
330 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n");
331 return GNUNET_SYSERR;
332 }
333 if (NULL == usr_ctx)
334 {
335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n");
336 return GNUNET_SYSERR;
337 }
338 GNUNET_STRINGS_urlencode (strlen (pp_name),
339 pp_name,
340 &pp_filename);
341
342 size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1
343 + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1;
344 fname = GNUNET_malloc (fname_size);
345 snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name,
346 pp_filename,
347 PABC_USR_EXT);
348 GNUNET_free (pp_filename);
349 if (GNUNET_OK != read_file (fname, &json))
350 {
351 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
352 "Failed to read `%s'\n", fname);
353 PABC_FREE_NULL (fname);
354 return GNUNET_SYSERR;
355 }
356 GNUNET_free (fname);
357
358 status = pabc_new_user_context (ctx, pp, usr_ctx);
359 if (PABC_OK != status)
360 {
361 GNUNET_free (json);
362 return GNUNET_SYSERR;
363 }
364 status = pabc_decode_user_ctx (ctx, pp, *usr_ctx, json);
365 GNUNET_free (json);
366 if (PABC_OK != status)
367 {
368 pabc_free_user_context (ctx, pp, usr_ctx);
369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n");
370 return GNUNET_SYSERR;
371 }
372
373 return GNUNET_OK;
374}
diff --git a/src/plugin/reclaim/pabc_helper.h b/src/plugin/reclaim/pabc_helper.h
new file mode 100644
index 000000000..045ad5dda
--- /dev/null
+++ b/src/plugin/reclaim/pabc_helper.h
@@ -0,0 +1,41 @@
1#include "platform.h"
2#include "gnunet_util_lib.h"
3#include <pabc/pabc.h>
4
5#ifndef PATH_MAX
6#define PATH_MAX 4096
7#endif
8
9#define PABC_ISK_EXT ".isk"
10
11#define PABC_PP_EXT ".pp"
12
13#define PABC_USR_EXT ".usr"
14
15#define PABC_ATTR_DELIM "="
16
17enum GNUNET_GenericReturnValue
18PABC_write_public_parameters (char const *const pp_name,
19 struct pabc_public_parameters *const pp);
20
21
22enum GNUNET_GenericReturnValue
23PABC_load_public_parameters (struct pabc_context *const ctx,
24 char const *const pp_name,
25 struct pabc_public_parameters **pp);
26
27enum GNUNET_GenericReturnValue
28PABC_write_usr_ctx (char const *const user_name,
29 char const *const pp_name,
30 struct pabc_context const *const ctx,
31 struct pabc_public_parameters const *const
32 pp,
33 struct pabc_user_context *const usr_ctx);
34
35enum GNUNET_GenericReturnValue
36PABC_read_usr_ctx (char const *const user_name,
37 char const *const pp_name,
38 struct pabc_context const *const ctx,
39 struct pabc_public_parameters const *const
40 pp,
41 struct pabc_user_context **usr_ctx);
diff --git a/src/plugin/reclaim/plugin_gnsrecord_reclaim.c b/src/plugin/reclaim/plugin_gnsrecord_reclaim.c
new file mode 100644
index 000000000..baf2fc37a
--- /dev/null
+++ b/src/plugin/reclaim/plugin_gnsrecord_reclaim.c
@@ -0,0 +1,195 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/plugin_gnsrecord_reclaim.c
23 * @brief gnsrecord plugin to provide the API for identity records
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27
28#include "gnunet_util_lib.h"
29
30#include "gnunet_gnsrecord_lib.h"
31#include "gnunet_gnsrecord_plugin.h"
32
33/**
34 * Convert the 'value' of a record to a string.
35 *
36 * @param cls closure, unused
37 * @param type type of the record
38 * @param data value in binary encoding
39 * @param data_size number of bytes in @a data
40 * @return NULL on error, otherwise human-readable representation of the value
41 */
42static char *
43value_to_string (void *cls, uint32_t type, const void *data, size_t data_size)
44{
45 switch (type)
46 {
47 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
48 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT:
49 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT:
50 return GNUNET_strndup (data, data_size);
51 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
52 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
53 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
54 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
55 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
56
57 default:
58 return NULL;
59 }
60}
61
62
63/**
64 * Convert human-readable version of a 'value' of a record to the binary
65 * representation.
66 *
67 * @param cls closure, unused
68 * @param type type of the record
69 * @param s human-readable string
70 * @param data set to value in binary encoding (will be allocated)
71 * @param data_size set to number of bytes in @a data
72 * @return #GNUNET_OK on success
73 */
74static int
75string_to_value (void *cls, uint32_t type, const char *s, void **data,
76 size_t *data_size)
77{
78 if (NULL == s)
79 return GNUNET_SYSERR;
80 switch (type)
81 {
82 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
83 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT:
84 case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT:
85 *data = GNUNET_strdup (s);
86 *data_size = strlen (s);
87 return GNUNET_OK;
88 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
89 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
90 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
91 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
92 return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
93
94 default:
95 return GNUNET_SYSERR;
96 }
97}
98
99
100/**
101 * Mapping of record type numbers to human-readable
102 * record type names.
103 */
104static struct
105{
106 const char *name;
107 uint32_t number;
108} name_map[] = {
109 { "RECLAIM_ATTRIBUTE", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE },
110 { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF },
111 { "RECLAIM_CREDENTIAL", GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL },
112 { "RECLAIM_PRESENTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION },
113 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
114 { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT },
115 { "RECLAIM_TICKET", GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET },
116 { NULL, UINT32_MAX }
117};
118
119
120/**
121 * Convert a type name (e.g. "AAAA") to the corresponding number.
122 *
123 * @param cls closure, unused
124 * @param dns_typename name to convert
125 * @return corresponding number, UINT32_MAX on error
126 */
127static uint32_t
128typename_to_number (void *cls, const char *dns_typename)
129{
130 unsigned int i;
131
132 i = 0;
133 while ((NULL != name_map[i].name) &&
134 (0 != strcasecmp (dns_typename, name_map[i].name)))
135 i++;
136 return name_map[i].number;
137}
138
139
140/**
141 * Convert a type number to the corresponding type string (e.g. 1 to "A")
142 *
143 * @param cls closure, unused
144 * @param type number of a type to convert
145 * @return corresponding typestring, NULL on error
146 */
147static const char *
148number_to_typename (void *cls, uint32_t type)
149{
150 unsigned int i;
151
152 i = 0;
153 while ((NULL != name_map[i].name) && (type != name_map[i].number))
154 i++;
155 return name_map[i].name;
156}
157
158
159/**
160 * Entry point for the plugin.
161 *
162 * @param cls NULL
163 * @return the exported block API
164 */
165void *
166libgnunet_plugin_gnsrecord_reclaim_init (void *cls)
167{
168 struct GNUNET_GNSRECORD_PluginFunctions *api;
169
170 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
171 api->value_to_string = &value_to_string;
172 api->string_to_value = &string_to_value;
173 api->typename_to_number = &typename_to_number;
174 api->number_to_typename = &number_to_typename;
175 return api;
176}
177
178
179/**
180 * Exit point from the plugin.
181 *
182 * @param cls the return value from #libgnunet_plugin_block_test_init
183 * @return NULL
184 */
185void *
186libgnunet_plugin_gnsrecord_reclaim_done (void *cls)
187{
188 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
189
190 GNUNET_free (api);
191 return NULL;
192}
193
194
195/* end of plugin_gnsrecord_dns.c */
diff --git a/src/plugin/reclaim/plugin_reclaim_attribute_basic.c b/src/plugin/reclaim/plugin_reclaim_attribute_basic.c
new file mode 100644
index 000000000..66f59998a
--- /dev/null
+++ b/src/plugin/reclaim/plugin_reclaim_attribute_basic.c
@@ -0,0 +1,181 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim-attribute/plugin_reclaim_attribute_gnuid.c
23 * @brief reclaim-attribute-plugin-gnuid attribute plugin to provide the API for
24 * fundamental
25 * attribute types.
26 *
27 * @author Martin Schanzenbach
28 */
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_reclaim_plugin.h"
32#include <inttypes.h>
33
34
35/**
36 * Convert the 'value' of an attribute to a string.
37 *
38 * @param cls closure, unused
39 * @param type type of the attribute
40 * @param data value in binary encoding
41 * @param data_size number of bytes in @a data
42 * @return NULL on error, otherwise human-readable representation of the value
43 */
44static char *
45basic_value_to_string (void *cls,
46 uint32_t type,
47 const void *data,
48 size_t data_size)
49{
50 switch (type)
51 {
52 case GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING:
53 return GNUNET_strndup (data, data_size);
54
55 default:
56 return NULL;
57 }
58}
59
60
61/**
62 * Convert human-readable version of a 'value' of an attribute to the binary
63 * representation.
64 *
65 * @param cls closure, unused
66 * @param type type of the attribute
67 * @param s human-readable string
68 * @param data set to value in binary encoding (will be allocated)
69 * @param data_size set to number of bytes in @a data
70 * @return #GNUNET_OK on success
71 */
72static int
73basic_string_to_value (void *cls,
74 uint32_t type,
75 const char *s,
76 void **data,
77 size_t *data_size)
78{
79 if (NULL == s)
80 return GNUNET_SYSERR;
81 switch (type)
82 {
83 case GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING:
84 *data = GNUNET_strdup (s);
85 *data_size = strlen (s) + 1;
86 return GNUNET_OK;
87
88 default:
89 return GNUNET_SYSERR;
90 }
91}
92
93
94/**
95 * Mapping of attribute type numbers to human-readable
96 * attribute type names.
97 */
98static struct
99{
100 const char *name;
101 uint32_t number;
102} basic_name_map[] = { { "STRING", GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING },
103 { NULL, UINT32_MAX } };
104
105
106/**
107 * Convert a type name to the corresponding number.
108 *
109 * @param cls closure, unused
110 * @param basic_typename name to convert
111 * @return corresponding number, UINT32_MAX on error
112 */
113static uint32_t
114basic_typename_to_number (void *cls, const char *basic_typename)
115{
116 unsigned int i;
117
118 i = 0;
119 while ((NULL != basic_name_map[i].name) &&
120 (0 != strcasecmp (basic_typename, basic_name_map[i].name)))
121 i++;
122 return basic_name_map[i].number;
123}
124
125
126/**
127 * Convert a type number to the corresponding type string (e.g. 1 to "A")
128 *
129 * @param cls closure, unused
130 * @param type number of a type to convert
131 * @return corresponding typestring, NULL on error
132 */
133static const char *
134basic_number_to_typename (void *cls, uint32_t type)
135{
136 unsigned int i;
137
138 i = 0;
139 while ((NULL != basic_name_map[i].name) && (type != basic_name_map[i].number))
140 i++;
141 return basic_name_map[i].name;
142}
143
144
145/**
146 * Entry point for the plugin.
147 *
148 * @param cls NULL
149 * @return the exported block API
150 */
151void *
152libgnunet_plugin_reclaim_attribute_basic_init (void *cls)
153{
154 struct GNUNET_RECLAIM_AttributePluginFunctions *api;
155
156 api = GNUNET_new (struct GNUNET_RECLAIM_AttributePluginFunctions);
157 api->value_to_string = &basic_value_to_string;
158 api->string_to_value = &basic_string_to_value;
159 api->typename_to_number = &basic_typename_to_number;
160 api->number_to_typename = &basic_number_to_typename;
161 return api;
162}
163
164
165/**
166 * Exit point from the plugin.
167 *
168 * @param cls the return value from #libgnunet_plugin_block_test_init()
169 * @return NULL
170 */
171void *
172libgnunet_plugin_reclaim_attribute_basic_done (void *cls)
173{
174 struct GNUNET_RECLAIM_AttributePluginFunctions *api = cls;
175
176 GNUNET_free (api);
177 return NULL;
178}
179
180
181/* end of plugin_reclaim_attribute_type_gnuid.c */
diff --git a/src/plugin/reclaim/plugin_reclaim_credential_jwt.c b/src/plugin/reclaim/plugin_reclaim_credential_jwt.c
new file mode 100644
index 000000000..3eb4bfebf
--- /dev/null
+++ b/src/plugin/reclaim/plugin_reclaim_credential_jwt.c
@@ -0,0 +1,512 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/plugin_reclaim_credential_jwt.c
23 * @brief reclaim-credential-plugin-jwt attribute plugin to provide the API for
24 * JWT credentials.
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_reclaim_plugin.h"
31#include <inttypes.h>
32#include <jansson.h>
33
34/**
35 * Convert the 'value' of an credential to a string.
36 *
37 * @param cls closure, unused
38 * @param type type of the credential
39 * @param data value in binary encoding
40 * @param data_size number of bytes in @a data
41 * @return NULL on error, otherwise human-readable representation of the value
42 */
43static char *
44jwt_value_to_string (void *cls,
45 uint32_t type,
46 const void *data,
47 size_t data_size)
48{
49 switch (type)
50 {
51 case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
52 return GNUNET_strndup (data, data_size);
53
54 default:
55 return NULL;
56 }
57}
58
59
60/**
61 * Convert human-readable version of a 'value' of an credential to the binary
62 * representation.
63 *
64 * @param cls closure, unused
65 * @param type type of the credential
66 * @param s human-readable string
67 * @param data set to value in binary encoding (will be allocated)
68 * @param data_size set to number of bytes in @a data
69 * @return #GNUNET_OK on success
70 */
71static int
72jwt_string_to_value (void *cls,
73 uint32_t type,
74 const char *s,
75 void **data,
76 size_t *data_size)
77{
78 if (NULL == s)
79 return GNUNET_SYSERR;
80 switch (type)
81 {
82 case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
83 *data = GNUNET_strdup (s);
84 *data_size = strlen (s) + 1;
85 return GNUNET_OK;
86
87 default:
88 return GNUNET_SYSERR;
89 }
90}
91
92
93/**
94 * Mapping of credential type numbers to human-readable
95 * credential type names.
96 */
97static struct
98{
99 const char *name;
100 uint32_t number;
101} jwt_cred_name_map[] = { { "JWT", GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT },
102 { NULL, UINT32_MAX } };
103
104/**
105 * Convert a type name to the corresponding number.
106 *
107 * @param cls closure, unused
108 * @param jwt_typename name to convert
109 * @return corresponding number, UINT32_MAX on error
110 */
111static uint32_t
112jwt_typename_to_number (void *cls, const char *jwt_typename)
113{
114 unsigned int i;
115
116 i = 0;
117 while ((NULL != jwt_cred_name_map[i].name) &&
118 (0 != strcasecmp (jwt_typename, jwt_cred_name_map[i].name)))
119 i++;
120 return jwt_cred_name_map[i].number;
121}
122
123
124/**
125 * Convert a type number to the corresponding type string (e.g. 1 to "A")
126 *
127 * @param cls closure, unused
128 * @param type number of a type to convert
129 * @return corresponding typestring, NULL on error
130 */
131static const char *
132jwt_number_to_typename (void *cls, uint32_t type)
133{
134 unsigned int i;
135
136 i = 0;
137 while ((NULL != jwt_cred_name_map[i].name) && (type !=
138 jwt_cred_name_map[i].
139 number))
140 i++;
141 return jwt_cred_name_map[i].name;
142}
143
144
145/**
146 * Parse a JWT and return the respective claim value as Attribute
147 *
148 * @param cls the plugin
149 * @param cred the jwt credential
150 * @return a GNUNET_RECLAIM_Attribute, containing the new value
151 */
152struct GNUNET_RECLAIM_AttributeList *
153jwt_parse_attributes (void *cls,
154 const char *data,
155 size_t data_size)
156{
157 char *jwt_string;
158 struct GNUNET_RECLAIM_AttributeList *attrs;
159 char delim[] = ".";
160 char *val_str = NULL;
161 char *decoded_jwt;
162 char *tmp;
163 json_t *json_val;
164 json_error_t json_err;
165
166 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
167
168 jwt_string = GNUNET_strndup (data, data_size);
169 const char *jwt_body = strtok (jwt_string, delim);
170 if (NULL == jwt_body)
171 {
172 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
173 "Failed to parse JSON %s\n", jwt_string);
174 return attrs;
175 }
176 jwt_body = strtok (NULL, delim);
177 if (NULL == jwt_body)
178 {
179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
180 "Failed to parse JSON %s\n", jwt_string);
181 GNUNET_free (jwt_string);
182 return attrs;
183 }
184 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
185 (void **) &decoded_jwt);
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded JWT: %s\n", decoded_jwt);
187 GNUNET_assert (NULL != decoded_jwt);
188 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err);
189 GNUNET_free (decoded_jwt);
190 const char *key;
191 const char *addr_key;
192 json_t *value;
193 json_t *addr_value;
194
195 json_object_foreach (json_val, key, value) {
196 if (0 == strcmp ("iss", key))
197 continue;
198 if (0 == strcmp ("jti", key))
199 continue;
200 if (0 == strcmp ("exp", key))
201 continue;
202 if (0 == strcmp ("iat", key))
203 continue;
204 if (0 == strcmp ("nbf", key))
205 continue;
206 if (0 == strcmp ("aud", key))
207 continue;
208 if (0 == strcmp ("address", key))
209 {
210 if (! json_is_object (value))
211 {
212 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
213 "address claim in wrong format!");
214 continue;
215 }
216 json_object_foreach (value, addr_key, addr_value) {
217 val_str = json_dumps (addr_value, JSON_ENCODE_ANY);
218 tmp = val_str;
219 // Remove leading " from jasson conversion
220 if (tmp[0] == '"')
221 tmp++;
222 // Remove trailing " from jansson conversion
223 if (tmp[strlen (tmp) - 1] == '"')
224 tmp[strlen (tmp) - 1] = '\0';
225 GNUNET_RECLAIM_attribute_list_add (attrs,
226 addr_key,
227 NULL,
228 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
229 tmp,
230 strlen (val_str));
231 GNUNET_free (val_str);
232 }
233 continue;
234 }
235 val_str = json_dumps (value, JSON_ENCODE_ANY);
236 tmp = val_str;
237 // Remove leading " from jasson conversion
238 if (tmp[0] == '"')
239 tmp++;
240 // Remove trailing " from jansson conversion
241 if (tmp[strlen (tmp) - 1] == '"')
242 tmp[strlen (tmp) - 1] = '\0';
243 GNUNET_RECLAIM_attribute_list_add (attrs,
244 key,
245 NULL,
246 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,// FIXME
247 tmp,
248 strlen (val_str));
249 GNUNET_free (val_str);
250 }
251 json_decref (json_val);
252 GNUNET_free (jwt_string);
253 return attrs;
254}
255
256
257/**
258 * Parse a JWT and return the respective claim value as Attribute
259 *
260 * @param cls the plugin
261 * @param cred the jwt credential
262 * @return a GNUNET_RECLAIM_Attribute, containing the new value
263 */
264struct GNUNET_RECLAIM_AttributeList *
265jwt_parse_attributes_c (void *cls,
266 const struct GNUNET_RECLAIM_Credential *cred)
267{
268 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT)
269 return NULL;
270 return jwt_parse_attributes (cls, cred->data, cred->data_size);
271}
272
273
274/**
275 * Parse a JWT and return the respective claim value as Attribute
276 *
277 * @param cls the plugin
278 * @param cred the jwt credential
279 * @return a GNUNET_RECLAIM_Attribute, containing the new value
280 */
281struct GNUNET_RECLAIM_AttributeList *
282jwt_parse_attributes_p (void *cls,
283 const struct GNUNET_RECLAIM_Presentation *cred)
284{
285 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT)
286 return NULL;
287 return jwt_parse_attributes (cls, cred->data, cred->data_size);
288}
289
290
291/**
292 * Parse a JWT and return the issuer
293 *
294 * @param cls the plugin
295 * @param cred the jwt credential
296 * @return a string, containing the isser
297 */
298char *
299jwt_get_issuer (void *cls,
300 const char *data,
301 size_t data_size)
302{
303 const char *jwt_body;
304 char *jwt_string;
305 char delim[] = ".";
306 char *issuer = NULL;
307 char *decoded_jwt;
308 json_t *issuer_json;
309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
310 json_t *json_val;
311 json_error_t json_err;
312
313 jwt_string = GNUNET_strndup (data, data_size);
314 jwt_body = strtok (jwt_string, delim);
315 jwt_body = strtok (NULL, delim);
316 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
317 (void **) &decoded_jwt);
318 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err);
319 GNUNET_free (decoded_jwt);
320 GNUNET_free (jwt_string);
321 if (NULL == json_val)
322 return NULL;
323 issuer_json = json_object_get (json_val, "iss");
324 if ((NULL == issuer_json) || (! json_is_string (issuer_json)))
325 {
326 json_decref (json_val);
327 return NULL;
328 }
329 issuer = GNUNET_strdup (json_string_value (issuer_json));
330 json_decref (json_val);
331 return issuer;
332}
333
334
335/**
336 * Parse a JWT and return the issuer
337 *
338 * @param cls the plugin
339 * @param cred the jwt credential
340 * @return a string, containing the isser
341 */
342char *
343jwt_get_issuer_c (void *cls,
344 const struct GNUNET_RECLAIM_Credential *cred)
345{
346 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
347 return NULL;
348 return jwt_get_issuer (cls, cred->data, cred->data_size);
349}
350
351
352/**
353 * Parse a JWT and return the issuer
354 *
355 * @param cls the plugin
356 * @param cred the jwt credential
357 * @return a string, containing the isser
358 */
359char *
360jwt_get_issuer_p (void *cls,
361 const struct GNUNET_RECLAIM_Presentation *cred)
362{
363 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
364 return NULL;
365 return jwt_get_issuer (cls, cred->data, cred->data_size);
366}
367
368
369/**
370 * Parse a JWT and return the expiration
371 *
372 * @param cls the plugin
373 * @param cred the jwt credential
374 * @return a string, containing the isser
375 */
376enum GNUNET_GenericReturnValue
377jwt_get_expiration (void *cls,
378 const char *data,
379 size_t data_size,
380 struct GNUNET_TIME_Absolute *exp)
381{
382 const char *jwt_body;
383 char *jwt_string;
384 char delim[] = ".";
385 char *decoded_jwt;
386 json_t *exp_json;
387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
388 json_t *json_val;
389 json_error_t json_err;
390
391 jwt_string = GNUNET_strndup (data, data_size);
392 jwt_body = strtok (jwt_string, delim);
393 jwt_body = strtok (NULL, delim);
394 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
395 (void **) &decoded_jwt);
396 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err);
397 GNUNET_free (decoded_jwt);
398 GNUNET_free (jwt_string);
399 if (NULL == json_val)
400 return GNUNET_SYSERR;
401 exp_json = json_object_get (json_val, "exp");
402 if ((NULL == exp_json) || (! json_is_integer (exp_json)))
403 {
404 json_decref (json_val);
405 return GNUNET_SYSERR;
406 }
407 exp->abs_value_us = json_integer_value (exp_json) * 1000 * 1000;
408 json_decref (json_val);
409 return GNUNET_OK;
410}
411
412
413/**
414 * Parse a JWT and return the expiration
415 *
416 * @param cls the plugin
417 * @param cred the jwt credential
418 * @return the expirati
419 */
420enum GNUNET_GenericReturnValue
421jwt_get_expiration_c (void *cls,
422 const struct GNUNET_RECLAIM_Credential *cred,
423 struct GNUNET_TIME_Absolute *exp)
424{
425 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
426 return GNUNET_NO;
427 return jwt_get_expiration (cls, cred->data, cred->data_size, exp);
428}
429
430
431/**
432 * Parse a JWT and return the expiration
433 *
434 * @param cls the plugin
435 * @param cred the jwt credential
436 * @return a string, containing the isser
437 */
438enum GNUNET_GenericReturnValue
439jwt_get_expiration_p (void *cls,
440 const struct GNUNET_RECLAIM_Presentation *cred,
441 struct GNUNET_TIME_Absolute *exp)
442{
443 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
444 return GNUNET_NO;
445 return jwt_get_expiration (cls, cred->data, cred->data_size, exp);
446}
447
448
449enum GNUNET_GenericReturnValue
450jwt_create_presentation (void *cls,
451 const struct GNUNET_RECLAIM_Credential *cred,
452 const struct GNUNET_RECLAIM_AttributeList *attrs,
453 struct GNUNET_RECLAIM_Presentation **presentation)
454{
455 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
456 return GNUNET_NO;
457 *presentation = GNUNET_RECLAIM_presentation_new (
458 GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT,
459 cred->data,
460 cred->data_size);
461 return GNUNET_OK;
462}
463
464
465/**
466 * Entry point for the plugin.
467 *
468 * @param cls NULL
469 * @return the exported block API
470 */
471void *
472libgnunet_plugin_reclaim_credential_jwt_init (void *cls)
473{
474 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
475
476 api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions);
477 api->value_to_string = &jwt_value_to_string;
478 api->string_to_value = &jwt_string_to_value;
479 api->typename_to_number = &jwt_typename_to_number;
480 api->number_to_typename = &jwt_number_to_typename;
481 api->get_attributes = &jwt_parse_attributes_c;
482 api->get_issuer = &jwt_get_issuer_c;
483 api->get_expiration = &jwt_get_expiration_c;
484 api->value_to_string_p = &jwt_value_to_string;
485 api->string_to_value_p = &jwt_string_to_value;
486 api->typename_to_number_p = &jwt_typename_to_number;
487 api->number_to_typename_p = &jwt_number_to_typename;
488 api->get_attributes_p = &jwt_parse_attributes_p;
489 api->get_issuer_p = &jwt_get_issuer_p;
490 api->get_expiration_p = &jwt_get_expiration_p;
491 api->create_presentation = &jwt_create_presentation;
492 return api;
493}
494
495
496/**
497 * Exit point from the plugin.
498 *
499 * @param cls the return value from #libgnunet_plugin_block_test_init()
500 * @return NULL
501 */
502void *
503libgnunet_plugin_reclaim_credential_jwt_done (void *cls)
504{
505 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
506
507 GNUNET_free (api);
508 return NULL;
509}
510
511
512/* end of plugin_reclaim_credential_type_jwt.c */
diff --git a/src/plugin/reclaim/plugin_reclaim_credential_pabc.c b/src/plugin/reclaim/plugin_reclaim_credential_pabc.c
new file mode 100644
index 000000000..a906805fb
--- /dev/null
+++ b/src/plugin/reclaim/plugin_reclaim_credential_pabc.c
@@ -0,0 +1,572 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/plugin_reclaim_credential_pabc.c
23 * @brief reclaim-credential-plugin-pabc attribute plugin to provide the API for
24 * pabc credentials.
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_reclaim_plugin.h"
31#include <inttypes.h>
32#include <jansson.h>
33#include <pabc/pabc.h>
34#include "pabc_helper.h"
35
36/**
37 * Convert the 'value' of an credential to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the credential
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46pabc_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51 switch (type)
52 {
53 case GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC:
54 return GNUNET_strndup (data, data_size);
55
56 default:
57 return NULL;
58 }
59}
60
61
62/**
63 * Convert human-readable version of a 'value' of an credential to the binary
64 * representation.
65 *
66 * @param cls closure, unused
67 * @param type type of the credential
68 * @param s human-readable string
69 * @param data set to value in binary encoding (will be allocated)
70 * @param data_size set to number of bytes in @a data
71 * @return #GNUNET_OK on success
72 */
73static int
74pabc_string_to_value (void *cls,
75 uint32_t type,
76 const char *s,
77 void **data,
78 size_t *data_size)
79{
80 if (NULL == s)
81 return GNUNET_SYSERR;
82 switch (type)
83 {
84 case GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC:
85 *data = GNUNET_strdup (s);
86 *data_size = strlen (s) + 1;
87 return GNUNET_OK;
88
89 default:
90 return GNUNET_SYSERR;
91 }
92}
93
94
95/**
96 * Mapping of credential type numbers to human-readable
97 * credential type names.
98 */
99static struct
100{
101 const char *name;
102 uint32_t number;
103} pabc_cred_name_map[] = { { "PABC", GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC },
104 { NULL, UINT32_MAX } };
105
106/**
107 * Convert a type name to the corresponding number.
108 *
109 * @param cls closure, unused
110 * @param pabc_typename name to convert
111 * @return corresponding number, UINT32_MAX on error
112 */
113static uint32_t
114pabc_typename_to_number (void *cls, const char *pabc_typename)
115{
116 unsigned int i;
117
118 i = 0;
119 while ((NULL != pabc_cred_name_map[i].name) &&
120 (0 != strcasecmp (pabc_typename, pabc_cred_name_map[i].name)))
121 i++;
122 return pabc_cred_name_map[i].number;
123}
124
125
126/**
127 * Convert a type number (i.e. 1) to the corresponding type string
128 *
129 * @param cls closure, unused
130 * @param type number of a type to convert
131 * @return corresponding typestring, NULL on error
132 */
133static const char *
134pabc_number_to_typename (void *cls, uint32_t type)
135{
136 unsigned int i;
137
138 i = 0;
139 while ((NULL != pabc_cred_name_map[i].name) && (type !=
140 pabc_cred_name_map[i].
141 number))
142 i++;
143 return pabc_cred_name_map[i].name;
144}
145
146
147static void
148inspect_attrs (char const *const key,
149 char const *const value,
150 void *ctx)
151{
152 struct GNUNET_RECLAIM_AttributeList *attrs = ctx;
153
154 if (NULL == value)
155 return;
156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
157 "Found attribute in PABC credential: `%s': `%s'\n",
158 key, value);
159 if (0 == strcmp (key, "expiration"))
160 return;
161 if (0 == strcmp (key, "issuer"))
162 return;
163 if (0 == strcmp (key, "subject"))
164 return;
165 GNUNET_RECLAIM_attribute_list_add (attrs,
166 key,
167 NULL,
168 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
169 value,
170 strlen (value));
171}
172
173
174/**
175 * Parse a pabc and return the respective claim value as Attribute
176 *
177 * @param cls the plugin
178 * @param cred the pabc credential
179 * @return a GNUNET_RECLAIM_Attribute, containing the new value
180 */
181struct GNUNET_RECLAIM_AttributeList *
182pabc_parse_attributes (void *cls,
183 const char *data,
184 size_t data_size)
185{
186 struct GNUNET_RECLAIM_AttributeList *attrs;
187
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189 "Collecting PABC attributes...\n");
190 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
191 GNUNET_assert (PABC_OK ==
192 pabc_cred_inspect_credential (data,
193 &inspect_attrs, attrs));
194 return attrs;
195}
196
197
198/**
199 * Parse a pabc and return the respective claim value as Attribute
200 *
201 * @param cls the plugin
202 * @param cred the pabc credential
203 * @return a GNUNET_RECLAIM_Attribute, containing the new value
204 */
205struct GNUNET_RECLAIM_AttributeList *
206pabc_parse_attributes_c (void *cls,
207 const struct GNUNET_RECLAIM_Credential *cred)
208{
209 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
210 return NULL;
211 return pabc_parse_attributes (cls, cred->data, cred->data_size);
212}
213
214
215/**
216 * Parse a pabc and return the respective claim value as Attribute
217 *
218 * @param cls the plugin
219 * @param cred the pabc credential
220 * @return a GNUNET_RECLAIM_Attribute, containing the new value
221 */
222struct GNUNET_RECLAIM_AttributeList *
223pabc_parse_attributes_p (void *cls,
224 const struct GNUNET_RECLAIM_Presentation *cred)
225{
226 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
227 return NULL;
228 return pabc_parse_attributes (cls, cred->data, cred->data_size);
229}
230
231
232/**
233 * Parse a pabc and return the issuer
234 *
235 * @param cls the plugin
236 * @param cred the pabc credential
237 * @return a string, containing the isser
238 */
239char*
240pabc_get_issuer (void *cls,
241 const char *data,
242 size_t data_size)
243{
244 char *res;
245 if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (data,
246 "issuer",
247 &res))
248 return NULL;
249 return res;
250}
251
252
253/**
254 * Parse a pabc and return the issuer
255 *
256 * @param cls the plugin
257 * @param cred the pabc credential
258 * @return a string, containing the isser
259 */
260char *
261pabc_get_issuer_c (void *cls,
262 const struct GNUNET_RECLAIM_Credential *cred)
263{
264 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type)
265 return NULL;
266 return pabc_get_issuer (cls, cred->data, cred->data_size);
267}
268
269
270/**
271 * Parse a pabc and return the issuer
272 *
273 * @param cls the plugin
274 * @param cred the pabc credential
275 * @return a string, containing the isser
276 */
277char *
278pabc_get_issuer_p (void *cls,
279 const struct GNUNET_RECLAIM_Presentation *cred)
280{
281 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type)
282 return NULL;
283 return pabc_get_issuer (cls, cred->data, cred->data_size);
284}
285
286
287/**
288 * Parse a pabc and return the expiration
289 *
290 * @param cls the plugin
291 * @param cred the pabc credential
292 * @return a string, containing the isser
293 */
294enum GNUNET_GenericReturnValue
295pabc_get_expiration (void *cls,
296 const char *data,
297 size_t data_size,
298 struct GNUNET_TIME_Absolute *exp)
299{
300 char *exp_str;
301 uint64_t exp_i;
302
303 if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (data,
304 "expiration",
305 &exp_str))
306 return GNUNET_SYSERR;
307
308 if (1 != sscanf (exp_str, "%llu", &exp_i))
309 {
310 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
311 "Invalid expiration `%s'\n", exp_str);
312 GNUNET_free (exp_str);
313 return GNUNET_SYSERR;
314 }
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 "Converted expiration string `%s' to %llu",
317 exp_str, exp_i);
318
319 GNUNET_free (exp_str);
320 exp->abs_value_us = exp_i * 1000 * 1000;
321 return GNUNET_OK;
322}
323
324
325/**
326 * Parse a pabc and return the expiration
327 *
328 * @param cls the plugin
329 * @param cred the pabc credential
330 * @return a string, containing the isser
331 */
332enum GNUNET_GenericReturnValue
333pabc_get_expiration_c (void *cls,
334 const struct GNUNET_RECLAIM_Credential *cred,
335 struct GNUNET_TIME_Absolute *exp)
336{
337 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
338 return GNUNET_NO;
339 return pabc_get_expiration (cls, cred->data, cred->data_size, exp);
340}
341
342
343/**
344 * Parse a pabc and return the expiration
345 *
346 * @param cls the plugin
347 * @param cred the pabc credential
348 * @return a string, containing the isser
349 */
350enum GNUNET_GenericReturnValue
351pabc_get_expiration_p (void *cls,
352 const struct GNUNET_RECLAIM_Presentation *cred,
353 struct GNUNET_TIME_Absolute *exp)
354{
355 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
356 return GNUNET_NO;
357 return pabc_get_expiration (cls, cred->data, cred->data_size, exp);
358}
359
360
361int
362pabc_create_presentation (void *cls,
363 const struct GNUNET_RECLAIM_Credential *credential,
364 const struct GNUNET_RECLAIM_AttributeList *attrs,
365 struct GNUNET_RECLAIM_Presentation **presentation)
366{
367 struct pabc_context *ctx = NULL;
368 struct pabc_user_context *usr_ctx = NULL;
369 struct pabc_public_parameters *pp = NULL;
370 struct pabc_credential *cred = NULL;
371 struct pabc_blinded_proof *proof = NULL;
372 struct GNUNET_RECLAIM_AttributeListEntry *ale;
373 char *issuer;
374 char *subject;
375 enum pabc_status status;
376
377 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != credential->type)
378 return GNUNET_NO;
379
380
381 PABC_ASSERT (pabc_new_ctx (&ctx));
382 issuer = pabc_get_issuer_c (cls, credential);
383 if (NULL == issuer)
384 {
385 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
386 "No issuer found in credential\n");
387 pabc_free_ctx (&ctx);
388 return GNUNET_SYSERR;
389 }
390 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
391 "Got issuer for credential: %s\n", issuer);
392 status = PABC_load_public_parameters (ctx, issuer, &pp);
393 if (status != PABC_OK)
394 {
395 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
396 "Failed to read public parameters.\n");
397 pabc_free_ctx (&ctx);
398 GNUNET_free (issuer);
399 return GNUNET_SYSERR;
400 }
401 if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (credential->data,
402 "subject",
403 &subject))
404 {
405 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
406 "Failed to get subject.\n");
407 pabc_free_ctx (&ctx);
408 GNUNET_free (issuer);
409 return GNUNET_SYSERR;
410 }
411 status = PABC_read_usr_ctx (subject, issuer, ctx, pp, &usr_ctx);
412 GNUNET_free (issuer);
413 GNUNET_free (subject);
414 if (PABC_OK != status)
415 {
416 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
417 "Failed to read user context.\n");
418 pabc_free_public_parameters (ctx, &pp);
419 return GNUNET_SYSERR;
420 }
421
422 status = pabc_new_credential (ctx, pp, &cred);
423 if (status != PABC_OK)
424 {
425 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
426 "Failed to allocate credential.\n");
427 pabc_free_user_context (ctx, pp, &usr_ctx);
428 pabc_free_public_parameters (ctx, &pp);
429 return GNUNET_SYSERR;
430 }
431
432 status = pabc_decode_credential (ctx, pp, cred, credential->data);
433 if (status != PABC_OK)
434 {
435 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
436 "Failed to decode credential.\n");
437 pabc_free_credential (ctx, pp, &cred);
438 pabc_free_user_context (ctx, pp, &usr_ctx);
439 pabc_free_public_parameters (ctx, &pp);
440 return GNUNET_SYSERR;
441 }
442
443 status = pabc_new_proof (ctx, pp, &proof);
444 if (status != PABC_OK)
445 {
446 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
447 "Failed to allocate proof.\n");
448 pabc_free_credential (ctx, pp, &cred);
449 pabc_free_user_context (ctx, pp, &usr_ctx);
450 pabc_free_public_parameters (ctx, &pp);
451 return GNUNET_SYSERR;
452 }
453
454 // now we can parse the attributes to disclose and configure the proof
455 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
456 {
457 status = pabc_set_disclosure_by_attribute_name (ctx, pp, proof,
458 ale->attribute->name,
459 PABC_DISCLOSED, cred);
460 if (status != PABC_OK)
461 {
462 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
463 "Failed to configure proof.\n");
464 pabc_free_credential (ctx, pp, &cred);
465 pabc_free_user_context (ctx, pp, &usr_ctx);
466 pabc_free_public_parameters (ctx, &pp);
467 return GNUNET_SYSERR;
468 }
469 }
470
471 // and finally -> sign the proof
472 status = pabc_gen_proof (ctx, usr_ctx, pp, proof, cred);
473 if (status != PABC_OK)
474 {
475 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
476 "Failed to sign proof.\n");
477 pabc_free_proof (ctx, pp, &proof);
478 pabc_free_credential (ctx, pp, &cred);
479 pabc_free_user_context (ctx, pp, &usr_ctx);
480 pabc_free_public_parameters (ctx, &pp);
481 return GNUNET_SYSERR;
482 }
483 // print the result
484 char *json = NULL;
485 char *ppid = NULL;
486 char *userid = NULL;
487 GNUNET_assert (PABC_OK == pabc_cred_get_userid_from_cred (credential->data,
488 &userid));
489 GNUNET_assert (PABC_OK == pabc_cred_get_ppid_from_cred (credential->data,
490 &ppid));
491 pabc_cred_encode_proof (ctx, pp, proof, userid, ppid, &json);
492 GNUNET_free (ppid);
493 GNUNET_free (userid);
494 if (PABC_OK != status)
495 {
496 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
497 "Failed to serialize proof.\n");
498 pabc_free_proof (ctx, pp, &proof);
499 pabc_free_credential (ctx, pp, &cred);
500 pabc_free_user_context (ctx, pp, &usr_ctx);
501 pabc_free_public_parameters (ctx, &pp);
502 return GNUNET_SYSERR;
503 }
504 char *json_enc;
505 GNUNET_STRINGS_base64_encode (json,
506 strlen (json) + 1,
507 &json_enc);
508 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
509 "Presentation: %s\n", json_enc);
510 // clean up
511 *presentation = GNUNET_RECLAIM_presentation_new (
512 GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC,
513 json_enc,
514 strlen (json_enc) + 1);
515 GNUNET_free (json_enc);
516 PABC_FREE_NULL (json);
517 pabc_free_proof (ctx, pp, &proof);
518 pabc_free_credential (ctx, pp, &cred);
519 pabc_free_user_context (ctx, pp, &usr_ctx);
520 pabc_free_public_parameters (ctx, &pp);
521 return GNUNET_OK;
522}
523
524
525/**
526 * Entry point for the plugin.
527 *
528 * @param cls NULL
529 * @return the exported block API
530 */
531void *
532libgnunet_plugin_reclaim_credential_pabc_init (void *cls)
533{
534 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
535
536 api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions);
537 api->value_to_string = &pabc_value_to_string;
538 api->string_to_value = &pabc_string_to_value;
539 api->typename_to_number = &pabc_typename_to_number;
540 api->number_to_typename = &pabc_number_to_typename;
541 api->get_attributes = &pabc_parse_attributes_c;
542 api->get_issuer = &pabc_get_issuer_c;
543 api->get_expiration = &pabc_get_expiration_c;
544 api->value_to_string_p = &pabc_value_to_string;
545 api->string_to_value_p = &pabc_string_to_value;
546 api->typename_to_number_p = &pabc_typename_to_number;
547 api->number_to_typename_p = &pabc_number_to_typename;
548 api->get_attributes_p = &pabc_parse_attributes_p;
549 api->get_issuer_p = &pabc_get_issuer_p;
550 api->get_expiration_p = &pabc_get_expiration_p;
551 api->create_presentation = &pabc_create_presentation;
552 return api;
553}
554
555
556/**
557 * Exit point from the plugin.
558 *
559 * @param cls the return value from #libgnunet_plugin_block_test_init()
560 * @return NULL
561 */
562void *
563libgnunet_plugin_reclaim_credential_pabc_done (void *cls)
564{
565 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
566
567 GNUNET_free (api);
568 return NULL;
569}
570
571
572/* end of plugin_reclaim_credential_type_pabc.c */