diff options
-rw-r--r-- | src/reclaim/plugin_reclaim_credential_pabc.c | 361 |
1 files changed, 229 insertions, 132 deletions
diff --git a/src/reclaim/plugin_reclaim_credential_pabc.c b/src/reclaim/plugin_reclaim_credential_pabc.c index 765652355..422d7c82b 100644 --- a/src/reclaim/plugin_reclaim_credential_pabc.c +++ b/src/reclaim/plugin_reclaim_credential_pabc.c | |||
@@ -99,7 +99,7 @@ static struct | |||
99 | { | 99 | { |
100 | const char *name; | 100 | const char *name; |
101 | uint32_t number; | 101 | uint32_t number; |
102 | } pabc_cred_name_map[] = { { "pabc", GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC }, | 102 | } pabc_cred_name_map[] = { { "PABC", GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC }, |
103 | { NULL, UINT32_MAX } }; | 103 | { NULL, UINT32_MAX } }; |
104 | 104 | ||
105 | /** | 105 | /** |
@@ -155,89 +155,73 @@ pabc_parse_attributes (void *cls, | |||
155 | const char *data, | 155 | const char *data, |
156 | size_t data_size) | 156 | size_t data_size) |
157 | { | 157 | { |
158 | char *pabc_string; | 158 | const char *key; |
159 | struct GNUNET_RECLAIM_AttributeList *attrs; | 159 | struct GNUNET_RECLAIM_AttributeList *attrs; |
160 | char delim[] = "."; | ||
161 | char *val_str = NULL; | 160 | char *val_str = NULL; |
162 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing pabc attributes.\n"); | ||
163 | char *decoded_pabc; | ||
164 | char *tmp; | 161 | char *tmp; |
165 | json_t *json_val; | 162 | json_t *value; |
163 | json_t *attr; | ||
164 | json_t *json_attrs; | ||
165 | json_t *json_root; | ||
166 | json_error_t *json_err = NULL; | 166 | json_error_t *json_err = NULL; |
167 | 167 | ||
168 | attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | 168 | json_root = json_loads (data, JSON_DECODE_ANY, json_err); |
169 | if ((NULL == json_root) || | ||
170 | (!json_is_object (json_root))) | ||
171 | { | ||
172 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
173 | "%s is not a valid pabc credentials (not an object)\n", | ||
174 | data); | ||
175 | if (NULL != json_root) | ||
176 | json_decref (json_root); | ||
177 | return NULL; | ||
178 | } | ||
179 | json_attrs = json_object_get (json_root, "attributes"); | ||
180 | if ((NULL == json_attrs) || | ||
181 | (!json_is_array (json_attrs))) | ||
182 | { | ||
183 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
184 | "%s is not a valid pabc credentials (attributes not an array)\n", | ||
185 | data); | ||
186 | json_decref (json_root); | ||
187 | return NULL; | ||
188 | } | ||
169 | 189 | ||
170 | pabc_string = GNUNET_strndup (data, data_size); | 190 | attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); |
171 | const char *pabc_body = strtok (pabc_string, delim); | 191 | for (int i = 0; i < json_array_size (json_attrs); i++) |
172 | pabc_body = strtok (NULL, delim); | 192 | { |
173 | GNUNET_STRINGS_base64url_decode (pabc_body, strlen (pabc_body), | 193 | attr = json_array_get (json_attrs, i); |
174 | (void **) &decoded_pabc); | 194 | if (!json_is_object(attr)) |
175 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded pabc: %s\n", decoded_pabc); | ||
176 | GNUNET_assert (NULL != decoded_pabc); | ||
177 | json_val = json_loads (decoded_pabc, JSON_DECODE_ANY, json_err); | ||
178 | GNUNET_free (decoded_pabc); | ||
179 | const char *key; | ||
180 | const char *addr_key; | ||
181 | json_t *value; | ||
182 | json_t *addr_value; | ||
183 | |||
184 | json_object_foreach (json_val, key, value) { | ||
185 | if (0 == strcmp ("iss", key)) | ||
186 | continue; | ||
187 | if (0 == strcmp ("jti", key)) | ||
188 | continue; | ||
189 | if (0 == strcmp ("exp", key)) | ||
190 | continue; | ||
191 | if (0 == strcmp ("iat", key)) | ||
192 | continue; | ||
193 | if (0 == strcmp ("nbf", key)) | ||
194 | continue; | ||
195 | if (0 == strcmp ("aud", key)) | ||
196 | continue; | ||
197 | if (0 == strcmp ("address", key)) | ||
198 | { | 195 | { |
199 | if (!json_is_object(value)) { | 196 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
200 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 197 | "Found json entry is not an object!\n"); |
201 | "address claim in wrong format!"); | 198 | GNUNET_RECLAIM_attribute_list_destroy (attrs); |
202 | continue; | 199 | json_decref (json_root); |
203 | } | 200 | return NULL; |
204 | json_object_foreach (value, addr_key, addr_value) { | 201 | } |
205 | val_str = json_dumps (addr_value, JSON_ENCODE_ANY); | 202 | /** |
206 | tmp = val_str; | 203 | * This *should* only contain a single pair. |
207 | //Remove leading " from jasson conversion | 204 | */ |
208 | if (tmp[0] == '"') | 205 | json_object_foreach (attr, key, value) |
209 | tmp++; | 206 | { |
210 | //Remove trailing " from jansson conversion | 207 | val_str = json_dumps (value, JSON_ENCODE_ANY); |
211 | if (tmp[strlen(tmp)-1] == '"') | 208 | tmp = val_str; |
212 | tmp[strlen(tmp)-1] = '\0'; | 209 | //Remove leading " from jasson conversion |
213 | GNUNET_RECLAIM_attribute_list_add (attrs, | 210 | if (tmp[0] == '"') |
214 | addr_key, | 211 | tmp++; |
215 | NULL, | 212 | //Remove trailing " from jansson conversion |
216 | GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, | 213 | if (tmp[strlen(tmp)-1] == '"') |
217 | tmp, | 214 | tmp[strlen(tmp)-1] = '\0'; |
218 | strlen (val_str)); | 215 | GNUNET_RECLAIM_attribute_list_add (attrs, |
219 | GNUNET_free (val_str); | 216 | key, |
220 | } | 217 | NULL, |
221 | continue; | 218 | GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, |
219 | tmp, | ||
220 | strlen (tmp)); | ||
221 | GNUNET_free (val_str); | ||
222 | } | 222 | } |
223 | val_str = json_dumps (value, JSON_ENCODE_ANY); | ||
224 | tmp = val_str; | ||
225 | //Remove leading " from jasson conversion | ||
226 | if (tmp[0] == '"') | ||
227 | tmp++; | ||
228 | //Remove trailing " from jansson conversion | ||
229 | if (tmp[strlen(tmp)-1] == '"') | ||
230 | tmp[strlen(tmp)-1] = '\0'; | ||
231 | GNUNET_RECLAIM_attribute_list_add (attrs, | ||
232 | key, | ||
233 | NULL, | ||
234 | GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,// FIXME | ||
235 | tmp, | ||
236 | strlen (val_str)); | ||
237 | GNUNET_free (val_str); | ||
238 | } | 223 | } |
239 | json_decref (json_val); | 224 | json_decref (json_root); |
240 | GNUNET_free (pabc_string); | ||
241 | return attrs; | 225 | return attrs; |
242 | } | 226 | } |
243 | 227 | ||
@@ -284,34 +268,41 @@ pabc_get_issuer (void *cls, | |||
284 | const char *data, | 268 | const char *data, |
285 | size_t data_size) | 269 | size_t data_size) |
286 | { | 270 | { |
287 | const char *pabc_body; | 271 | char *val_str = NULL; |
288 | char *pabc_string; | 272 | char *tmp; |
289 | char delim[] = "."; | 273 | json_t *json_iss; |
290 | char *issuer = NULL; | 274 | json_t *json_root; |
291 | char *decoded_pabc; | ||
292 | json_t *issuer_json; | ||
293 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing pabc attributes.\n"); | ||
294 | json_t *json_val; | ||
295 | json_error_t *json_err = NULL; | 275 | json_error_t *json_err = NULL; |
296 | 276 | ||
297 | pabc_string = GNUNET_strndup (data, data_size); | 277 | json_root = json_loads (data, JSON_DECODE_ANY, json_err); |
298 | pabc_body = strtok (pabc_string, delim); | 278 | if ((NULL == json_root) || |
299 | pabc_body = strtok (NULL, delim); | 279 | (!json_is_object (json_root))) |
300 | GNUNET_STRINGS_base64url_decode (pabc_body, strlen (pabc_body), | 280 | { |
301 | (void **) &decoded_pabc); | 281 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
302 | json_val = json_loads (decoded_pabc, JSON_DECODE_ANY, json_err); | 282 | "%s is not a valid pabc credentials (not an object)\n", |
303 | GNUNET_free (decoded_pabc); | 283 | data); |
304 | GNUNET_free (pabc_string); | 284 | if (NULL != json_root) |
305 | if (NULL == json_val) | 285 | json_decref (json_root); |
306 | return NULL; | 286 | return NULL; |
307 | issuer_json = json_object_get (json_val, "iss"); | 287 | } |
308 | if ((NULL == issuer_json) || (! json_is_string (issuer_json))) { | 288 | json_iss = json_object_get (json_root, "issuer"); |
309 | json_decref (json_val); | 289 | if (NULL == json_iss) |
290 | { | ||
291 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
292 | "%s is not a valid pabc credential (issuer malformed or missing)\n", | ||
293 | data); | ||
294 | json_decref (json_root); | ||
310 | return NULL; | 295 | return NULL; |
311 | } | 296 | } |
312 | issuer = GNUNET_strdup (json_string_value (issuer_json)); | 297 | val_str = json_dumps (json_iss, JSON_ENCODE_ANY); |
313 | json_decref (json_val); | 298 | tmp = val_str; |
314 | return issuer; | 299 | //Remove leading " from jasson conversion |
300 | if (tmp[0] == '"') | ||
301 | tmp++; | ||
302 | //Remove trailing " from jansson conversion | ||
303 | if (tmp[strlen(tmp)-1] == '"') | ||
304 | tmp[strlen(tmp)-1] = '\0'; | ||
305 | return tmp; | ||
315 | } | 306 | } |
316 | 307 | ||
317 | 308 | ||
@@ -362,32 +353,32 @@ pabc_get_expiration (void *cls, | |||
362 | size_t data_size, | 353 | size_t data_size, |
363 | struct GNUNET_TIME_Absolute *exp) | 354 | struct GNUNET_TIME_Absolute *exp) |
364 | { | 355 | { |
365 | const char *pabc_body; | 356 | json_t *json_exp; |
366 | char *pabc_string; | 357 | json_t *json_root; |
367 | char delim[] = "."; | ||
368 | char *decoded_pabc; | ||
369 | json_t *exp_json; | ||
370 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing pabc attributes.\n"); | ||
371 | json_t *json_val; | ||
372 | json_error_t *json_err = NULL; | 358 | json_error_t *json_err = NULL; |
373 | 359 | ||
374 | pabc_string = GNUNET_strndup (data, data_size); | 360 | json_root = json_loads (data, JSON_DECODE_ANY, json_err); |
375 | pabc_body = strtok (pabc_string, delim); | 361 | if ((NULL == json_root) || |
376 | pabc_body = strtok (NULL, delim); | 362 | (!json_is_object (json_root))) |
377 | GNUNET_STRINGS_base64url_decode (pabc_body, strlen (pabc_body), | 363 | { |
378 | (void **) &decoded_pabc); | 364 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
379 | json_val = json_loads (decoded_pabc, JSON_DECODE_ANY, json_err); | 365 | "%s is not a valid pabc credentials (not an object)\n", |
380 | GNUNET_free (decoded_pabc); | 366 | data); |
381 | GNUNET_free (pabc_string); | 367 | if (NULL != json_root) |
382 | if (NULL == json_val) | 368 | json_decref (json_root); |
383 | return GNUNET_SYSERR; | 369 | return GNUNET_SYSERR; |
384 | exp_json = json_object_get (json_val, "exp"); | 370 | } |
385 | if ((NULL == exp_json) || (! json_is_integer (exp_json))) { | 371 | json_exp = json_object_get (json_root, "expiration"); |
386 | json_decref (json_val); | 372 | if ((NULL == json_exp) || (! json_is_integer (json_exp))) |
373 | { | ||
374 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
375 | "%s is not a valid pabc credential (expiration malformed or missing)\n", | ||
376 | data); | ||
377 | json_decref (json_root); | ||
387 | return GNUNET_SYSERR; | 378 | return GNUNET_SYSERR; |
388 | } | 379 | } |
389 | exp->abs_value_us = json_integer_value (exp_json) * 1000 * 1000; | 380 | exp->abs_value_us = json_integer_value (json_exp) * 1000 * 1000; |
390 | json_decref (json_val); | 381 | json_decref (json_root); |
391 | return GNUNET_OK; | 382 | return GNUNET_OK; |
392 | } | 383 | } |
393 | 384 | ||
@@ -426,16 +417,130 @@ pabc_get_expiration_p (void *cls, | |||
426 | 417 | ||
427 | int | 418 | int |
428 | pabc_create_presentation (void *cls, | 419 | pabc_create_presentation (void *cls, |
429 | const struct GNUNET_RECLAIM_Credential *cred, | 420 | const struct GNUNET_RECLAIM_Credential *credential, |
430 | const struct GNUNET_RECLAIM_AttributeList *attrs, | 421 | const struct GNUNET_RECLAIM_AttributeList *attrs, |
431 | struct GNUNET_RECLAIM_Presentation **pres) | 422 | struct GNUNET_RECLAIM_Presentation **pres) |
432 | { | 423 | { |
433 | // FIXME sanity checks?? | 424 | struct pabc_context *ctx = NULL; |
434 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type) | 425 | struct pabc_user_context *usr_ctx = NULL; |
426 | struct pabc_public_parameters *pp = NULL; | ||
427 | struct pabc_credential *cred = NULL; | ||
428 | struct pabc_blinded_proof *proof = NULL; | ||
429 | struct GNUNET_RECLAIM_AttributeListEntry *ale; | ||
430 | enum pabc_status status; | ||
431 | |||
432 | if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != credential->type) | ||
435 | return GNUNET_NO; | 433 | return GNUNET_NO; |
434 | |||
435 | |||
436 | PABC_ASSERT (pabc_new_ctx (&ctx)); | ||
437 | /** | ||
438 | * FIXME, how to get pp_name. | ||
439 | * Ideal would be an API that allows us to load pp by | ||
440 | * issuer name. | ||
441 | */ | ||
442 | //status = load_public_parameters (ctx, "issuerXY", &pp); | ||
443 | if (status != PABC_OK) | ||
444 | { | ||
445 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
446 | "Failed to read public parameters.\n"); | ||
447 | pabc_free_ctx (&ctx); | ||
448 | return GNUNET_SYSERR; | ||
449 | } | ||
450 | //FIXME needs API | ||
451 | //status = read_usr_ctx (usr_name, pp_name, ctx, pp, &usr_ctx); | ||
452 | if (PABC_OK != status) | ||
453 | { | ||
454 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
455 | "Failed to read user context.\n"); | ||
456 | pabc_free_public_parameters (ctx, &pp); | ||
457 | return GNUNET_SYSERR; | ||
458 | } | ||
459 | |||
460 | status = pabc_new_credential (ctx, pp, &cred); | ||
461 | if (status != PABC_OK) | ||
462 | { | ||
463 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
464 | "Failed to allocate credential.\n"); | ||
465 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
466 | pabc_free_public_parameters (ctx, &pp); | ||
467 | return GNUNET_SYSERR; | ||
468 | } | ||
469 | |||
470 | status = pabc_decode_credential (ctx, pp, cred, credential->data); | ||
471 | if (status != PABC_OK) | ||
472 | { | ||
473 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
474 | "Failed to decode credential.\n"); | ||
475 | pabc_free_credential (ctx, pp, &cred); | ||
476 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
477 | pabc_free_public_parameters (ctx, &pp); | ||
478 | return GNUNET_SYSERR; | ||
479 | } | ||
480 | |||
481 | status = pabc_new_proof (ctx, pp, &proof); | ||
482 | if (status != PABC_OK) | ||
483 | { | ||
484 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
485 | "Failed to allocate proof.\n"); | ||
486 | pabc_free_credential (ctx, pp, &cred); | ||
487 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
488 | pabc_free_public_parameters (ctx, &pp); | ||
489 | return GNUNET_SYSERR; | ||
490 | } | ||
491 | |||
492 | // now we can parse the attributes to disclose and configure the proof | ||
493 | for (ale = attrs->list_head; NULL != ale; ale = ale->next) | ||
494 | { | ||
495 | status = pabc_set_disclosure_by_attribute_name (ctx, pp, proof, | ||
496 | ale->attribute->name, | ||
497 | PABC_DISCLOSED, cred); | ||
498 | if (status != PABC_OK) | ||
499 | { | ||
500 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
501 | "Failed to configure proof.\n"); | ||
502 | pabc_free_credential (ctx, pp, &cred); | ||
503 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
504 | pabc_free_public_parameters (ctx, &pp); | ||
505 | return GNUNET_SYSERR; | ||
506 | } | ||
507 | } | ||
508 | |||
509 | // and finally -> sign the proof | ||
510 | status = pabc_gen_proof (ctx, usr_ctx, pp, proof, cred); | ||
511 | if (status != PABC_OK) | ||
512 | { | ||
513 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
514 | "Failed to sign proof.\n"); | ||
515 | pabc_free_proof (ctx, pp, &proof); | ||
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 | // print the result | ||
522 | char *json = NULL; | ||
523 | pabc_encode_proof (ctx, pp, proof, &json); | ||
524 | if (PABC_OK != status) | ||
525 | { | ||
526 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
527 | "Failed to serialize proof.\n"); | ||
528 | pabc_free_proof (ctx, pp, &proof); | ||
529 | pabc_free_credential (ctx, pp, &cred); | ||
530 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
531 | pabc_free_public_parameters (ctx, &pp); | ||
532 | return GNUNET_SYSERR; | ||
533 | } | ||
534 | printf ("%s", json); | ||
535 | // clean up | ||
436 | *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC, | 536 | *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC, |
437 | cred->data, | 537 | json, |
438 | cred->data_size); | 538 | strlen (json) + 1); |
539 | PABC_FREE_NULL (json); | ||
540 | pabc_free_proof (ctx, pp, &proof); | ||
541 | pabc_free_credential (ctx, pp, &cred); | ||
542 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
543 | pabc_free_public_parameters (ctx, &pp); | ||
439 | return GNUNET_OK; | 544 | return GNUNET_OK; |
440 | } | 545 | } |
441 | 546 | ||
@@ -450,14 +555,6 @@ void * | |||
450 | libgnunet_plugin_reclaim_credential_pabc_init (void *cls) | 555 | libgnunet_plugin_reclaim_credential_pabc_init (void *cls) |
451 | { | 556 | { |
452 | struct GNUNET_RECLAIM_CredentialPluginFunctions *api; | 557 | struct GNUNET_RECLAIM_CredentialPluginFunctions *api; |
453 | struct pabc_context *ctx; | ||
454 | |||
455 | if (PABC_OK != pabc_new_ctx (&ctx)) | ||
456 | { | ||
457 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
458 | "Unable to initialize pabc context\n"); | ||
459 | return NULL; | ||
460 | } | ||
461 | 558 | ||
462 | api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions); | 559 | api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions); |
463 | api->value_to_string = &pabc_value_to_string; | 560 | api->value_to_string = &pabc_value_to_string; |