diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/reclaim/Makefile.am | 40 | ||||
-rw-r--r-- | src/reclaim/json_reclaim.c | 16 | ||||
-rw-r--r-- | src/reclaim/pabc_helper.c | 364 | ||||
-rw-r--r-- | src/reclaim/pabc_helper.h | 41 | ||||
-rw-r--r-- | src/reclaim/plugin_reclaim_credential_jwt.c | 32 | ||||
-rw-r--r-- | src/reclaim/plugin_reclaim_credential_pabc.c | 639 | ||||
-rw-r--r-- | src/reclaim/plugin_rest_pabc.c | 666 | ||||
-rw-r--r-- | src/reclaim/reclaim_credential.c | 1 |
8 files changed, 1780 insertions, 19 deletions
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am index 9463f19d9..1a0b7fae4 100644 --- a/src/reclaim/Makefile.am +++ b/src/reclaim/Makefile.am | |||
@@ -16,6 +16,11 @@ REST_PLUGIN = \ | |||
16 | CREDENTIAL_PLUGIN = \ | 16 | CREDENTIAL_PLUGIN = \ |
17 | libgnunet_plugin_reclaim_credential_jwt.la | 17 | libgnunet_plugin_reclaim_credential_jwt.la |
18 | 18 | ||
19 | if HAVE_PABC | ||
20 | CREDENTIAL_PLUGIN += libgnunet_plugin_reclaim_credential_pabc.la | ||
21 | REST_PLUGIN += libgnunet_plugin_rest_pabc.la | ||
22 | endif | ||
23 | |||
19 | EXTRA_DIST = \ | 24 | EXTRA_DIST = \ |
20 | reclaim.conf \ | 25 | reclaim.conf \ |
21 | test_reclaim_defaults.conf \ | 26 | test_reclaim_defaults.conf \ |
@@ -87,6 +92,26 @@ libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \ | |||
87 | $(GN_PLUGIN_LDFLAGS) | 92 | $(GN_PLUGIN_LDFLAGS) |
88 | libgnunet_plugin_rest_openid_connect_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | 93 | libgnunet_plugin_rest_openid_connect_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) |
89 | 94 | ||
95 | if HAVE_PABC | ||
96 | libgnunet_plugin_rest_pabc_la_SOURCES = \ | ||
97 | plugin_rest_pabc.c \ | ||
98 | pabc_helper.c | ||
99 | libgnunet_plugin_rest_pabc_la_LIBADD = \ | ||
100 | libgnunetreclaim.la \ | ||
101 | $(top_builddir)/src/json/libgnunetjson.la \ | ||
102 | $(top_builddir)/src/rest/libgnunetrest.la \ | ||
103 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | ||
104 | $(LTLIBINTL) -ljansson -lpabc $(MHD_LIBS) | ||
105 | libgnunet_plugin_rest_pabc_la_DEPENDENCIES = \ | ||
106 | libgnunetreclaim.la \ | ||
107 | $(top_builddir)/src/json/libgnunetjson.la \ | ||
108 | $(top_builddir)/src/rest/libgnunetrest.la \ | ||
109 | $(top_builddir)/src/util/libgnunetutil.la | ||
110 | libgnunet_plugin_rest_pabc_la_LDFLAGS = \ | ||
111 | $(GN_PLUGIN_LDFLAGS) | ||
112 | libgnunet_plugin_rest_pabc_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | ||
113 | endif | ||
114 | |||
90 | 115 | ||
91 | libgnunet_plugin_gnsrecord_reclaim_la_SOURCES = \ | 116 | libgnunet_plugin_gnsrecord_reclaim_la_SOURCES = \ |
92 | plugin_gnsrecord_reclaim.c | 117 | plugin_gnsrecord_reclaim.c |
@@ -134,6 +159,21 @@ libgnunet_plugin_reclaim_attribute_basic_la_LIBADD = \ | |||
134 | libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \ | 159 | libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \ |
135 | $(GN_PLUGIN_LDFLAGS) | 160 | $(GN_PLUGIN_LDFLAGS) |
136 | 161 | ||
162 | if HAVE_PABC | ||
163 | libgnunet_plugin_reclaim_credential_pabc_la_SOURCES = \ | ||
164 | plugin_reclaim_credential_pabc.c \ | ||
165 | pabc_helper.c | ||
166 | libgnunet_plugin_reclaim_credential_pabc_la_LIBADD = \ | ||
167 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
168 | libgnunetreclaim.la \ | ||
169 | -ljansson\ | ||
170 | -lpabc \ | ||
171 | $(LTLIBINTL) | ||
172 | libgnunet_plugin_reclaim_credential_pabc_la_LDFLAGS = \ | ||
173 | $(GN_PLUGIN_LDFLAGS) | ||
174 | endif | ||
175 | |||
176 | |||
137 | libgnunet_plugin_reclaim_credential_jwt_la_SOURCES = \ | 177 | libgnunet_plugin_reclaim_credential_jwt_la_SOURCES = \ |
138 | plugin_reclaim_credential_jwt.c | 178 | plugin_reclaim_credential_jwt.c |
139 | libgnunet_plugin_reclaim_credential_jwt_la_LIBADD = \ | 179 | libgnunet_plugin_reclaim_credential_jwt_la_LIBADD = \ |
diff --git a/src/reclaim/json_reclaim.c b/src/reclaim/json_reclaim.c index 4eeb22bee..b1ca7a4a5 100644 --- a/src/reclaim/json_reclaim.c +++ b/src/reclaim/json_reclaim.c | |||
@@ -290,10 +290,11 @@ parse_credential (void *cls, json_t *root, struct GNUNET_JSON_Specification *spe | |||
290 | { | 290 | { |
291 | struct GNUNET_RECLAIM_Credential *cred; | 291 | struct GNUNET_RECLAIM_Credential *cred; |
292 | const char *name_str = NULL; | 292 | const char *name_str = NULL; |
293 | const char *val_str = NULL; | ||
294 | const char *type_str = NULL; | 293 | const char *type_str = NULL; |
295 | const char *id_str = NULL; | 294 | const char *id_str = NULL; |
296 | char *data; | 295 | json_t *val_json; |
296 | char *data = NULL; | ||
297 | char *val_str = NULL; | ||
297 | int unpack_state; | 298 | int unpack_state; |
298 | uint32_t type; | 299 | uint32_t type; |
299 | size_t data_size; | 300 | size_t data_size; |
@@ -308,7 +309,7 @@ parse_credential (void *cls, json_t *root, struct GNUNET_JSON_Specification *spe | |||
308 | } | 309 | } |
309 | // interpret single attribute | 310 | // interpret single attribute |
310 | unpack_state = json_unpack (root, | 311 | unpack_state = json_unpack (root, |
311 | "{s:s, s?s, s:s, s:s!}", | 312 | "{s:s, s?s, s:s, s:o!}", |
312 | "name", | 313 | "name", |
313 | &name_str, | 314 | &name_str, |
314 | "id", | 315 | "id", |
@@ -316,14 +317,19 @@ parse_credential (void *cls, json_t *root, struct GNUNET_JSON_Specification *spe | |||
316 | "type", | 317 | "type", |
317 | &type_str, | 318 | &type_str, |
318 | "value", | 319 | "value", |
319 | &val_str); | 320 | &val_json); |
320 | if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) || | 321 | if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_json) || |
321 | (NULL == type_str)) | 322 | (NULL == type_str)) |
322 | { | 323 | { |
323 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 324 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
324 | "Error json object has a wrong format!\n"); | 325 | "Error json object has a wrong format!\n"); |
325 | return GNUNET_SYSERR; | 326 | return GNUNET_SYSERR; |
326 | } | 327 | } |
328 | if (json_is_string (val_json)) { | ||
329 | val_str = GNUNET_strdup (json_string_value (val_json)); | ||
330 | } else { | ||
331 | val_str = json_dumps (val_json, JSON_COMPACT); | ||
332 | } | ||
327 | type = GNUNET_RECLAIM_credential_typename_to_number (type_str); | 333 | type = GNUNET_RECLAIM_credential_typename_to_number (type_str); |
328 | if (GNUNET_SYSERR == | 334 | if (GNUNET_SYSERR == |
329 | (GNUNET_RECLAIM_credential_string_to_value (type, | 335 | (GNUNET_RECLAIM_credential_string_to_value (type, |
diff --git a/src/reclaim/pabc_helper.c b/src/reclaim/pabc_helper.c new file mode 100644 index 000000000..1b1dbea0f --- /dev/null +++ b/src/reclaim/pabc_helper.c | |||
@@ -0,0 +1,364 @@ | |||
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 "pabc_helper.h" | ||
8 | #include <pwd.h> | ||
9 | #include <stdlib.h> | ||
10 | #include <unistd.h> | ||
11 | |||
12 | static char pabc_dir[PATH_MAX + 1]; | ||
13 | |||
14 | static const char * | ||
15 | get_homedir () | ||
16 | { | ||
17 | const char *homedir; | ||
18 | if ((homedir = getenv ("HOME")) == NULL) | ||
19 | { | ||
20 | homedir = getpwuid (getuid ())->pw_dir; | ||
21 | } | ||
22 | return homedir; | ||
23 | } | ||
24 | |||
25 | |||
26 | static enum GNUNET_GenericReturnValue | ||
27 | write_file (char const *const filename, const char *buffer) | ||
28 | { | ||
29 | struct GNUNET_DISK_FileHandle *fh; | ||
30 | fh = GNUNET_DISK_file_open (filename, | ||
31 | GNUNET_DISK_OPEN_WRITE | ||
32 | | GNUNET_DISK_OPEN_TRUNCATE | ||
33 | | GNUNET_DISK_OPEN_CREATE, | ||
34 | GNUNET_DISK_PERM_USER_WRITE | ||
35 | | GNUNET_DISK_PERM_USER_READ); | ||
36 | if (fh == NULL) | ||
37 | return GNUNET_SYSERR; | ||
38 | if (GNUNET_SYSERR == GNUNET_DISK_file_write (fh, | ||
39 | buffer, strlen (buffer) + 1)) | ||
40 | goto fail; | ||
41 | GNUNET_DISK_file_close (fh); | ||
42 | return GNUNET_OK; | ||
43 | |||
44 | fail: | ||
45 | GNUNET_DISK_file_close (fh); | ||
46 | return GNUNET_SYSERR; | ||
47 | } | ||
48 | |||
49 | |||
50 | static enum GNUNET_GenericReturnValue | ||
51 | init_pabc_dir () | ||
52 | { | ||
53 | size_t filename_size = strlen (get_homedir ()) + 1 + strlen (".local") + 1 | ||
54 | + strlen ("pabc-reclaim") + 1; | ||
55 | snprintf (pabc_dir, filename_size, "%s/%s/%s", | ||
56 | get_homedir (), ".local", "pabc-reclaim"); | ||
57 | return GNUNET_DISK_directory_create (pabc_dir); | ||
58 | } | ||
59 | |||
60 | |||
61 | static const char * | ||
62 | get_pabcdir () | ||
63 | { | ||
64 | init_pabc_dir (); | ||
65 | return pabc_dir; | ||
66 | } | ||
67 | |||
68 | |||
69 | enum GNUNET_GenericReturnValue | ||
70 | read_file (char const *const filename, char **buffer) | ||
71 | { | ||
72 | struct GNUNET_DISK_FileHandle *fh; | ||
73 | if (GNUNET_YES != GNUNET_DISK_file_test (filename)) | ||
74 | return GNUNET_SYSERR; | ||
75 | |||
76 | fh = GNUNET_DISK_file_open (filename, | ||
77 | GNUNET_DISK_OPEN_READ, | ||
78 | GNUNET_DISK_PERM_USER_READ); | ||
79 | if (fh == NULL) | ||
80 | return GNUNET_SYSERR; | ||
81 | long lSize = GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_END); | ||
82 | if (lSize < 0) | ||
83 | goto fail; | ||
84 | GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_SET); | ||
85 | *buffer = calloc ((size_t) lSize + 1, sizeof(char)); | ||
86 | if (*buffer == NULL) | ||
87 | goto fail; | ||
88 | |||
89 | // copy the file into the buffer: | ||
90 | size_t r = GNUNET_DISK_file_read (fh, *buffer, (size_t) lSize); | ||
91 | if (r != (size_t) lSize) | ||
92 | goto fail; | ||
93 | |||
94 | GNUNET_DISK_file_close (fh); | ||
95 | return GNUNET_OK; | ||
96 | |||
97 | fail: | ||
98 | GNUNET_DISK_file_close (fh); | ||
99 | return GNUNET_SYSERR; | ||
100 | } | ||
101 | |||
102 | |||
103 | struct pabc_public_parameters * | ||
104 | PABC_read_issuer_ppfile (const char *f, struct pabc_context *const ctx) | ||
105 | { | ||
106 | if (NULL == ctx) | ||
107 | { | ||
108 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No global context provided\n"); | ||
109 | return NULL; | ||
110 | } | ||
111 | struct pabc_public_parameters *pp; | ||
112 | char *buffer; | ||
113 | int r; | ||
114 | r = read_file (f, &buffer); | ||
115 | if (GNUNET_OK != r) | ||
116 | { | ||
117 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading file\n"); | ||
118 | return NULL; | ||
119 | } | ||
120 | if (PABC_OK != pabc_decode_and_new_public_parameters (ctx, &pp, buffer)) | ||
121 | { | ||
122 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
123 | "Failed to decode public parameters\n"); | ||
124 | PABC_FREE_NULL (buffer); | ||
125 | return NULL; | ||
126 | } | ||
127 | PABC_FREE_NULL (buffer); | ||
128 | return pp; | ||
129 | } | ||
130 | |||
131 | |||
132 | enum GNUNET_GenericReturnValue | ||
133 | PABC_load_public_parameters (struct pabc_context *const ctx, | ||
134 | char const *const pp_name, | ||
135 | struct pabc_public_parameters **pp) | ||
136 | { | ||
137 | char fname[PATH_MAX]; | ||
138 | char *pp_filename; | ||
139 | const char *pdir = get_pabcdir (); | ||
140 | |||
141 | if (ctx == NULL) | ||
142 | return GNUNET_SYSERR; | ||
143 | if (pp_name == NULL) | ||
144 | return GNUNET_SYSERR; | ||
145 | |||
146 | GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename); | ||
147 | if (GNUNET_YES != GNUNET_DISK_directory_test (pdir, GNUNET_YES)) | ||
148 | { | ||
149 | GNUNET_free (pp_filename); | ||
150 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading %s\n", pdir); | ||
151 | return GNUNET_SYSERR; | ||
152 | } | ||
153 | snprintf (fname, PATH_MAX, "%s/%s%s", pdir, pp_filename, PABC_PP_EXT); | ||
154 | if (GNUNET_YES != GNUNET_DISK_file_test (fname)) | ||
155 | { | ||
156 | GNUNET_free (pp_filename); | ||
157 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error testing %s\n", fname); | ||
158 | return GNUNET_SYSERR; | ||
159 | } | ||
160 | *pp = PABC_read_issuer_ppfile (fname, ctx); | ||
161 | if (*pp) | ||
162 | return GNUNET_OK; | ||
163 | else | ||
164 | return GNUNET_SYSERR; | ||
165 | } | ||
166 | |||
167 | |||
168 | enum GNUNET_GenericReturnValue | ||
169 | PABC_write_public_parameters (char const *const pp_name, | ||
170 | struct pabc_public_parameters *const pp) | ||
171 | { | ||
172 | char *json; | ||
173 | char *filename; | ||
174 | char *pp_filename; | ||
175 | enum pabc_status status; | ||
176 | struct pabc_context *ctx = NULL; | ||
177 | |||
178 | GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename); | ||
179 | PABC_ASSERT (pabc_new_ctx (&ctx)); | ||
180 | // store in json file | ||
181 | status = pabc_encode_public_parameters (ctx, pp, &json); | ||
182 | if (status != PABC_OK) | ||
183 | { | ||
184 | GNUNET_free (pp_filename); | ||
185 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
186 | "Failed to encode public parameters.\n"); | ||
187 | pabc_free_ctx (&ctx); | ||
188 | return GNUNET_SYSERR; | ||
189 | } | ||
190 | |||
191 | size_t filename_size = | ||
192 | strlen (get_pabcdir ()) + 1 + strlen (pp_filename) + strlen (PABC_PP_EXT) | ||
193 | + 1; | ||
194 | filename = GNUNET_malloc (filename_size); | ||
195 | if (! filename) | ||
196 | { | ||
197 | GNUNET_free (pp_filename); | ||
198 | PABC_FREE_NULL (json); | ||
199 | pabc_free_ctx (&ctx); | ||
200 | return GNUNET_SYSERR; | ||
201 | } | ||
202 | snprintf (filename, filename_size, "%s/%s%s", get_pabcdir (), pp_filename, | ||
203 | PABC_PP_EXT); | ||
204 | |||
205 | GNUNET_free (pp_filename); | ||
206 | if (GNUNET_OK != write_file (filename, json)) | ||
207 | { | ||
208 | PABC_FREE_NULL (filename); | ||
209 | PABC_FREE_NULL (json); | ||
210 | pabc_free_ctx (&ctx); | ||
211 | return GNUNET_SYSERR; | ||
212 | } | ||
213 | PABC_FREE_NULL (filename); | ||
214 | PABC_FREE_NULL (json); | ||
215 | pabc_free_ctx (&ctx); | ||
216 | return GNUNET_OK; | ||
217 | } | ||
218 | |||
219 | |||
220 | enum GNUNET_GenericReturnValue | ||
221 | PABC_write_usr_ctx (char const *const usr_name, | ||
222 | char const *const pp_name, | ||
223 | struct pabc_context const *const ctx, | ||
224 | struct pabc_public_parameters const *const pp, | ||
225 | struct pabc_user_context *const usr_ctx) | ||
226 | { | ||
227 | |||
228 | char *pp_filename; | ||
229 | char *json = NULL; | ||
230 | enum pabc_status status; | ||
231 | char *fname = NULL; | ||
232 | |||
233 | if (NULL == usr_name) | ||
234 | { | ||
235 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n"); | ||
236 | return GNUNET_SYSERR; | ||
237 | } | ||
238 | if (NULL == pp_name) | ||
239 | { | ||
240 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n"); | ||
241 | return GNUNET_SYSERR; | ||
242 | } | ||
243 | if (NULL == ctx) | ||
244 | { | ||
245 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n"); | ||
246 | return GNUNET_SYSERR; | ||
247 | } | ||
248 | if (NULL == pp) | ||
249 | { | ||
250 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n"); | ||
251 | return GNUNET_SYSERR; | ||
252 | } | ||
253 | if (NULL == usr_ctx) | ||
254 | { | ||
255 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n"); | ||
256 | return GNUNET_SYSERR; | ||
257 | } | ||
258 | |||
259 | GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename); | ||
260 | status = pabc_encode_user_ctx (ctx, pp, usr_ctx, &json); | ||
261 | if (PABC_OK != status) | ||
262 | { | ||
263 | GNUNET_free (pp_filename); | ||
264 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n"); | ||
265 | return status; | ||
266 | } | ||
267 | |||
268 | size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1 | ||
269 | + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1; | ||
270 | fname = GNUNET_malloc (fname_size); | ||
271 | |||
272 | snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name, | ||
273 | pp_filename, | ||
274 | PABC_USR_EXT); | ||
275 | |||
276 | GNUNET_free (pp_filename); | ||
277 | if (GNUNET_OK == write_file (fname, json)) | ||
278 | { | ||
279 | GNUNET_free (fname); | ||
280 | GNUNET_free (json); | ||
281 | return GNUNET_OK; | ||
282 | } | ||
283 | else | ||
284 | { | ||
285 | GNUNET_free (fname); | ||
286 | GNUNET_free (json); | ||
287 | return GNUNET_SYSERR; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | |||
292 | enum GNUNET_GenericReturnValue | ||
293 | PABC_read_usr_ctx (char const *const usr_name, | ||
294 | char const *const pp_name, | ||
295 | struct pabc_context const *const ctx, | ||
296 | struct pabc_public_parameters const *const pp, | ||
297 | struct pabc_user_context **usr_ctx) | ||
298 | { | ||
299 | char *json = NULL; | ||
300 | char *pp_filename; | ||
301 | enum pabc_status status; | ||
302 | |||
303 | char *fname = NULL; | ||
304 | |||
305 | if (NULL == usr_name) | ||
306 | { | ||
307 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n"); | ||
308 | return GNUNET_SYSERR; | ||
309 | } | ||
310 | if (NULL == pp_name) | ||
311 | { | ||
312 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n"); | ||
313 | return GNUNET_SYSERR; | ||
314 | } | ||
315 | if (NULL == ctx) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n"); | ||
318 | return GNUNET_SYSERR; | ||
319 | } | ||
320 | if (NULL == pp) | ||
321 | { | ||
322 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n"); | ||
323 | return GNUNET_SYSERR; | ||
324 | } | ||
325 | if (NULL == usr_ctx) | ||
326 | { | ||
327 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n"); | ||
328 | return GNUNET_SYSERR; | ||
329 | } | ||
330 | GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename); | ||
331 | |||
332 | size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1 | ||
333 | + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1; | ||
334 | fname = GNUNET_malloc (fname_size); | ||
335 | snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name, | ||
336 | pp_filename, | ||
337 | PABC_USR_EXT); | ||
338 | GNUNET_free (pp_filename); | ||
339 | if (GNUNET_OK != read_file (fname, &json)) | ||
340 | { | ||
341 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
342 | "Failed to read `%s'\n", fname); | ||
343 | PABC_FREE_NULL (fname); | ||
344 | return GNUNET_SYSERR; | ||
345 | } | ||
346 | GNUNET_free (fname); | ||
347 | |||
348 | status = pabc_new_user_context (ctx, pp, usr_ctx); | ||
349 | if (PABC_OK != status) | ||
350 | { | ||
351 | GNUNET_free (json); | ||
352 | return GNUNET_SYSERR; | ||
353 | } | ||
354 | status = pabc_decode_user_ctx (ctx, pp, *usr_ctx, json); | ||
355 | GNUNET_free (json); | ||
356 | if (PABC_OK != status) | ||
357 | { | ||
358 | pabc_free_user_context (ctx, pp, usr_ctx); | ||
359 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n"); | ||
360 | return GNUNET_SYSERR; | ||
361 | } | ||
362 | |||
363 | return GNUNET_OK; | ||
364 | } | ||
diff --git a/src/reclaim/pabc_helper.h b/src/reclaim/pabc_helper.h new file mode 100644 index 000000000..045ad5dda --- /dev/null +++ b/src/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 | |||
17 | enum GNUNET_GenericReturnValue | ||
18 | PABC_write_public_parameters (char const *const pp_name, | ||
19 | struct pabc_public_parameters *const pp); | ||
20 | |||
21 | |||
22 | enum GNUNET_GenericReturnValue | ||
23 | PABC_load_public_parameters (struct pabc_context *const ctx, | ||
24 | char const *const pp_name, | ||
25 | struct pabc_public_parameters **pp); | ||
26 | |||
27 | enum GNUNET_GenericReturnValue | ||
28 | PABC_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 | |||
35 | enum GNUNET_GenericReturnValue | ||
36 | PABC_read_usr_ctx (char const *const user_name, | ||
37 | char const *const pp_name, | ||
38 | struct pabc_context const *const ctx, | ||
39 | struct pabc_public_parameters const *const | ||
40 | pp, | ||
41 | struct pabc_user_context **usr_ctx); | ||
diff --git a/src/reclaim/plugin_reclaim_credential_jwt.c b/src/reclaim/plugin_reclaim_credential_jwt.c index aac0a6ea5..e5dc90363 100644 --- a/src/reclaim/plugin_reclaim_credential_jwt.c +++ b/src/reclaim/plugin_reclaim_credential_jwt.c | |||
@@ -158,11 +158,10 @@ jwt_parse_attributes (void *cls, | |||
158 | struct GNUNET_RECLAIM_AttributeList *attrs; | 158 | struct GNUNET_RECLAIM_AttributeList *attrs; |
159 | char delim[] = "."; | 159 | char delim[] = "."; |
160 | char *val_str = NULL; | 160 | char *val_str = NULL; |
161 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n"); | ||
162 | char *decoded_jwt; | 161 | char *decoded_jwt; |
163 | char *tmp; | 162 | char *tmp; |
164 | json_t *json_val; | 163 | json_t *json_val; |
165 | json_error_t *json_err = NULL; | 164 | json_error_t json_err; |
166 | 165 | ||
167 | attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | 166 | attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); |
168 | 167 | ||
@@ -173,7 +172,7 @@ jwt_parse_attributes (void *cls, | |||
173 | (void **) &decoded_jwt); | 172 | (void **) &decoded_jwt); |
174 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded JWT: %s\n", decoded_jwt); | 173 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded JWT: %s\n", decoded_jwt); |
175 | GNUNET_assert (NULL != decoded_jwt); | 174 | GNUNET_assert (NULL != decoded_jwt); |
176 | json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err); | 175 | json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err); |
177 | GNUNET_free (decoded_jwt); | 176 | GNUNET_free (decoded_jwt); |
178 | const char *key; | 177 | const char *key; |
179 | const char *addr_key; | 178 | const char *addr_key; |
@@ -252,6 +251,8 @@ struct GNUNET_RECLAIM_AttributeList * | |||
252 | jwt_parse_attributes_c (void *cls, | 251 | jwt_parse_attributes_c (void *cls, |
253 | const struct GNUNET_RECLAIM_Credential *cred) | 252 | const struct GNUNET_RECLAIM_Credential *cred) |
254 | { | 253 | { |
254 | if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT) | ||
255 | return NULL; | ||
255 | return jwt_parse_attributes (cls, cred->data, cred->data_size); | 256 | return jwt_parse_attributes (cls, cred->data, cred->data_size); |
256 | } | 257 | } |
257 | 258 | ||
@@ -267,6 +268,8 @@ struct GNUNET_RECLAIM_AttributeList * | |||
267 | jwt_parse_attributes_p (void *cls, | 268 | jwt_parse_attributes_p (void *cls, |
268 | const struct GNUNET_RECLAIM_Presentation *cred) | 269 | const struct GNUNET_RECLAIM_Presentation *cred) |
269 | { | 270 | { |
271 | if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT) | ||
272 | return NULL; | ||
270 | return jwt_parse_attributes (cls, cred->data, cred->data_size); | 273 | return jwt_parse_attributes (cls, cred->data, cred->data_size); |
271 | } | 274 | } |
272 | 275 | ||
@@ -291,14 +294,14 @@ jwt_get_issuer (void *cls, | |||
291 | json_t *issuer_json; | 294 | json_t *issuer_json; |
292 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n"); | 295 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n"); |
293 | json_t *json_val; | 296 | json_t *json_val; |
294 | json_error_t *json_err = NULL; | 297 | json_error_t json_err; |
295 | 298 | ||
296 | jwt_string = GNUNET_strndup (data, data_size); | 299 | jwt_string = GNUNET_strndup (data, data_size); |
297 | jwt_body = strtok (jwt_string, delim); | 300 | jwt_body = strtok (jwt_string, delim); |
298 | jwt_body = strtok (NULL, delim); | 301 | jwt_body = strtok (NULL, delim); |
299 | GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), | 302 | GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), |
300 | (void **) &decoded_jwt); | 303 | (void **) &decoded_jwt); |
301 | json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err); | 304 | json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err); |
302 | GNUNET_free (decoded_jwt); | 305 | GNUNET_free (decoded_jwt); |
303 | GNUNET_free (jwt_string); | 306 | GNUNET_free (jwt_string); |
304 | if (NULL == json_val) | 307 | if (NULL == json_val) |
@@ -355,7 +358,7 @@ jwt_get_issuer_p (void *cls, | |||
355 | * @param cred the jwt credential | 358 | * @param cred the jwt credential |
356 | * @return a string, containing the isser | 359 | * @return a string, containing the isser |
357 | */ | 360 | */ |
358 | int | 361 | enum GNUNET_GenericReturnValue |
359 | jwt_get_expiration (void *cls, | 362 | jwt_get_expiration (void *cls, |
360 | const char *data, | 363 | const char *data, |
361 | size_t data_size, | 364 | size_t data_size, |
@@ -368,14 +371,14 @@ jwt_get_expiration (void *cls, | |||
368 | json_t *exp_json; | 371 | json_t *exp_json; |
369 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n"); | 372 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n"); |
370 | json_t *json_val; | 373 | json_t *json_val; |
371 | json_error_t *json_err = NULL; | 374 | json_error_t json_err; |
372 | 375 | ||
373 | jwt_string = GNUNET_strndup (data, data_size); | 376 | jwt_string = GNUNET_strndup (data, data_size); |
374 | jwt_body = strtok (jwt_string, delim); | 377 | jwt_body = strtok (jwt_string, delim); |
375 | jwt_body = strtok (NULL, delim); | 378 | jwt_body = strtok (NULL, delim); |
376 | GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), | 379 | GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), |
377 | (void **) &decoded_jwt); | 380 | (void **) &decoded_jwt); |
378 | json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err); | 381 | json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err); |
379 | GNUNET_free (decoded_jwt); | 382 | GNUNET_free (decoded_jwt); |
380 | GNUNET_free (jwt_string); | 383 | GNUNET_free (jwt_string); |
381 | if (NULL == json_val) | 384 | if (NULL == json_val) |
@@ -396,13 +399,15 @@ jwt_get_expiration (void *cls, | |||
396 | * | 399 | * |
397 | * @param cls the plugin | 400 | * @param cls the plugin |
398 | * @param cred the jwt credential | 401 | * @param cred the jwt credential |
399 | * @return a string, containing the isser | 402 | * @return the expirati |
400 | */ | 403 | */ |
401 | int | 404 | enum GNUNET_GenericReturnValue |
402 | jwt_get_expiration_c (void *cls, | 405 | jwt_get_expiration_c (void *cls, |
403 | const struct GNUNET_RECLAIM_Credential *cred, | 406 | const struct GNUNET_RECLAIM_Credential *cred, |
404 | struct GNUNET_TIME_Absolute *exp) | 407 | struct GNUNET_TIME_Absolute *exp) |
405 | { | 408 | { |
409 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type) | ||
410 | return GNUNET_NO; | ||
406 | return jwt_get_expiration (cls, cred->data, cred->data_size, exp); | 411 | return jwt_get_expiration (cls, cred->data, cred->data_size, exp); |
407 | } | 412 | } |
408 | 413 | ||
@@ -414,22 +419,23 @@ jwt_get_expiration_c (void *cls, | |||
414 | * @param cred the jwt credential | 419 | * @param cred the jwt credential |
415 | * @return a string, containing the isser | 420 | * @return a string, containing the isser |
416 | */ | 421 | */ |
417 | int | 422 | enum GNUNET_GenericReturnValue |
418 | jwt_get_expiration_p (void *cls, | 423 | jwt_get_expiration_p (void *cls, |
419 | const struct GNUNET_RECLAIM_Presentation *cred, | 424 | const struct GNUNET_RECLAIM_Presentation *cred, |
420 | struct GNUNET_TIME_Absolute *exp) | 425 | struct GNUNET_TIME_Absolute *exp) |
421 | { | 426 | { |
427 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type) | ||
428 | return GNUNET_NO; | ||
422 | return jwt_get_expiration (cls, cred->data, cred->data_size, exp); | 429 | return jwt_get_expiration (cls, cred->data, cred->data_size, exp); |
423 | } | 430 | } |
424 | 431 | ||
425 | 432 | ||
426 | int | 433 | enum GNUNET_GenericReturnValue |
427 | jwt_create_presentation (void *cls, | 434 | jwt_create_presentation (void *cls, |
428 | const struct GNUNET_RECLAIM_Credential *cred, | 435 | const struct GNUNET_RECLAIM_Credential *cred, |
429 | const struct GNUNET_RECLAIM_AttributeList *attrs, | 436 | const struct GNUNET_RECLAIM_AttributeList *attrs, |
430 | struct GNUNET_RECLAIM_Presentation **pres) | 437 | struct GNUNET_RECLAIM_Presentation **pres) |
431 | { | 438 | { |
432 | // FIXME sanity checks?? | ||
433 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type) | 439 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type) |
434 | return GNUNET_NO; | 440 | return GNUNET_NO; |
435 | *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT, | 441 | *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT, |
diff --git a/src/reclaim/plugin_reclaim_credential_pabc.c b/src/reclaim/plugin_reclaim_credential_pabc.c new file mode 100644 index 000000000..2f6b7b8c4 --- /dev/null +++ b/src/reclaim/plugin_reclaim_credential_pabc.c | |||
@@ -0,0 +1,639 @@ | |||
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 | */ | ||
45 | static char * | ||
46 | pabc_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 | */ | ||
73 | static int | ||
74 | pabc_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 | */ | ||
99 | static 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 | */ | ||
113 | static uint32_t | ||
114 | pabc_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 | */ | ||
133 | static const char * | ||
134 | pabc_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 | |||
147 | static void | ||
148 | inspect_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 attribue 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 | */ | ||
181 | struct GNUNET_RECLAIM_AttributeList * | ||
182 | pabc_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 | */ | ||
205 | struct GNUNET_RECLAIM_AttributeList * | ||
206 | pabc_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 | */ | ||
222 | struct GNUNET_RECLAIM_AttributeList * | ||
223 | pabc_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 | struct Finder | ||
232 | { | ||
233 | const char* target; | ||
234 | char *result; | ||
235 | }; | ||
236 | |||
237 | static void | ||
238 | find_attr (char const *const key, | ||
239 | char const *const value, | ||
240 | void *ctx) | ||
241 | { | ||
242 | struct Finder *fdr = ctx; | ||
243 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
244 | "Found `%s', looking for `%s'\n", | ||
245 | key, fdr->target); | ||
246 | if (0 == strcmp (key, fdr->target)) | ||
247 | fdr->result = GNUNET_strdup (value); | ||
248 | } | ||
249 | |||
250 | |||
251 | |||
252 | /** | ||
253 | * Parse a pabc and return an attribute value. | ||
254 | * | ||
255 | * @param cls the plugin | ||
256 | * @param data the pabc credential data | ||
257 | * @param data_size the pabc credential size | ||
258 | * @param skey the attribute key to look for. | ||
259 | * @return a string, containing the isser | ||
260 | */ | ||
261 | char * | ||
262 | pabc_get_attribute (void *cls, | ||
263 | const char *data, | ||
264 | size_t data_size, | ||
265 | const char *skey) | ||
266 | { | ||
267 | |||
268 | struct Finder fdr; | ||
269 | memset (&fdr, 0, sizeof (fdr)); | ||
270 | fdr.target = skey; | ||
271 | pabc_cred_inspect_credential (data, &find_attr, &fdr); | ||
272 | return fdr.result; | ||
273 | } | ||
274 | |||
275 | |||
276 | /** | ||
277 | * Parse a pabc and return the issuer | ||
278 | * | ||
279 | * @param cls the plugin | ||
280 | * @param cred the pabc credential | ||
281 | * @return a string, containing the isser | ||
282 | */ | ||
283 | char* | ||
284 | pabc_get_issuer (void *cls, | ||
285 | const char *data, | ||
286 | size_t data_size) | ||
287 | { | ||
288 | char *res; | ||
289 | if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (data, | ||
290 | "issuer", | ||
291 | &res)) | ||
292 | return NULL; | ||
293 | return res; | ||
294 | } | ||
295 | |||
296 | |||
297 | /** | ||
298 | * Parse a pabc and return the issuer | ||
299 | * | ||
300 | * @param cls the plugin | ||
301 | * @param cred the pabc credential | ||
302 | * @return a string, containing the isser | ||
303 | */ | ||
304 | char* | ||
305 | pabc_get_issuer (void *cls, | ||
306 | const char *data, | ||
307 | size_t data_size) | ||
308 | { | ||
309 | return pabc_get_attribute (cls, data, data_size, "issuer"); | ||
310 | } | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Parse a pabc and return the issuer | ||
315 | * | ||
316 | * @param cls the plugin | ||
317 | * @param cred the pabc credential | ||
318 | * @return a string, containing the isser | ||
319 | */ | ||
320 | char * | ||
321 | pabc_get_issuer_c (void *cls, | ||
322 | const struct GNUNET_RECLAIM_Credential *cred) | ||
323 | { | ||
324 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type) | ||
325 | return NULL; | ||
326 | return pabc_get_issuer (cls, cred->data, cred->data_size); | ||
327 | } | ||
328 | |||
329 | |||
330 | /** | ||
331 | * Parse a pabc and return the issuer | ||
332 | * | ||
333 | * @param cls the plugin | ||
334 | * @param cred the pabc credential | ||
335 | * @return a string, containing the isser | ||
336 | */ | ||
337 | char * | ||
338 | pabc_get_issuer_p (void *cls, | ||
339 | const struct GNUNET_RECLAIM_Presentation *cred) | ||
340 | { | ||
341 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type) | ||
342 | return NULL; | ||
343 | return pabc_get_issuer (cls, cred->data, cred->data_size); | ||
344 | } | ||
345 | |||
346 | |||
347 | /** | ||
348 | * Parse a pabc and return the expiration | ||
349 | * | ||
350 | * @param cls the plugin | ||
351 | * @param cred the pabc credential | ||
352 | * @return a string, containing the isser | ||
353 | */ | ||
354 | int | ||
355 | pabc_get_expiration (void *cls, | ||
356 | const char *data, | ||
357 | size_t data_size, | ||
358 | struct GNUNET_TIME_Absolute *exp) | ||
359 | { | ||
360 | json_t *json_root; | ||
361 | json_t *json_attrs; | ||
362 | json_t *value; | ||
363 | json_t *exp_j; | ||
364 | json_error_t *json_err = NULL; | ||
365 | const char*key; | ||
366 | |||
367 | json_root = json_loads (data, JSON_DECODE_ANY, json_err); | ||
368 | if ((NULL == json_root) || | ||
369 | (! json_is_object (json_root))) | ||
370 | { | ||
371 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
372 | "Unable to retrive expiration from credential\n"); | ||
373 | return GNUNET_SYSERR; | ||
374 | } | ||
375 | |||
376 | if (1 != sscanf (exp_str, "%llu", &exp_i)) | ||
377 | { | ||
378 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
379 | "Invalid expiration `%s'\n", exp_str); | ||
380 | GNUNET_free (exp_str); | ||
381 | return GNUNET_SYSERR; | ||
382 | } | ||
383 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
384 | "Converted expiration string `%s' to %llu", | ||
385 | exp_str, exp_i); | ||
386 | |||
387 | GNUNET_free (exp_str); | ||
388 | exp->abs_value_us = exp_i * 1000 * 1000; | ||
389 | return GNUNET_OK; | ||
390 | } | ||
391 | |||
392 | |||
393 | /** | ||
394 | * Parse a pabc and return the expiration | ||
395 | * | ||
396 | * @param cls the plugin | ||
397 | * @param cred the pabc credential | ||
398 | * @return a string, containing the isser | ||
399 | */ | ||
400 | enum GNUNET_GenericReturnValue | ||
401 | pabc_get_expiration_c (void *cls, | ||
402 | const struct GNUNET_RECLAIM_Credential *cred, | ||
403 | struct GNUNET_TIME_Absolute *exp) | ||
404 | { | ||
405 | if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC) | ||
406 | return GNUNET_NO; | ||
407 | return pabc_get_expiration (cls, cred->data, cred->data_size, exp); | ||
408 | } | ||
409 | |||
410 | |||
411 | /** | ||
412 | * Parse a pabc and return the expiration | ||
413 | * | ||
414 | * @param cls the plugin | ||
415 | * @param cred the pabc credential | ||
416 | * @return a string, containing the isser | ||
417 | */ | ||
418 | enum GNUNET_GenericReturnValue | ||
419 | pabc_get_expiration_p (void *cls, | ||
420 | const struct GNUNET_RECLAIM_Presentation *cred, | ||
421 | struct GNUNET_TIME_Absolute *exp) | ||
422 | { | ||
423 | if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC) | ||
424 | return GNUNET_NO; | ||
425 | return pabc_get_expiration (cls, cred->data, cred->data_size, exp); | ||
426 | } | ||
427 | |||
428 | |||
429 | int | ||
430 | pabc_create_presentation (void *cls, | ||
431 | const struct GNUNET_RECLAIM_Credential *credential, | ||
432 | const struct GNUNET_RECLAIM_AttributeList *attrs, | ||
433 | struct GNUNET_RECLAIM_Presentation **pres) | ||
434 | { | ||
435 | struct pabc_context *ctx = NULL; | ||
436 | struct pabc_user_context *usr_ctx = NULL; | ||
437 | struct pabc_public_parameters *pp = NULL; | ||
438 | struct pabc_credential *cred = NULL; | ||
439 | struct pabc_blinded_proof *proof = NULL; | ||
440 | struct GNUNET_RECLAIM_AttributeListEntry *ale; | ||
441 | char *issuer; | ||
442 | char *subject; | ||
443 | enum pabc_status status; | ||
444 | |||
445 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != credential->type) | ||
446 | return GNUNET_NO; | ||
447 | |||
448 | |||
449 | PABC_ASSERT (pabc_new_ctx (&ctx)); | ||
450 | issuer = pabc_get_issuer_c (cls, credential); | ||
451 | if (NULL == issuer) | ||
452 | { | ||
453 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
454 | "No issuer found in credential\n"); | ||
455 | pabc_free_ctx (&ctx); | ||
456 | return GNUNET_SYSERR; | ||
457 | } | ||
458 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
459 | "Got issuer for credential: %s\n", issuer); | ||
460 | status = PABC_load_public_parameters (ctx, issuer, &pp); | ||
461 | if (status != PABC_OK) | ||
462 | { | ||
463 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
464 | "Failed to read public parameters.\n"); | ||
465 | pabc_free_ctx (&ctx); | ||
466 | GNUNET_free (issuer); | ||
467 | return GNUNET_SYSERR; | ||
468 | } | ||
469 | if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (credential->data, | ||
470 | "subject", | ||
471 | &subject)) | ||
472 | { | ||
473 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
474 | "Failed to get subject.\n"); | ||
475 | pabc_free_ctx (&ctx); | ||
476 | GNUNET_free (issuer); | ||
477 | return GNUNET_SYSERR; | ||
478 | } | ||
479 | status = PABC_read_usr_ctx (subject, issuer, ctx, pp, &usr_ctx); | ||
480 | GNUNET_free (issuer); | ||
481 | GNUNET_free (subject); | ||
482 | if (PABC_OK != status) | ||
483 | { | ||
484 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
485 | "Failed to read user context.\n"); | ||
486 | pabc_free_public_parameters (ctx, &pp); | ||
487 | return GNUNET_SYSERR; | ||
488 | } | ||
489 | |||
490 | status = pabc_new_credential (ctx, pp, &cred); | ||
491 | if (status != PABC_OK) | ||
492 | { | ||
493 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
494 | "Failed to allocate credential.\n"); | ||
495 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
496 | pabc_free_public_parameters (ctx, &pp); | ||
497 | return GNUNET_SYSERR; | ||
498 | } | ||
499 | |||
500 | status = pabc_decode_credential (ctx, pp, cred, credential->data); | ||
501 | if (status != PABC_OK) | ||
502 | { | ||
503 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
504 | "Failed to decode credential.\n"); | ||
505 | pabc_free_credential (ctx, pp, &cred); | ||
506 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
507 | pabc_free_public_parameters (ctx, &pp); | ||
508 | return GNUNET_SYSERR; | ||
509 | } | ||
510 | |||
511 | status = pabc_new_proof (ctx, pp, &proof); | ||
512 | if (status != PABC_OK) | ||
513 | { | ||
514 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
515 | "Failed to allocate proof.\n"); | ||
516 | pabc_free_credential (ctx, pp, &cred); | ||
517 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
518 | pabc_free_public_parameters (ctx, &pp); | ||
519 | return GNUNET_SYSERR; | ||
520 | } | ||
521 | |||
522 | // now we can parse the attributes to disclose and configure the proof | ||
523 | for (ale = attrs->list_head; NULL != ale; ale = ale->next) | ||
524 | { | ||
525 | status = pabc_set_disclosure_by_attribute_name (ctx, pp, proof, | ||
526 | ale->attribute->name, | ||
527 | PABC_DISCLOSED, cred); | ||
528 | if (status != PABC_OK) | ||
529 | { | ||
530 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
531 | "Failed to configure proof.\n"); | ||
532 | pabc_free_credential (ctx, pp, &cred); | ||
533 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
534 | pabc_free_public_parameters (ctx, &pp); | ||
535 | return GNUNET_SYSERR; | ||
536 | } | ||
537 | } | ||
538 | |||
539 | // and finally -> sign the proof | ||
540 | status = pabc_gen_proof (ctx, usr_ctx, pp, proof, cred); | ||
541 | if (status != PABC_OK) | ||
542 | { | ||
543 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
544 | "Failed to sign proof.\n"); | ||
545 | pabc_free_proof (ctx, pp, &proof); | ||
546 | pabc_free_credential (ctx, pp, &cred); | ||
547 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
548 | pabc_free_public_parameters (ctx, &pp); | ||
549 | return GNUNET_SYSERR; | ||
550 | } | ||
551 | // print the result | ||
552 | char *json = NULL; | ||
553 | char *ppid = NULL; | ||
554 | char *userid = NULL; | ||
555 | GNUNET_assert (PABC_OK == pabc_cred_get_userid_from_cred (credential->data, | ||
556 | &userid)); | ||
557 | GNUNET_assert (PABC_OK == pabc_cred_get_ppid_from_cred (credential->data, | ||
558 | &ppid)); | ||
559 | pabc_cred_encode_proof (ctx, pp, proof, userid, ppid, &json); | ||
560 | GNUNET_free (ppid); | ||
561 | GNUNET_free (userid); | ||
562 | if (PABC_OK != status) | ||
563 | { | ||
564 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
565 | "Failed to serialize proof.\n"); | ||
566 | pabc_free_proof (ctx, pp, &proof); | ||
567 | pabc_free_credential (ctx, pp, &cred); | ||
568 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
569 | pabc_free_public_parameters (ctx, &pp); | ||
570 | return GNUNET_SYSERR; | ||
571 | } | ||
572 | char *json_enc; | ||
573 | GNUNET_STRINGS_base64_encode (json, | ||
574 | strlen (json) + 1, | ||
575 | &json_enc); | ||
576 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
577 | "Presentation: %s\n", json_enc); | ||
578 | // clean up | ||
579 | *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC, | ||
580 | json_enc, | ||
581 | strlen (json_enc) + 1); | ||
582 | GNUNET_free (json_enc); | ||
583 | PABC_FREE_NULL (json); | ||
584 | pabc_free_proof (ctx, pp, &proof); | ||
585 | pabc_free_credential (ctx, pp, &cred); | ||
586 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
587 | pabc_free_public_parameters (ctx, &pp); | ||
588 | return GNUNET_OK; | ||
589 | } | ||
590 | |||
591 | |||
592 | /** | ||
593 | * Entry point for the plugin. | ||
594 | * | ||
595 | * @param cls NULL | ||
596 | * @return the exported block API | ||
597 | */ | ||
598 | void * | ||
599 | libgnunet_plugin_reclaim_credential_pabc_init (void *cls) | ||
600 | { | ||
601 | struct GNUNET_RECLAIM_CredentialPluginFunctions *api; | ||
602 | |||
603 | api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions); | ||
604 | api->value_to_string = &pabc_value_to_string; | ||
605 | api->string_to_value = &pabc_string_to_value; | ||
606 | api->typename_to_number = &pabc_typename_to_number; | ||
607 | api->number_to_typename = &pabc_number_to_typename; | ||
608 | api->get_attributes = &pabc_parse_attributes_c; | ||
609 | api->get_issuer = &pabc_get_issuer_c; | ||
610 | api->get_expiration = &pabc_get_expiration_c; | ||
611 | api->value_to_string_p = &pabc_value_to_string; | ||
612 | api->string_to_value_p = &pabc_string_to_value; | ||
613 | api->typename_to_number_p = &pabc_typename_to_number; | ||
614 | api->number_to_typename_p = &pabc_number_to_typename; | ||
615 | api->get_attributes_p = &pabc_parse_attributes_p; | ||
616 | api->get_issuer_p = &pabc_get_issuer_p; | ||
617 | api->get_expiration_p = &pabc_get_expiration_p; | ||
618 | api->create_presentation = &pabc_create_presentation; | ||
619 | return api; | ||
620 | } | ||
621 | |||
622 | |||
623 | /** | ||
624 | * Exit point from the plugin. | ||
625 | * | ||
626 | * @param cls the return value from #libgnunet_plugin_block_test_init() | ||
627 | * @return NULL | ||
628 | */ | ||
629 | void * | ||
630 | libgnunet_plugin_reclaim_credential_pabc_done (void *cls) | ||
631 | { | ||
632 | struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls; | ||
633 | |||
634 | GNUNET_free (api); | ||
635 | return NULL; | ||
636 | } | ||
637 | |||
638 | |||
639 | /* end of plugin_reclaim_credential_type_pabc.c */ | ||
diff --git a/src/reclaim/plugin_rest_pabc.c b/src/reclaim/plugin_rest_pabc.c new file mode 100644 index 000000000..6603fb888 --- /dev/null +++ b/src/reclaim/plugin_rest_pabc.c | |||
@@ -0,0 +1,666 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @author Martin Schanzenbach | ||
22 | * @file reclaim/plugin_rest_pabc.c | ||
23 | * @brief GNUnet pabc REST plugin | ||
24 | * | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "microhttpd.h" | ||
28 | #include <inttypes.h> | ||
29 | #include <jansson.h> | ||
30 | #include <pabc/pabc.h> | ||
31 | #include "gnunet_reclaim_lib.h" | ||
32 | #include "gnunet_reclaim_service.h" | ||
33 | #include "gnunet_rest_lib.h" | ||
34 | #include "gnunet_rest_plugin.h" | ||
35 | #include "gnunet_signatures.h" | ||
36 | #include "pabc_helper.h" | ||
37 | |||
38 | /** | ||
39 | * REST root namespace | ||
40 | */ | ||
41 | #define GNUNET_REST_API_NS_PABC "/pabc" | ||
42 | |||
43 | /** | ||
44 | * Credential request endpoint | ||
45 | */ | ||
46 | #define GNUNET_REST_API_NS_PABC_CR "/pabc/cr" | ||
47 | |||
48 | /** | ||
49 | * The configuration handle | ||
50 | */ | ||
51 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
52 | |||
53 | /** | ||
54 | * HTTP methods allows for this plugin | ||
55 | */ | ||
56 | static char *allow_methods; | ||
57 | |||
58 | /** | ||
59 | * @brief struct returned by the initialization function of the plugin | ||
60 | */ | ||
61 | struct Plugin | ||
62 | { | ||
63 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
64 | }; | ||
65 | |||
66 | |||
67 | struct RequestHandle | ||
68 | { | ||
69 | /** | ||
70 | * DLL | ||
71 | */ | ||
72 | struct RequestHandle *next; | ||
73 | |||
74 | /** | ||
75 | * DLL | ||
76 | */ | ||
77 | struct RequestHandle *prev; | ||
78 | |||
79 | /** | ||
80 | * Rest connection | ||
81 | */ | ||
82 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
83 | |||
84 | /** | ||
85 | * Desired timeout for the lookup (default is no timeout). | ||
86 | */ | ||
87 | struct GNUNET_TIME_Relative timeout; | ||
88 | |||
89 | /** | ||
90 | * ID of a task associated with the resolution process. | ||
91 | */ | ||
92 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
93 | |||
94 | /** | ||
95 | * The plugin result processor | ||
96 | */ | ||
97 | GNUNET_REST_ResultProcessor proc; | ||
98 | |||
99 | /** | ||
100 | * The closure of the result processor | ||
101 | */ | ||
102 | void *proc_cls; | ||
103 | |||
104 | /** | ||
105 | * The url | ||
106 | */ | ||
107 | char *url; | ||
108 | |||
109 | /** | ||
110 | * Error response message | ||
111 | */ | ||
112 | char *emsg; | ||
113 | |||
114 | /** | ||
115 | * Reponse code | ||
116 | */ | ||
117 | int response_code; | ||
118 | |||
119 | /** | ||
120 | * Response object | ||
121 | */ | ||
122 | json_t *resp_object; | ||
123 | }; | ||
124 | |||
125 | /** | ||
126 | * DLL | ||
127 | */ | ||
128 | static struct RequestHandle *requests_head; | ||
129 | |||
130 | /** | ||
131 | * DLL | ||
132 | */ | ||
133 | static struct RequestHandle *requests_tail; | ||
134 | |||
135 | |||
136 | /** | ||
137 | * Cleanup lookup handle | ||
138 | * @param handle Handle to clean up | ||
139 | */ | ||
140 | static void | ||
141 | cleanup_handle (void *cls) | ||
142 | { | ||
143 | struct RequestHandle *handle = cls; | ||
144 | |||
145 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); | ||
146 | if (NULL != handle->resp_object) | ||
147 | json_decref (handle->resp_object); | ||
148 | if (NULL != handle->timeout_task) | ||
149 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
150 | if (NULL != handle->url) | ||
151 | GNUNET_free (handle->url); | ||
152 | if (NULL != handle->emsg) | ||
153 | GNUNET_free (handle->emsg); | ||
154 | GNUNET_CONTAINER_DLL_remove (requests_head, | ||
155 | requests_tail, | ||
156 | handle); | ||
157 | GNUNET_free (handle); | ||
158 | } | ||
159 | |||
160 | |||
161 | /** | ||
162 | * Task run on error, sends error message. Cleans up everything. | ||
163 | * | ||
164 | * @param cls the `struct RequestHandle` | ||
165 | */ | ||
166 | static void | ||
167 | do_error (void *cls) | ||
168 | { | ||
169 | struct RequestHandle *handle = cls; | ||
170 | struct MHD_Response *resp; | ||
171 | char *json_error; | ||
172 | |||
173 | GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", handle->emsg); | ||
174 | if (0 == handle->response_code) | ||
175 | { | ||
176 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
177 | } | ||
178 | resp = GNUNET_REST_create_response (json_error); | ||
179 | MHD_add_response_header (resp, "Content-Type", "application/json"); | ||
180 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
181 | cleanup_handle (handle); | ||
182 | GNUNET_free (json_error); | ||
183 | } | ||
184 | |||
185 | |||
186 | /** | ||
187 | * Task run on timeout, sends error message. Cleans up everything. | ||
188 | * | ||
189 | * @param cls the `struct RequestHandle` | ||
190 | */ | ||
191 | static void | ||
192 | do_timeout (void *cls) | ||
193 | { | ||
194 | struct RequestHandle *handle = cls; | ||
195 | |||
196 | handle->timeout_task = NULL; | ||
197 | do_error (handle); | ||
198 | } | ||
199 | |||
200 | |||
201 | static void | ||
202 | return_response (void *cls) | ||
203 | { | ||
204 | char *result_str; | ||
205 | struct RequestHandle *handle = cls; | ||
206 | struct MHD_Response *resp; | ||
207 | |||
208 | result_str = json_dumps (handle->resp_object, 0); | ||
209 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
210 | resp = GNUNET_REST_create_response (result_str); | ||
211 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); | ||
212 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
213 | GNUNET_free (result_str); | ||
214 | cleanup_handle (handle); | ||
215 | } | ||
216 | |||
217 | |||
218 | static enum pabc_status | ||
219 | set_attributes_from_idtoken (const struct pabc_context *ctx, | ||
220 | const struct pabc_public_parameters *pp, | ||
221 | struct pabc_user_context *usr_ctx, | ||
222 | const char *id_token) | ||
223 | { | ||
224 | json_t *payload_json; | ||
225 | json_t *value; | ||
226 | json_error_t json_err; | ||
227 | const char *key; | ||
228 | const char *jwt_body; | ||
229 | char *decoded_jwt; | ||
230 | char delim[] = "."; | ||
231 | char *jwt_string; | ||
232 | const char *pabc_key; | ||
233 | enum pabc_status status; | ||
234 | |||
235 | // FIXME parse JWT | ||
236 | jwt_string = GNUNET_strndup (id_token, strlen (id_token)); | ||
237 | jwt_body = strtok (jwt_string, delim); | ||
238 | jwt_body = strtok (NULL, delim); | ||
239 | GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), | ||
240 | (void **) &decoded_jwt); | ||
241 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded ID Token: %s\n", decoded_jwt); | ||
242 | payload_json = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err); | ||
243 | GNUNET_free (decoded_jwt); | ||
244 | |||
245 | json_object_foreach (payload_json, key, value) | ||
246 | { | ||
247 | pabc_key = key; | ||
248 | if (0 == strcmp ("iss", key)) | ||
249 | pabc_key = "issuer"; // rename | ||
250 | if (0 == strcmp ("sub", key)) | ||
251 | pabc_key = "subject"; // rename | ||
252 | if (0 == strcmp ("jti", key)) | ||
253 | continue; | ||
254 | if (0 == strcmp ("exp", key)) | ||
255 | pabc_key = "expiration"; // rename | ||
256 | if (0 == strcmp ("iat", key)) | ||
257 | continue; | ||
258 | if (0 == strcmp ("nbf", key)) | ||
259 | continue; | ||
260 | if (0 == strcmp ("aud", key)) | ||
261 | continue; | ||
262 | char *tmp_val; | ||
263 | if (json_is_string (value)) | ||
264 | tmp_val = GNUNET_strdup (json_string_value (value)); | ||
265 | else | ||
266 | tmp_val = json_dumps (value, JSON_ENCODE_ANY); | ||
267 | if (NULL == tmp_val) | ||
268 | { | ||
269 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
270 | "Unable to encode JSON value for `%s'\n", key); | ||
271 | continue; | ||
272 | } | ||
273 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
274 | "Setting `%s' to `%s'\n", key, tmp_val); | ||
275 | status = pabc_set_attribute_value_by_name (ctx, pp, usr_ctx, | ||
276 | pabc_key, | ||
277 | tmp_val); | ||
278 | GNUNET_free (tmp_val); | ||
279 | if (PABC_OK != status) | ||
280 | { | ||
281 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
282 | "Failed to set attribute `%s'.\n", key); | ||
283 | } | ||
284 | } | ||
285 | return PABC_OK; | ||
286 | } | ||
287 | |||
288 | |||
289 | static enum GNUNET_GenericReturnValue | ||
290 | setup_new_user_context (struct pabc_context *ctx, | ||
291 | struct pabc_public_parameters *pp, | ||
292 | struct pabc_user_context **usr_ctx) | ||
293 | { | ||
294 | if (PABC_OK != pabc_new_user_context (ctx, pp, usr_ctx)) | ||
295 | return GNUNET_SYSERR; | ||
296 | |||
297 | if (PABC_OK != pabc_populate_user_context (ctx, *usr_ctx)) | ||
298 | { | ||
299 | pabc_free_user_context (ctx, pp, usr_ctx); | ||
300 | return GNUNET_SYSERR; | ||
301 | } | ||
302 | return GNUNET_OK; | ||
303 | } | ||
304 | |||
305 | |||
306 | static void | ||
307 | cr_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
308 | const char *url, | ||
309 | void *cls) | ||
310 | { | ||
311 | struct RequestHandle *handle = cls; | ||
312 | char term_data[handle->rest_handle->data_size + 1]; | ||
313 | char *response_str; | ||
314 | json_t *data_json; | ||
315 | json_t *nonce_json; | ||
316 | json_t *pp_json; | ||
317 | json_t *idtoken_json; | ||
318 | json_t *iss_json; | ||
319 | json_t *identity_json; | ||
320 | json_error_t err; | ||
321 | struct pabc_public_parameters *pp = NULL; | ||
322 | struct pabc_context *ctx = NULL; | ||
323 | struct pabc_user_context *usr_ctx = NULL; | ||
324 | struct pabc_credential_request *cr = NULL; | ||
325 | struct pabc_nonce *nonce = NULL; | ||
326 | enum pabc_status status; | ||
327 | |||
328 | |||
329 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
330 | "Credential request...\n"); | ||
331 | |||
332 | if (0 >= handle->rest_handle->data_size) | ||
333 | { | ||
334 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | term_data[handle->rest_handle->data_size] = '\0'; | ||
339 | GNUNET_memcpy (term_data, | ||
340 | handle->rest_handle->data, | ||
341 | handle->rest_handle->data_size); | ||
342 | data_json = json_loads (term_data, JSON_DECODE_ANY, &err); | ||
343 | if (NULL == data_json) | ||
344 | { | ||
345 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
346 | "Unable to parse %s\n", term_data); | ||
347 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
348 | return; | ||
349 | } | ||
350 | if (! json_is_object (data_json)) | ||
351 | { | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
353 | "Unable to parse %s\n", term_data); | ||
354 | json_decref (data_json); | ||
355 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
356 | return; | ||
357 | } | ||
358 | |||
359 | nonce_json = json_object_get (data_json, "nonce"); | ||
360 | if (NULL == nonce_json) | ||
361 | { | ||
362 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
363 | "Unable to parse nonce\n"); | ||
364 | json_decref (data_json); | ||
365 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
366 | return; | ||
367 | } | ||
368 | iss_json = json_object_get (data_json, "issuer"); | ||
369 | if (NULL == iss_json) | ||
370 | { | ||
371 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
372 | "Unable to parse issuer\n"); | ||
373 | json_decref (data_json); | ||
374 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
375 | return; | ||
376 | } | ||
377 | identity_json = json_object_get (data_json, "identity"); | ||
378 | if (NULL == identity_json) | ||
379 | { | ||
380 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
381 | "Unable to parse identity\n"); | ||
382 | json_decref (data_json); | ||
383 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
384 | return; | ||
385 | } | ||
386 | idtoken_json = json_object_get (data_json, "id_token"); | ||
387 | if (NULL == idtoken_json) | ||
388 | { | ||
389 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
390 | "Unable to parse id_token\n"); | ||
391 | json_decref (data_json); | ||
392 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
393 | return; | ||
394 | } | ||
395 | pp_json = json_object_get (data_json, "public_params"); | ||
396 | if (NULL == pp_json) | ||
397 | { | ||
398 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
399 | "Unable to parse public parameters\n"); | ||
400 | json_decref (data_json); | ||
401 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
402 | return; | ||
403 | } | ||
404 | |||
405 | PABC_ASSERT (pabc_new_ctx (&ctx)); | ||
406 | char *pp_str = json_dumps (pp_json, JSON_ENCODE_ANY); | ||
407 | status = pabc_decode_and_new_public_parameters (ctx, | ||
408 | &pp, | ||
409 | pp_str); | ||
410 | char *ppid; | ||
411 | GNUNET_assert (PABC_OK == pabc_cred_get_ppid_from_pp (pp_str, &ppid)); | ||
412 | GNUNET_free (pp_str); | ||
413 | if (status != PABC_OK) | ||
414 | { | ||
415 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
416 | "Failed to read public parameters: %s\n", | ||
417 | pp_str); | ||
418 | json_decref (data_json); | ||
419 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
420 | return; | ||
421 | } | ||
422 | // (Over)write parameters | ||
423 | status = PABC_write_public_parameters (json_string_value (iss_json), | ||
424 | pp); | ||
425 | if (status != PABC_OK) | ||
426 | { | ||
427 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
428 | "Failed to write public parameters.\n"); | ||
429 | json_decref (data_json); | ||
430 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
431 | return; | ||
432 | } | ||
433 | status = PABC_read_usr_ctx (json_string_value (identity_json), | ||
434 | json_string_value (iss_json), | ||
435 | ctx, pp, &usr_ctx); | ||
436 | if (PABC_OK != status) | ||
437 | { | ||
438 | if (GNUNET_OK != setup_new_user_context (ctx, pp, &usr_ctx)) | ||
439 | { | ||
440 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup user context.\n"); | ||
441 | pabc_free_public_parameters (ctx, &pp); | ||
442 | json_decref (data_json); | ||
443 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
444 | return; | ||
445 | } | ||
446 | PABC_write_usr_ctx (json_string_value (identity_json), | ||
447 | json_string_value (iss_json), | ||
448 | ctx, pp, usr_ctx); | ||
449 | } | ||
450 | |||
451 | // Set attributes from JWT to context | ||
452 | status = set_attributes_from_idtoken (ctx, | ||
453 | pp, | ||
454 | usr_ctx, | ||
455 | json_string_value (idtoken_json)); | ||
456 | if (status != PABC_OK) | ||
457 | { | ||
458 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to set attributes.\n"); | ||
459 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
460 | pabc_free_public_parameters (ctx, &pp); | ||
461 | json_decref (data_json); | ||
462 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
463 | return; | ||
464 | } | ||
465 | |||
466 | |||
467 | // nonce | ||
468 | status = pabc_new_nonce (ctx, &nonce); | ||
469 | if (status != PABC_OK) | ||
470 | { | ||
471 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to allocate nonce.\n"); | ||
472 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
473 | pabc_free_public_parameters (ctx, &pp); | ||
474 | json_decref (data_json); | ||
475 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
476 | return; | ||
477 | } | ||
478 | char *nonce_str = json_dumps (nonce_json, JSON_ENCODE_ANY); | ||
479 | status = pabc_decode_nonce (ctx, nonce, nonce_str); | ||
480 | if (status != PABC_OK) | ||
481 | { | ||
482 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to decode nonce.\n"); | ||
483 | pabc_free_nonce (ctx, &nonce); | ||
484 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
485 | pabc_free_public_parameters (ctx, &pp); | ||
486 | json_decref (data_json); | ||
487 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | // cr | ||
492 | status = pabc_new_credential_request (ctx, pp, &cr); | ||
493 | if (PABC_OK != status) | ||
494 | { | ||
495 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to allocate cr.\n"); | ||
496 | pabc_free_nonce (ctx, &nonce); | ||
497 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
498 | pabc_free_public_parameters (ctx, &pp); | ||
499 | json_decref (data_json); | ||
500 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | status = pabc_gen_credential_request (ctx, pp, usr_ctx, nonce, cr); | ||
505 | if (PABC_OK != status) | ||
506 | { | ||
507 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to generate cr.\n"); | ||
508 | pabc_free_nonce (ctx, &nonce); | ||
509 | pabc_free_credential_request (ctx, pp, &cr); | ||
510 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
511 | pabc_free_public_parameters (ctx, &pp); | ||
512 | json_decref (data_json); | ||
513 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
514 | return; | ||
515 | } | ||
516 | handle->resp_object = json_object (); | ||
517 | GNUNET_assert (PABC_OK == pabc_cred_encode_cr (ctx, pp, cr, | ||
518 | json_string_value ( | ||
519 | identity_json), | ||
520 | ppid, &response_str)); | ||
521 | if (PABC_OK != status) | ||
522 | { | ||
523 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to serialize cr.\n"); | ||
524 | pabc_free_nonce (ctx, &nonce); | ||
525 | pabc_free_credential_request (ctx, pp, &cr); | ||
526 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
527 | pabc_free_public_parameters (ctx, &pp); | ||
528 | json_decref (data_json); | ||
529 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
530 | return; | ||
531 | } | ||
532 | json_decref (handle->resp_object); | ||
533 | handle->resp_object = json_loads (response_str, JSON_DECODE_ANY, &err); | ||
534 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", response_str); | ||
535 | GNUNET_free (response_str); | ||
536 | |||
537 | // clean up | ||
538 | pabc_free_nonce (ctx, &nonce); | ||
539 | pabc_free_credential_request (ctx, pp, &cr); | ||
540 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
541 | pabc_free_public_parameters (ctx, &pp); | ||
542 | GNUNET_SCHEDULER_add_now (&return_response, handle); | ||
543 | json_decref (data_json); | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Respond to OPTIONS request | ||
549 | * | ||
550 | * @param con_handle the connection handle | ||
551 | * @param url the url | ||
552 | * @param cls the RequestHandle | ||
553 | */ | ||
554 | static void | ||
555 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
556 | const char *url, | ||
557 | void *cls) | ||
558 | { | ||
559 | struct MHD_Response *resp; | ||
560 | struct RequestHandle *handle = cls; | ||
561 | |||
562 | // For now, independent of path return all options | ||
563 | resp = GNUNET_REST_create_response (NULL); | ||
564 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); | ||
565 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
566 | cleanup_handle (handle); | ||
567 | return; | ||
568 | } | ||
569 | |||
570 | |||
571 | static enum GNUNET_GenericReturnValue | ||
572 | rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | ||
573 | GNUNET_REST_ResultProcessor proc, | ||
574 | void *proc_cls) | ||
575 | { | ||
576 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
577 | struct GNUNET_REST_RequestHandlerError err; | ||
578 | static const struct GNUNET_REST_RequestHandler handlers[] = { | ||
579 | {MHD_HTTP_METHOD_POST, | ||
580 | GNUNET_REST_API_NS_PABC_CR, &cr_cont }, | ||
581 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PABC, &options_cont }, | ||
582 | GNUNET_REST_HANDLER_END | ||
583 | }; | ||
584 | |||
585 | handle->response_code = 0; | ||
586 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
587 | handle->proc_cls = proc_cls; | ||
588 | handle->proc = proc; | ||
589 | handle->rest_handle = rest_handle; | ||
590 | |||
591 | handle->url = GNUNET_strdup (rest_handle->url); | ||
592 | if (handle->url[strlen (handle->url) - 1] == '/') | ||
593 | handle->url[strlen (handle->url) - 1] = '\0'; | ||
594 | handle->timeout_task = | ||
595 | GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle); | ||
596 | GNUNET_CONTAINER_DLL_insert (requests_head, | ||
597 | requests_tail, | ||
598 | handle); | ||
599 | if (GNUNET_NO == | ||
600 | GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) | ||
601 | { | ||
602 | cleanup_handle (handle); | ||
603 | return GNUNET_NO; | ||
604 | } | ||
605 | |||
606 | return GNUNET_YES; | ||
607 | } | ||
608 | |||
609 | |||
610 | /** | ||
611 | * Entry point for the plugin. | ||
612 | * | ||
613 | * @param cls Config info | ||
614 | * @return NULL on error, otherwise the plugin context | ||
615 | */ | ||
616 | void * | ||
617 | libgnunet_plugin_rest_pabc_init (void *cls) | ||
618 | { | ||
619 | static struct Plugin plugin; | ||
620 | struct GNUNET_REST_Plugin *api; | ||
621 | |||
622 | cfg = cls; | ||
623 | if (NULL != plugin.cfg) | ||
624 | return NULL; /* can only initialize once! */ | ||
625 | memset (&plugin, 0, sizeof(struct Plugin)); | ||
626 | plugin.cfg = cfg; | ||
627 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
628 | api->cls = &plugin; | ||
629 | api->name = GNUNET_REST_API_NS_PABC; | ||
630 | api->process_request = &rest_identity_process_request; | ||
631 | GNUNET_asprintf (&allow_methods, | ||
632 | "%s, %s", | ||
633 | MHD_HTTP_METHOD_POST, | ||
634 | MHD_HTTP_METHOD_OPTIONS); | ||
635 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
636 | _ ("Identity Provider REST API initialized\n")); | ||
637 | return api; | ||
638 | } | ||
639 | |||
640 | |||
641 | /** | ||
642 | * Exit point from the plugin. | ||
643 | * | ||
644 | * @param cls the plugin context (as returned by "init") | ||
645 | * @return always NULL | ||
646 | */ | ||
647 | void * | ||
648 | libgnunet_plugin_rest_reclaim_done (void *cls) | ||
649 | { | ||
650 | struct GNUNET_REST_Plugin *api = cls; | ||
651 | struct Plugin *plugin = api->cls; | ||
652 | struct RequestHandle *request; | ||
653 | |||
654 | plugin->cfg = NULL; | ||
655 | while (NULL != (request = requests_head)) | ||
656 | do_error (request); | ||
657 | |||
658 | GNUNET_free (allow_methods); | ||
659 | GNUNET_free (api); | ||
660 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
661 | "PABC REST plugin is finished\n"); | ||
662 | return NULL; | ||
663 | } | ||
664 | |||
665 | |||
666 | /* end of plugin_rest_reclaim.c */ | ||
diff --git a/src/reclaim/reclaim_credential.c b/src/reclaim/reclaim_credential.c index c8c0d397c..da5cee988 100644 --- a/src/reclaim/reclaim_credential.c +++ b/src/reclaim/reclaim_credential.c | |||
@@ -1033,7 +1033,6 @@ GNUNET_RECLAIM_presentation_get_expiration (const struct | |||
1033 | /** | 1033 | /** |
1034 | * Create a presentation from a credential and a lift of (selected) | 1034 | * Create a presentation from a credential and a lift of (selected) |
1035 | * attributes in the credential. | 1035 | * attributes in the credential. |
1036 | * FIXME not yet implemented | ||
1037 | * | 1036 | * |
1038 | * @param cred the credential to use | 1037 | * @param cred the credential to use |
1039 | * @param attrs the attributes to present from the credential | 1038 | * @param attrs the attributes to present from the credential |