aboutsummaryrefslogtreecommitdiff
path: root/src/identity-provider/plugin_rest_identity_provider.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/identity-provider/plugin_rest_identity_provider.c')
-rw-r--r--src/identity-provider/plugin_rest_identity_provider.c1119
1 files changed, 559 insertions, 560 deletions
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c
index 907b28ba9..6eb856435 100644
--- a/src/identity-provider/plugin_rest_identity_provider.c
+++ b/src/identity-provider/plugin_rest_identity_provider.c
@@ -37,6 +37,7 @@
37#include <jansson.h> 37#include <jansson.h>
38#include <inttypes.h> 38#include <inttypes.h>
39#include "gnunet_signatures.h" 39#include "gnunet_signatures.h"
40#include "gnunet_identity_attribute_lib.h"
40#include "gnunet_identity_provider_service.h" 41#include "gnunet_identity_provider_service.h"
41 42
42/** 43/**
@@ -45,39 +46,40 @@
45#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp" 46#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp"
46 47
47/** 48/**
48 * Issue namespace 49 * Attribute namespace
49 */ 50 */
50#define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/idp/issue" 51#define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes"
51 52
52/** 53/**
53 * Check namespace TODO 54 * Ticket namespace
54 */ 55 */
55#define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/idp/check" 56#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets"
56 57
57/** 58/**
58 * Token namespace 59 * Revoke namespace
59 */ 60 */
60#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token" 61#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke"
61 62
62/** 63/**
63 * The parameter name in which the ticket must be provided 64 * Revoke namespace
64 */ 65 */
65#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket" 66#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume"
66 67
67/** 68/**
68 * The parameter name in which the expected nonce must be provided 69 * Attribute key
69 */ 70 */
70#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce" 71#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute"
71 72
72/** 73/**
73 * The parameter name in which the ticket must be provided 74 * Ticket key
74 */ 75 */
75#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token" 76#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
77
76 78
77/** 79/**
78 * The URL parameter name in which the nonce must be provided 80 * Value key
79 */ 81 */
80#define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce" 82#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value"
81 83
82/** 84/**
83 * State while collecting all egos 85 * State while collecting all egos
@@ -89,41 +91,6 @@
89 */ 91 */
90#define ID_REST_STATE_POST_INIT 1 92#define ID_REST_STATE_POST_INIT 1
91 93
92/**
93 * Resource type
94 */
95#define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
96
97/**
98 * URL parameter to create a GNUid token for a specific audience
99 */
100#define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
101
102/**
103 * URL parameter to create a GNUid token for a specific issuer (EGO)
104 */
105#define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
106
107/**
108 * Attributes passed to issue request
109 */
110#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
111
112/**
113 * Token expiration string
114 */
115#define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
116
117/**
118 * Error messages
119 */
120#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
121#define GNUNET_REST_ERROR_NO_DATA "No data"
122
123/**
124 * GNUid token lifetime
125 */
126#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
127 94
128/** 95/**
129 * The configuration handle 96 * The configuration handle
@@ -198,11 +165,6 @@ struct RequestHandle
198 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 165 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
199 166
200 /** 167 /**
201 * Handle to the rest connection
202 */
203 struct GNUNET_REST_RequestHandle *conndata_handle;
204
205 /**
206 * The processing state 168 * The processing state
207 */ 169 */
208 int state; 170 int state;
@@ -213,6 +175,12 @@ struct RequestHandle
213 struct GNUNET_IDENTITY_Handle *identity_handle; 175 struct GNUNET_IDENTITY_Handle *identity_handle;
214 176
215 /** 177 /**
178 * Rest connection
179 */
180 struct GNUNET_REST_RequestHandle *rest_handle;
181
182
183 /**
216 * IDENTITY Operation 184 * IDENTITY Operation
217 */ 185 */
218 struct GNUNET_IDENTITY_Operation *op; 186 struct GNUNET_IDENTITY_Operation *op;
@@ -228,19 +196,14 @@ struct RequestHandle
228 struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; 196 struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
229 197
230 /** 198 /**
231 * Handle to NS service 199 * Attribute iterator
232 */
233 struct GNUNET_NAMESTORE_Handle *ns_handle;
234
235 /**
236 * NS iterator
237 */ 200 */
238 struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 201 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
239 202
240 /** 203 /**
241 * NS Handle 204 * Ticket iterator
242 */ 205 */
243 struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 206 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
244 207
245 /** 208 /**
246 * Desired timeout for the lookup (default is no timeout). 209 * Desired timeout for the lookup (default is no timeout).
@@ -285,6 +248,7 @@ struct RequestHandle
285}; 248};
286 249
287 250
251
288/** 252/**
289 * Cleanup lookup handle 253 * Cleanup lookup handle
290 * @param handle Handle to clean up 254 * @param handle Handle to clean up
@@ -302,14 +266,12 @@ cleanup_handle (struct RequestHandle *handle)
302 GNUNET_SCHEDULER_cancel (handle->timeout_task); 266 GNUNET_SCHEDULER_cancel (handle->timeout_task);
303 if (NULL != handle->identity_handle) 267 if (NULL != handle->identity_handle)
304 GNUNET_IDENTITY_disconnect (handle->identity_handle); 268 GNUNET_IDENTITY_disconnect (handle->identity_handle);
269 if (NULL != handle->attr_it)
270 GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it);
271 if (NULL != handle->ticket_it)
272 GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it);
305 if (NULL != handle->idp) 273 if (NULL != handle->idp)
306 GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp); 274 GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
307 if (NULL != handle->ns_it)
308 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
309 if (NULL != handle->ns_qe)
310 GNUNET_NAMESTORE_cancel (handle->ns_qe);
311 if (NULL != handle->ns_handle)
312 GNUNET_NAMESTORE_disconnect (handle->ns_handle);
313 if (NULL != handle->url) 275 if (NULL != handle->url)
314 GNUNET_free (handle->url); 276 GNUNET_free (handle->url);
315 if (NULL != handle->emsg) 277 if (NULL != handle->emsg)
@@ -326,6 +288,12 @@ cleanup_handle (struct RequestHandle *handle)
326 GNUNET_free (handle); 288 GNUNET_free (handle);
327} 289}
328 290
291static void
292cleanup_handle_delayed (void *cls)
293{
294 cleanup_handle (cls);
295}
296
329 297
330/** 298/**
331 * Task run on error, sends error message. Cleans up everything. 299 * Task run on error, sends error message. Cleans up everything.
@@ -363,622 +331,663 @@ do_timeout (void *cls)
363} 331}
364 332
365 333
366/**
367 * Task run on shutdown. Cleans up everything.
368 *
369 * @param cls unused
370 */
371static void 334static void
372do_cleanup_handle_delayed (void *cls) 335collect_error_cb (void *cls)
373{ 336{
374 struct RequestHandle *handle = cls; 337 struct RequestHandle *handle = cls;
375 338
376 cleanup_handle (handle); 339 do_error (handle);
377} 340}
378 341
379
380/**
381 * Get a ticket for identity
382 * @param cls the handle
383 * @param ticket the ticket returned from the idp
384 */
385static void 342static void
386token_creat_cont (void *cls, 343finished_cont (void *cls,
387 const char *label, 344 int32_t success,
388 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, 345 const char *emsg)
389 const struct GNUNET_IDENTITY_PROVIDER_Token *token)
390{ 346{
391 struct GNUNET_JSONAPI_Resource *json_resource;
392 struct RequestHandle *handle = cls; 347 struct RequestHandle *handle = cls;
393 struct MHD_Response *resp; 348 struct MHD_Response *resp;
394 json_t *ticket_json;
395 json_t *token_json;
396 char *ticket_str;
397 char *token_str;
398 char *result_str;
399 349
400 if (NULL == ticket) 350 resp = GNUNET_REST_create_response (emsg);
351 if (GNUNET_OK != success)
401 { 352 {
402 handle->emsg = GNUNET_strdup ("Error in token issue");
403 GNUNET_SCHEDULER_add_now (&do_error, handle); 353 GNUNET_SCHEDULER_add_now (&do_error, handle);
404 return; 354 return;
405 } 355 }
356 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
357 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
358}
406 359
407 handle->resp_object = GNUNET_JSONAPI_document_new (); 360
408 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 361/**
409 label); 362 * Return attributes for identity
410 ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket); 363 *
411 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token); 364 * @param cls the request handle
412 ticket_json = json_string (ticket_str); 365 */
413 token_json = json_string (token_str); 366static void
414 GNUNET_JSONAPI_resource_add_attr (json_resource, 367return_response (void *cls)
415 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 368{
416 ticket_json); 369 char* result_str;
417 GNUNET_JSONAPI_resource_add_attr (json_resource, 370 struct RequestHandle *handle = cls;
418 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN, 371 struct MHD_Response *resp;
419 token_json);
420 GNUNET_free (ticket_str);
421 GNUNET_free (token_str);
422 json_decref (ticket_json);
423 json_decref (token_json);
424 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
425 372
426 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str); 373 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
428 resp = GNUNET_REST_create_response (result_str); 375 resp = GNUNET_REST_create_response (result_str);
429 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 376 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
430 GNUNET_free (result_str); 377 GNUNET_free (result_str);
431 GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle); 378 cleanup_handle (handle);
379}
380
381
382static void
383collect_finished_cb (void *cls)
384{
385 struct RequestHandle *handle = cls;
386 //Done
387 handle->attr_it = NULL;
388 handle->ticket_it = NULL;
389 GNUNET_SCHEDULER_add_now (&return_response, handle);
432} 390}
433 391
434 392
435/** 393/**
436 * Continueationf for token issue request 394 * Collect all attributes for an ego
437 * 395 *
438 * @param con the Rest handle
439 * @param url the requested url
440 * @param cls the request handle
441 */ 396 */
442static void 397static void
443issue_token_cont (struct GNUNET_REST_RequestHandle *con, 398ticket_collect (void *cls,
444 const char *url, 399 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
445 void *cls)
446{ 400{
447 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 401 struct GNUNET_JSONAPI_Resource *json_resource;
448 const char *egoname; 402 struct RequestHandle *handle = cls;
403 json_t *value;
404 char* tmp;
405
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
407 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
408 sizeof (uint64_t));
409 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET,
410 tmp);
411 GNUNET_free (tmp);
412 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
413
414 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
415 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
416 value = json_string (tmp);
417 GNUNET_JSONAPI_resource_add_attr (json_resource,
418 "issuer",
419 value);
420 GNUNET_free (tmp);
421 json_decref (value);
422 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
423 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
424 value = json_string (tmp);
425 GNUNET_JSONAPI_resource_add_attr (json_resource,
426 "audience",
427 value);
428 GNUNET_free (tmp);
429 json_decref (value);
430 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
431 sizeof (uint64_t));
432 value = json_string (tmp);
433 GNUNET_JSONAPI_resource_add_attr (json_resource,
434 "rnd",
435 value);
436 GNUNET_free (tmp);
437 json_decref (value);
438 GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (handle->ticket_it);
439}
440
449 441
442
443/**
444 * List tickets for identity request
445 *
446 * @param con_handle the connection handle
447 * @param url the url
448 * @param cls the RequestHandle
449 */
450static void
451list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
452 const char* url,
453 void *cls)
454{
455 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
450 struct RequestHandle *handle = cls; 456 struct RequestHandle *handle = cls;
451 struct EgoEntry *ego_entry; 457 struct EgoEntry *ego_entry;
452 struct GNUNET_HashCode key; 458 char *identity;
453 struct MHD_Response *resp; 459
454 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
455 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 461 handle->url);
456 struct GNUNET_TIME_Relative etime_rel; 462 if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
457 struct GNUNET_TIME_Absolute exp_time; 463 strlen (handle->url))
458 char *ego_val;
459 char *audience;
460 char *exp_str;
461 char *nonce_str;
462 char *scopes;
463 uint64_t time;
464 uint64_t nonce;
465
466 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
467 GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
468 {
469 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
470 resp = GNUNET_REST_create_response (NULL);
471 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
472 cleanup_handle (handle);
473 return;
474 }
475 egoname = NULL;
476 ego_entry = NULL;
477 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
478 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
479 &key);
480 if ( GNUNET_YES !=
481 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
482 &key) )
483 {
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
485 "Issuer not found\n");
486 GNUNET_SCHEDULER_add_now (&do_error, handle);
487 return;
488 }
489 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
490 &key);
491 if (NULL == ego_val)
492 { 464 {
465 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
493 GNUNET_SCHEDULER_add_now (&do_error, handle); 466 GNUNET_SCHEDULER_add_now (&do_error, handle);
494 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
495 "Ego invalid: %s\n",
496 ego_val);
497 return; 467 return;
498 } 468 }
469 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
470
499 for (ego_entry = handle->ego_head; 471 for (ego_entry = handle->ego_head;
500 NULL != ego_entry; 472 NULL != ego_entry;
501 ego_entry = ego_entry->next) 473 ego_entry = ego_entry->next)
474 if (0 == strcmp (identity, ego_entry->identifier))
475 break;
476 handle->resp_object = GNUNET_JSONAPI_document_new ();
477
478 if (NULL == ego_entry)
502 { 479 {
503 if (0 != strcmp (ego_val, ego_entry->identifier)) 480 //Done
504 continue; 481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
505 egoname = ego_entry->identifier; 482 identity);
506 break; 483 GNUNET_SCHEDULER_add_now (&return_response, handle);
507 }
508 if ( (NULL == egoname) ||
509 (NULL == ego_entry) )
510 {
511 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
512 "Ego not found: %s\n",
513 ego_val);
514 GNUNET_SCHEDULER_add_now (&do_error, handle);
515 return; 484 return;
516 } 485 }
517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 486 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
518 "Ego to issue token for: %s\n", 487 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
519 egoname); 488 handle->ticket_it = GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (handle->idp,
489 priv_key,
490 &collect_error_cb,
491 handle,
492 &ticket_collect,
493 handle,
494 &collect_finished_cb,
495 handle);
496}
520 497
521 498
522 //Meta info 499static void
523 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST, 500add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
524 strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST), 501 const char* url,
525 &key); 502 void *cls)
503{
504 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
505 const char* identity;
506 const char* name_str;
507 const char* value_str;
526 508
527 scopes = NULL; 509 struct RequestHandle *handle = cls;
528 if ( GNUNET_YES != 510 struct EgoEntry *ego_entry;
529 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 511 struct MHD_Response *resp;
530 &key) ) 512 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attribute;
513 struct GNUNET_JSONAPI_Document *json_obj;
514 struct GNUNET_JSONAPI_Resource *json_res;
515 char term_data[handle->rest_handle->data_size+1];
516 json_t *value_json;
517 json_t *data_json;
518 json_error_t err;
519 struct GNUNET_JSON_Specification docspec[] = {
520 GNUNET_JSON_spec_jsonapi_document (&json_obj),
521 GNUNET_JSON_spec_end()
522 };
523
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
525 handle->url);
526 if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
527 strlen (handle->url))
531 { 528 {
532 handle->emsg = GNUNET_strdup ("Scopes missing!\n"); 529 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
533 GNUNET_SCHEDULER_add_now (&do_error, handle); 530 GNUNET_SCHEDULER_add_now (&do_error, handle);
534 return; 531 return;
535 } 532 }
536 scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 533 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
537 &key); 534
538 535 for (ego_entry = handle->ego_head;
539 536 NULL != ego_entry;
540 //Token audience 537 ego_entry = ego_entry->next)
541 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST, 538 if (0 == strcmp (identity, ego_entry->identifier))
542 strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST), 539 break;
543 &key); 540
544 audience = NULL; 541 if (NULL == ego_entry)
545 if ( GNUNET_YES !=
546 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
547 &key) )
548 { 542 {
549 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 543 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
550 "Audience missing!\n"); 544 "Identity unknown (%s)\n", identity);
551 GNUNET_SCHEDULER_add_now (&do_error, handle); 545 GNUNET_JSONAPI_document_delete (json_obj);
552 return; 546 return;
553 } 547 }
554 audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 548 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
555 &key);
556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
557 "Audience to issue token for: %s\n",
558 audience);
559
560 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
561 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
562 &pub_key);
563 GNUNET_STRINGS_string_to_data (audience,
564 strlen (audience),
565 &aud_key,
566 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
567 549
568 //Remote nonce 550 if (0 >= handle->rest_handle->data_size)
569 nonce_str = NULL;
570 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
571 strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
572 &key);
573 if ( GNUNET_YES !=
574 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
575 &key) )
576 { 551 {
577 handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
578 GNUNET_SCHEDULER_add_now (&do_error, handle); 552 GNUNET_SCHEDULER_add_now (&do_error, handle);
579 return; 553 return;
580 } 554 }
581 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 555
582 &key); 556 term_data[handle->rest_handle->data_size] = '\0';
583 GNUNET_assert (NULL != nonce_str); 557 GNUNET_memcpy (term_data,
584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 558 handle->rest_handle->data,
585 "Request nonce: %s\n", 559 handle->rest_handle->data_size);
586 nonce_str); 560 data_json = json_loads (term_data,
587 GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce)); 561 JSON_DECODE_ANY,
588 562 &err);
589 //Get expiration for token from URL parameter 563 GNUNET_assert (GNUNET_OK ==
590 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING, 564 GNUNET_JSON_parse (data_json, docspec,
591 strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING), 565 NULL, NULL));
592 &key); 566 json_decref (data_json);
593 567 if (NULL == json_obj)
594 exp_str = NULL;
595 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
596 &key))
597 { 568 {
598 exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 569 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
599 &key); 570 "Unable to parse JSONAPI Object from %s\n",
600 } 571 term_data);
601 if (NULL == exp_str) {
602 handle->emsg = GNUNET_strdup ("No expiration given!\n");
603 GNUNET_SCHEDULER_add_now (&do_error, handle); 572 GNUNET_SCHEDULER_add_now (&do_error, handle);
604 return; 573 return;
605 } 574 }
606 575 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
607 if (GNUNET_OK !=
608 GNUNET_STRINGS_fancy_time_to_relative (exp_str,
609 &etime_rel))
610 { 576 {
611 handle->emsg = GNUNET_strdup ("Expiration invalid!\n"); 577 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
578 "Cannot create more than 1 resource! (Got %d)\n",
579 GNUNET_JSONAPI_document_resource_count (json_obj));
580 GNUNET_JSONAPI_document_delete (json_obj);
612 GNUNET_SCHEDULER_add_now (&do_error, handle); 581 GNUNET_SCHEDULER_add_now (&do_error, handle);
613 return; 582 return;
614 } 583 }
615 time = GNUNET_TIME_absolute_get().abs_value_us; 584 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
616 exp_time.abs_value_us = time + etime_rel.rel_value_us; 585 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
617 586 GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE))
587 {
588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
589 "Unsupported JSON data type\n");
590 GNUNET_JSONAPI_document_delete (json_obj);
591 resp = GNUNET_REST_create_response (NULL);
592 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
593 cleanup_handle (handle);
594 return;
595 }
596 name_str = GNUNET_JSONAPI_resource_get_id (json_res);
597 value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
598 "value");
599 value_str = json_string_value (value_json);
600 attribute = GNUNET_IDENTITY_ATTRIBUTE_claim_new (name_str,
601 GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
602 value_str,
603 strlen (value_str) + 1);
618 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); 604 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
619 handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp, 605 handle->idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (handle->idp,
620 priv_key, 606 identity_priv,
621 &aud_key, 607 attribute,
622 scopes, 608 &finished_cont,
623 exp_time, 609 handle);
624 nonce, 610 GNUNET_free (attribute);
625 &token_creat_cont, 611 GNUNET_JSONAPI_document_delete (json_obj);
626 handle);
627
628}
629
630
631/**
632 * Build a GNUid token for identity
633 *
634 * @param cls the request handle
635 */
636static void
637return_token_list (void *cls)
638{
639 char* result_str;
640 struct RequestHandle *handle = cls;
641 struct MHD_Response *resp;
642
643 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
645 resp = GNUNET_REST_create_response (result_str);
646 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
647 GNUNET_free (result_str);
648 cleanup_handle (handle);
649} 612}
650 613
651 614
652static void
653token_collect_error_cb (void *cls)
654{
655 struct RequestHandle *handle = cls;
656
657 do_error (handle);
658}
659
660 615
661/** 616/**
662 * Collect all tokens for an ego 617 * Collect all attributes for an ego
663 *
664 * TODO move this into the identity-provider service
665 * 618 *
666 */ 619 */
667static void 620static void
668token_collect (void *cls, 621attr_collect (void *cls,
669 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 622 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
670 const char *label, 623 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
671 unsigned int rd_count,
672 const struct GNUNET_GNSRECORD_Data *rd);
673
674
675static void
676token_collect_finished_cb (void *cls)
677{ 624{
625 struct GNUNET_JSONAPI_Resource *json_resource;
678 struct RequestHandle *handle = cls; 626 struct RequestHandle *handle = cls;
679 struct EgoEntry *ego_tmp; 627 json_t *value;
680 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 628
681 629 if ((NULL == attr->name) || (NULL == attr->data))
682 ego_tmp = handle->ego_head;
683 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
684 handle->ego_tail,
685 ego_tmp);
686 GNUNET_free (ego_tmp->identifier);
687 GNUNET_free (ego_tmp->keystring);
688 GNUNET_free (ego_tmp);
689
690 if (NULL == handle->ego_head)
691 { 630 {
692 //Done 631 GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
694 handle->ns_it = NULL;
695 GNUNET_SCHEDULER_add_now (&return_token_list, handle);
696 return; 632 return;
697 } 633 }
698 634
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
700 "Next ego: %s\n", 636 attr->name);
701 handle->ego_head->identifier); 637 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
702 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); 638 attr->name);
703 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, 639 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
704 priv_key,
705 &token_collect_error_cb,
706 handle,
707 &token_collect,
708 handle,
709 &token_collect_finished_cb,
710 handle);
711}
712
713
714/**
715 * Collect all tokens for an ego
716 *
717 * TODO move this into the identity-provider service
718 *
719 */
720static void
721token_collect (void *cls,
722 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
723 const char *label,
724 unsigned int rd_count,
725 const struct GNUNET_GNSRECORD_Data *rd)
726{
727 struct RequestHandle *handle = cls;
728 int i;
729 char* data;
730 struct GNUNET_JSONAPI_Resource *json_resource;
731 json_t *issuer;
732 json_t *token;
733
734 for (i = 0; i < rd_count; i++)
735 {
736 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
737 {
738 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
739 rd[i].data,
740 rd[i].data_size);
741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
742 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
743 label);
744 issuer = json_string (handle->ego_head->identifier);
745 GNUNET_JSONAPI_resource_add_attr (json_resource,
746 GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
747 issuer);
748 json_decref (issuer);
749 token = json_string (data);
750 GNUNET_JSONAPI_resource_add_attr (json_resource,
751 GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
752 token);
753 json_decref (token);
754
755 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
756 GNUNET_free (data);
757 }
758 }
759 640
760 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 641 value = json_string (attr->data);
642 GNUNET_JSONAPI_resource_add_attr (json_resource,
643 "value",
644 value);
645 json_decref (value);
646 GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
761} 647}
762 648
763 649
764 650
765/** 651/**
766 * Respond to OPTIONS request 652 * List attributes for identity request
767 * 653 *
768 * @param con_handle the connection handle 654 * @param con_handle the connection handle
769 * @param url the url 655 * @param url the url
770 * @param cls the RequestHandle 656 * @param cls the RequestHandle
771 */ 657 */
772static void 658static void
773list_token_cont (struct GNUNET_REST_RequestHandle *con_handle, 659list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
774 const char* url, 660 const char* url,
775 void *cls) 661 void *cls)
776{ 662{
777 char* ego_val;
778 struct GNUNET_HashCode key;
779 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 663 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
780 struct RequestHandle *handle = cls; 664 struct RequestHandle *handle = cls;
781 struct EgoEntry *ego_entry; 665 struct EgoEntry *ego_entry;
782 struct EgoEntry *ego_tmp; 666 char *identity;
783 667
784 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST, 668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
785 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST), 669 handle->url);
786 &key); 670 if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
787 671 strlen (handle->url))
788 if ( GNUNET_YES !=
789 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
790 &key) )
791 { 672 {
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No issuer given.\n"); 673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
793 GNUNET_SCHEDULER_add_now (&do_error, handle); 674 GNUNET_SCHEDULER_add_now (&do_error, handle);
794 return; 675 return;
795 } 676 }
796 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 677 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
797 &key); 678
798 GNUNET_assert (NULL != ego_val);
799 //Remove non-matching egos
800 for (ego_entry = handle->ego_head; 679 for (ego_entry = handle->ego_head;
801 NULL != ego_entry;) 680 NULL != ego_entry;
802 { 681 ego_entry = ego_entry->next)
803 ego_tmp = ego_entry; 682 if (0 == strcmp (identity, ego_entry->identifier))
804 ego_entry = ego_entry->next; 683 break;
805 if (0 != strcmp (ego_val, ego_tmp->identifier))
806 {
807 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
808 handle->ego_tail,
809 ego_tmp);
810 GNUNET_free (ego_tmp->identifier);
811 GNUNET_free (ego_tmp->keystring);
812 GNUNET_free (ego_tmp);
813 }
814 }
815 handle->resp_object = GNUNET_JSONAPI_document_new (); 684 handle->resp_object = GNUNET_JSONAPI_document_new ();
816 if (NULL == handle->ego_head) 685
686
687 if (NULL == ego_entry)
817 { 688 {
818 //Done 689 //Done
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n"); 690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
820 GNUNET_SCHEDULER_add_now (&return_token_list, handle); 691 identity);
692 GNUNET_SCHEDULER_add_now (&return_response, handle);
821 return; 693 return;
822 } 694 }
823 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); 695 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
824 handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); 696 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
825 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, 697 handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (handle->idp,
826 priv_key, 698 priv_key,
827 &token_collect_error_cb, 699 &collect_error_cb,
828 handle, 700 handle,
829 &token_collect, 701 &attr_collect,
830 handle, 702 handle,
831 &token_collect_finished_cb, 703 &collect_finished_cb,
832 handle); 704 handle);
833
834} 705}
835 706
836/** 707
837 * Return token to requestor
838 *
839 * @param cls request handle
840 * @param token the token
841 */
842static void 708static void
843exchange_cont (void *cls, 709revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
844 const struct GNUNET_IDENTITY_PROVIDER_Token *token, 710 const char* url,
845 uint64_t ticket_nonce) 711 void *cls)
846{ 712{
847 json_t *root; 713 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
714 const char* identity_str;
715 const char* audience_str;
716 const char* rnd_str;
717
848 struct RequestHandle *handle = cls; 718 struct RequestHandle *handle = cls;
719 struct EgoEntry *ego_entry;
849 struct MHD_Response *resp; 720 struct MHD_Response *resp;
850 struct GNUNET_HashCode key; 721 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
851 char* result; 722 struct GNUNET_JSONAPI_Document *json_obj;
852 char* token_str; 723 struct GNUNET_JSONAPI_Resource *json_res;
853 char* nonce_str; 724 struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
854 uint64_t expected_nonce; 725 char term_data[handle->rest_handle->data_size+1];
855 726 json_t *rnd_json;
856 //Get nonce 727 json_t *identity_json;
857 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE, 728 json_t *audience_json;
858 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE), 729 json_t *data_json;
859 &key); 730 json_error_t err;
860 731 struct GNUNET_JSON_Specification docspec[] = {
861 if ( GNUNET_NO == 732 GNUNET_JSON_spec_jsonapi_document (&json_obj),
862 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 733 GNUNET_JSON_spec_end()
863 &key) ) 734 };
735
736 if (0 >= handle->rest_handle->data_size)
864 { 737 {
865 handle->emsg = GNUNET_strdup ("No nonce given.");
866 GNUNET_SCHEDULER_add_now (&do_error, handle); 738 GNUNET_SCHEDULER_add_now (&do_error, handle);
867 return; 739 return;
868 } 740 }
869 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
870 &key);
871 GNUNET_assert (NULL != nonce_str);
872 GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
873 741
874 if (ticket_nonce != expected_nonce) 742 term_data[handle->rest_handle->data_size] = '\0';
743 GNUNET_memcpy (term_data,
744 handle->rest_handle->data,
745 handle->rest_handle->data_size);
746 data_json = json_loads (term_data,
747 JSON_DECODE_ANY,
748 &err);
749 GNUNET_assert (GNUNET_OK ==
750 GNUNET_JSON_parse (data_json, docspec,
751 NULL, NULL));
752 json_decref (data_json);
753 if (NULL == json_obj)
754 {
755 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
756 "Unable to parse JSONAPI Object from %s\n",
757 term_data);
758 GNUNET_SCHEDULER_add_now (&do_error, handle);
759 return;
760 }
761 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
875 { 762 {
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
877 "Ticket nonce %"SCNu64" does not match expected nonce %"SCNu64"\n", 764 "Cannot create more than 1 resource! (Got %d)\n",
878 ticket_nonce, expected_nonce); 765 GNUNET_JSONAPI_document_resource_count (json_obj));
879 handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n"); 766 GNUNET_JSONAPI_document_delete (json_obj);
880 GNUNET_SCHEDULER_add_now (&do_error, handle); 767 GNUNET_SCHEDULER_add_now (&do_error, handle);
881 return; 768 return;
882 } 769 }
770 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
771 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
772 GNUNET_REST_JSONAPI_IDENTITY_TICKET))
773 {
774 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
775 "Unsupported JSON data type\n");
776 GNUNET_JSONAPI_document_delete (json_obj);
777 resp = GNUNET_REST_create_response (NULL);
778 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
779 cleanup_handle (handle);
780 return;
781 }
782 rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
783 "rnd");
784 identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
785 "identity");
786 audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
787 "audience");
788 rnd_str = json_string_value (rnd_json);
789 identity_str = json_string_value (identity_json);
790 audience_str = json_string_value (audience_json);
791
792 GNUNET_STRINGS_string_to_data (rnd_str,
793 strlen (rnd_str),
794 &ticket.rnd,
795 sizeof (uint64_t));
796 GNUNET_STRINGS_string_to_data (identity_str,
797 strlen (identity_str),
798 &ticket.identity,
799 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
800 GNUNET_STRINGS_string_to_data (audience_str,
801 strlen (audience_str),
802 &ticket.audience,
803 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
883 804
884 root = json_object (); 805 for (ego_entry = handle->ego_head;
885 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token); 806 NULL != ego_entry;
886 json_object_set_new (root, "token", json_string (token_str)); 807 ego_entry = ego_entry->next)
887 json_object_set_new (root, "token_type", json_string ("jwt")); 808 {
888 GNUNET_free (token_str); 809 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
810 &tmp_pk);
811 if (0 == memcmp (&ticket.identity,
812 &tmp_pk,
813 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
814 break;
815 }
816 if (NULL == ego_entry)
817 {
818 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
819 "Identity unknown (%s)\n", identity_str);
820 GNUNET_JSONAPI_document_delete (json_obj);
821 return;
822 }
823 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
889 824
890 result = json_dumps (root, JSON_INDENT(1)); 825 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
891 resp = GNUNET_REST_create_response (result); 826 handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp,
892 GNUNET_free (result); 827 identity_priv,
893 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 828 &ticket,
894 cleanup_handle (handle); 829 &finished_cont,
895 json_decref (root); 830 handle);
831 GNUNET_JSONAPI_document_delete (json_obj);
896} 832}
897 833
898
899/**
900 *
901 * Callback called when identity for token exchange has been found
902 *
903 * @param cls request handle
904 * @param ego the identity to use as issuer
905 * @param ctx user context
906 * @param name identity name
907 *
908 */
909static void 834static void
910exchange_token_ticket_cb (void *cls, 835consume_cont (void *cls,
911 struct GNUNET_IDENTITY_Ego *ego, 836 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
912 void **ctx, 837 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
913 const char *name)
914{ 838{
915 struct RequestHandle *handle = cls; 839 struct RequestHandle *handle = cls;
916 struct GNUNET_HashCode key; 840 struct GNUNET_JSONAPI_Resource *json_resource;
917 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; 841 json_t *value;
918 char* ticket_str;
919 842
920 handle->op = NULL; 843 if (NULL == identity)
844 {
845 GNUNET_SCHEDULER_add_now (&return_response, handle);
846 return;
847 }
848
849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
850 attr->name);
851 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
852 attr->name);
853 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
854
855 value = json_string (attr->data);
856 GNUNET_JSONAPI_resource_add_attr (json_resource,
857 "value",
858 value);
859 json_decref (value);
860}
921 861
922 if (NULL == ego) 862static void
863consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
864 const char* url,
865 void *cls)
866{
867 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
868 const char* identity_str;
869 const char* audience_str;
870 const char* rnd_str;
871
872 struct RequestHandle *handle = cls;
873 struct EgoEntry *ego_entry;
874 struct MHD_Response *resp;
875 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
876 struct GNUNET_JSONAPI_Document *json_obj;
877 struct GNUNET_JSONAPI_Resource *json_res;
878 struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
879 char term_data[handle->rest_handle->data_size+1];
880 json_t *rnd_json;
881 json_t *identity_json;
882 json_t *audience_json;
883 json_t *data_json;
884 json_error_t err;
885 struct GNUNET_JSON_Specification docspec[] = {
886 GNUNET_JSON_spec_jsonapi_document (&json_obj),
887 GNUNET_JSON_spec_end()
888 };
889
890 if (0 >= handle->rest_handle->data_size)
923 { 891 {
924 handle->emsg = GNUNET_strdup ("No identity found.");
925 GNUNET_SCHEDULER_add_now (&do_error, handle); 892 GNUNET_SCHEDULER_add_now (&do_error, handle);
926 return; 893 return;
927 } 894 }
928 895
929 //Get ticket 896 term_data[handle->rest_handle->data_size] = '\0';
930 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 897 GNUNET_memcpy (term_data,
931 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET), 898 handle->rest_handle->data,
932 &key); 899 handle->rest_handle->data_size);
933 900 data_json = json_loads (term_data,
934 if ( GNUNET_NO == 901 JSON_DECODE_ANY,
935 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 902 &err);
936 &key) ) 903 GNUNET_assert (GNUNET_OK ==
904 GNUNET_JSON_parse (data_json, docspec,
905 NULL, NULL));
906 json_decref (data_json);
907 if (NULL == json_obj)
908 {
909 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
910 "Unable to parse JSONAPI Object from %s\n",
911 term_data);
912 GNUNET_SCHEDULER_add_now (&do_error, handle);
913 return;
914 }
915 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
937 { 916 {
938 handle->emsg = GNUNET_strdup ("No ticket given."); 917 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
918 "Cannot create more than 1 resource! (Got %d)\n",
919 GNUNET_JSONAPI_document_resource_count (json_obj));
920 GNUNET_JSONAPI_document_delete (json_obj);
939 GNUNET_SCHEDULER_add_now (&do_error, handle); 921 GNUNET_SCHEDULER_add_now (&do_error, handle);
940 return; 922 return;
941 } 923 }
942 ticket_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 924 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
943 &key); 925 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
944 handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego); 926 GNUNET_REST_JSONAPI_IDENTITY_TICKET))
945 GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str, 927 {
946 &ticket); 928 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
929 "Unsupported JSON data type\n");
930 GNUNET_JSONAPI_document_delete (json_obj);
931 resp = GNUNET_REST_create_response (NULL);
932 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
933 cleanup_handle (handle);
934 return;
935 }
936 rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
937 "rnd");
938 identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
939 "identity");
940 audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
941 "audience");
942 rnd_str = json_string_value (rnd_json);
943 identity_str = json_string_value (identity_json);
944 audience_str = json_string_value (audience_json);
945
946 GNUNET_STRINGS_string_to_data (rnd_str,
947 strlen (rnd_str),
948 &ticket.rnd,
949 sizeof (uint64_t));
950 GNUNET_STRINGS_string_to_data (identity_str,
951 strlen (identity_str),
952 &ticket.identity,
953 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
954 GNUNET_STRINGS_string_to_data (audience_str,
955 strlen (audience_str),
956 &ticket.audience,
957 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
947 958
959 for (ego_entry = handle->ego_head;
960 NULL != ego_entry;
961 ego_entry = ego_entry->next)
962 {
963 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
964 &tmp_pk);
965 if (0 == memcmp (&ticket.audience,
966 &tmp_pk,
967 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
968 break;
969 }
970 if (NULL == ego_entry)
971 {
972 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
973 "Identity unknown (%s)\n", identity_str);
974 GNUNET_JSONAPI_document_delete (json_obj);
975 return;
976 }
977 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
978 handle->resp_object = GNUNET_JSONAPI_document_new ();
948 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); 979 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
949 handle->idp_op = GNUNET_IDENTITY_PROVIDER_exchange_ticket (handle->idp, 980 handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (handle->idp,
950 ticket, 981 identity_priv,
951 handle->priv_key, 982 &ticket,
952 &exchange_cont, 983 &consume_cont,
953 handle); 984 handle);
954 GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket); 985 GNUNET_JSONAPI_document_delete (json_obj);
955
956} 986}
957 987
958 988
959 989
960/** 990/**
961 * Respond to issue request
962 *
963 * @param con_handle the connection handle
964 * @param url the url
965 * @param cls the RequestHandle
966 */
967static void
968exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
969 const char* url,
970 void *cls)
971{
972 struct RequestHandle *handle = cls;
973
974 //Get token from GNS
975 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
976 "gns-master",
977 &exchange_token_ticket_cb,
978 handle);
979}
980
981/**
982 * Respond to OPTIONS request 991 * Respond to OPTIONS request
983 * 992 *
984 * @param con_handle the connection handle 993 * @param con_handle the connection handle
@@ -1013,15 +1022,17 @@ init_cont (struct RequestHandle *handle)
1013{ 1022{
1014 struct GNUNET_REST_RequestHandlerError err; 1023 struct GNUNET_REST_RequestHandlerError err;
1015 static const struct GNUNET_REST_RequestHandler handlers[] = { 1024 static const struct GNUNET_REST_RequestHandler handlers[] = {
1016 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont}, 1025 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont},
1017 //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont}, 1026 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont},
1018 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont}, 1027 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
1019 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &options_cont}, 1028 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
1020 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont}, 1029 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
1030 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER,
1031 &options_cont},
1021 GNUNET_REST_HANDLER_END 1032 GNUNET_REST_HANDLER_END
1022 }; 1033 };
1023 1034
1024 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, 1035 if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
1025 handlers, 1036 handlers,
1026 &err, 1037 &err,
1027 handle)) 1038 handle))
@@ -1092,19 +1103,8 @@ list_ego (void *cls,
1092 1103
1093} 1104}
1094 1105
1095/**
1096 * Function processing the REST call
1097 *
1098 * @param method HTTP method
1099 * @param url URL of the HTTP request
1100 * @param data body of the HTTP request (optional)
1101 * @param data_size length of the body
1102 * @param proc callback function for the result
1103 * @param proc_cls closure for callback function
1104 * @return GNUNET_OK if request accepted
1105 */
1106static void 1106static void
1107rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, 1107rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
1108 GNUNET_REST_ResultProcessor proc, 1108 GNUNET_REST_ResultProcessor proc,
1109 void *proc_cls) 1109 void *proc_cls)
1110{ 1110{
@@ -1114,10 +1114,9 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1114 handle->proc_cls = proc_cls; 1114 handle->proc_cls = proc_cls;
1115 handle->proc = proc; 1115 handle->proc = proc;
1116 handle->state = ID_REST_STATE_INIT; 1116 handle->state = ID_REST_STATE_INIT;
1117 handle->conndata_handle = conndata_handle; 1117 handle->rest_handle = rest_handle;
1118 1118
1119 1119 handle->url = GNUNET_strdup (rest_handle->url);
1120 handle->url = GNUNET_strdup (conndata_handle->url);
1121 if (handle->url[strlen (handle->url)-1] == '/') 1120 if (handle->url[strlen (handle->url)-1] == '/')
1122 handle->url[strlen (handle->url)-1] = '\0'; 1121 handle->url[strlen (handle->url)-1] = '\0';
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1162,8 +1161,8 @@ libgnunet_plugin_rest_identity_provider_init (void *cls)
1162 MHD_HTTP_METHOD_DELETE, 1161 MHD_HTTP_METHOD_DELETE,
1163 MHD_HTTP_METHOD_OPTIONS); 1162 MHD_HTTP_METHOD_OPTIONS);
1164 1163
1165 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1166 _("Identity Token REST API initialized\n")); 1165 _("Identity Provider REST API initialized\n"));
1167 return api; 1166 return api;
1168} 1167}
1169 1168
@@ -1184,8 +1183,8 @@ libgnunet_plugin_rest_identity_provider_done (void *cls)
1184 GNUNET_free_non_null (allow_methods); 1183 GNUNET_free_non_null (allow_methods);
1185 GNUNET_free (api); 1184 GNUNET_free (api);
1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "Identity Token REST plugin is finished\n"); 1186 "Identity Provider REST plugin is finished\n");
1188 return NULL; 1187 return NULL;
1189} 1188}
1190 1189
1191/* end of plugin_rest_gns.c */ 1190/* end of plugin_rest_identity_provider.c */