aboutsummaryrefslogtreecommitdiff
path: root/src/identity
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2015-07-10 16:17:30 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2015-07-10 16:17:30 +0000
commit9246b5973e3ae5eec1d51b35d942dd7e5e9f95d8 (patch)
tree45a4fad135ae25cb58be97e631e6116efce9e9f8 /src/identity
parent57eb2ec3125dbbf60a9d1a2635ddc19345e2e5c1 (diff)
downloadgnunet-9246b5973e3ae5eec1d51b35d942dd7e5e9f95d8.tar.gz
gnunet-9246b5973e3ae5eec1d51b35d942dd7e5e9f95d8.zip
- Identity token support
Diffstat (limited to 'src/identity')
-rw-r--r--src/identity/Makefile.am11
-rw-r--r--src/identity/plugin_rest_identity.c463
2 files changed, 346 insertions, 128 deletions
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index b0e7645b0..89f755fd9 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -56,7 +56,10 @@ bin_PROGRAMS = \
56 56
57libexec_PROGRAMS = \ 57libexec_PROGRAMS = \
58 gnunet-service-identity 58 gnunet-service-identity
59 59if HAVE_REST
60bin_PROGRAMS += \
61 gnunet-identity-token
62endif
60gnunet_service_identity_SOURCES = \ 63gnunet_service_identity_SOURCES = \
61 gnunet-service-identity.c 64 gnunet-service-identity.c
62gnunet_service_identity_LDADD = \ 65gnunet_service_identity_LDADD = \
@@ -72,6 +75,12 @@ gnunet_identity_LDADD = \
72 $(top_builddir)/src/util/libgnunetutil.la \ 75 $(top_builddir)/src/util/libgnunetutil.la \
73 $(GN_LIBINTL) 76 $(GN_LIBINTL)
74 77
78gnunet_identity_token_SOURCES = \
79 check_token.c
80gnunet_identity_token_LDADD = \
81 $(top_builddir)/src/util/libgnunetutil.la \
82 -ljansson -lmicrohttpd
83 $(GN_LIBINTL)
75 84
76if HAVE_TESTING 85if HAVE_TESTING
77check_PROGRAMS = \ 86check_PROGRAMS = \
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
index 11df90a70..870ed3446 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -30,21 +30,77 @@
30#include "gnunet_rest_lib.h" 30#include "gnunet_rest_lib.h"
31#include "microhttpd.h" 31#include "microhttpd.h"
32#include <jansson.h> 32#include <jansson.h>
33#include "gnunet_signatures.h"
33 34
35/**
36 * REST root namespace
37 */
34#define GNUNET_REST_API_NS_IDENTITY "/identity" 38#define GNUNET_REST_API_NS_IDENTITY "/identity"
35 39
40/**
41 * State while collecting all egos
42 */
36#define ID_REST_STATE_INIT 0 43#define ID_REST_STATE_INIT 0
37 44
45/**
46 * Done collecting egos
47 */
38#define ID_REST_STATE_POST_INIT 1 48#define ID_REST_STATE_POST_INIT 1
39 49
50/**
51 * Resource type
52 */
40#define GNUNET_REST_JSONAPI_IDENTITY_EGO "ego" 53#define GNUNET_REST_JSONAPI_IDENTITY_EGO "ego"
41 54
42#define GNUNET_REST_JSONAPI_IDENTITY_KEY "key" 55/**
56 * Name attribute
57 */
58#define GNUNET_REST_JSONAPI_IDENTITY_NAME "name"
43 59
60/**
61 * Attribute to rename "name" TODO we changed id to the pubkey
62 * so this can be unified with "name"
63 */
44#define GNUNET_REST_JSONAPI_IDENTITY_NEWNAME "newname" 64#define GNUNET_REST_JSONAPI_IDENTITY_NEWNAME "newname"
45 65
66/**
67 * URL parameter to change the subsytem for ego
68 */
46#define GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM "subsystem" 69#define GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM "subsystem"
47 70
71
72/**
73 * URL parameter to create a GNUid token for a specific audience
74 */
75#define GNUNET_REST_JSONAPI_IDENTITY_CREATE_TOKEN "create_token_for"
76
77/**
78 * Attribute containing the GNUid token if
79 * GNUNET_REST_JSONAPI_IDENTITY_CREATE_TOKEN was requested
80 */
81#define GNUNET_REST_JSONAPI_IDENTITY_GNUID "gnuid_token"
82
83/**
84 * Error messages
85 */
86#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
87#define GNUNET_REST_ERROR_NO_DATA "No data"
88
89/**
90 * GNUid token lifetime
91 */
92#define GNUNET_GNUID_TOKEN_EXPIRATION_SECONDS 360
93
94/**
95 * The configuration handle
96 */
97const struct GNUNET_CONFIGURATION_Handle *cfg;
98
99/**
100 * HTTP methods allows for this plugin
101 */
102static char* allow_methods;
103
48/** 104/**
49 * @brief struct returned by the initialization function of the plugin 105 * @brief struct returned by the initialization function of the plugin
50 */ 106 */
@@ -53,10 +109,9 @@ struct Plugin
53 const struct GNUNET_CONFIGURATION_Handle *cfg; 109 const struct GNUNET_CONFIGURATION_Handle *cfg;
54}; 110};
55 111
56const struct GNUNET_CONFIGURATION_Handle *cfg; 112/**
57 113 * The ego list
58static char* allow_methods; 114 */
59
60struct EgoEntry 115struct EgoEntry
61{ 116{
62 /** 117 /**
@@ -73,12 +128,12 @@ struct EgoEntry
73 * Ego Identifier 128 * Ego Identifier
74 */ 129 */
75 char *identifier; 130 char *identifier;
76 131
77 /** 132 /**
78 * Ego Pkey 133 * Public key string
79 */ 134 */
80 struct GNUNET_CRYPTO_EcdsaPublicKey pk; 135 char *keystring;
81 136
82 /** 137 /**
83 * The Ego 138 * The Ego
84 */ 139 */
@@ -98,6 +153,9 @@ struct RequestHandle
98 */ 153 */
99 struct EgoEntry *ego_tail; 154 struct EgoEntry *ego_tail;
100 155
156 /**
157 * Handle to the rest connection
158 */
101 struct RestConnectionDataHandle *conndata_handle; 159 struct RestConnectionDataHandle *conndata_handle;
102 160
103 /** 161 /**
@@ -126,11 +184,6 @@ struct RequestHandle
126 struct GNUNET_SCHEDULER_Task * timeout_task; 184 struct GNUNET_SCHEDULER_Task * timeout_task;
127 185
128 /** 186 /**
129 * The root of the received JSON or NULL
130 */
131 json_t *json_root;
132
133 /**
134 * The plugin result processor 187 * The plugin result processor
135 */ 188 */
136 GNUNET_REST_ResultProcessor proc; 189 GNUNET_REST_ResultProcessor proc;
@@ -170,6 +223,11 @@ struct RequestHandle
170 */ 223 */
171 const char* method; 224 const char* method;
172 225
226 /**
227 * Error response message
228 */
229 char *emsg;
230
173}; 231};
174 232
175 233
@@ -194,12 +252,15 @@ cleanup_handle (struct RequestHandle *handle)
194 GNUNET_free (handle->subsys); 252 GNUNET_free (handle->subsys);
195 if (NULL != handle->url) 253 if (NULL != handle->url)
196 GNUNET_free (handle->url); 254 GNUNET_free (handle->url);
255 if (NULL != handle->emsg)
256 GNUNET_free (handle->emsg);
197 for (ego_entry = handle->ego_head; 257 for (ego_entry = handle->ego_head;
198 NULL != ego_entry;) 258 NULL != ego_entry;)
199 { 259 {
200 ego_tmp = ego_entry; 260 ego_tmp = ego_entry;
201 ego_entry = ego_entry->next; 261 ego_entry = ego_entry->next;
202 GNUNET_free (ego_tmp->identifier); 262 GNUNET_free (ego_tmp->identifier);
263 GNUNET_free (ego_tmp->keystring);
203 GNUNET_free (ego_tmp); 264 GNUNET_free (ego_tmp);
204 } 265 }
205 GNUNET_free (handle); 266 GNUNET_free (handle);
@@ -217,9 +278,100 @@ do_error (void *cls,
217 const struct GNUNET_SCHEDULER_TaskContext *tc) 278 const struct GNUNET_SCHEDULER_TaskContext *tc)
218{ 279{
219 struct RequestHandle *handle = cls; 280 struct RequestHandle *handle = cls;
220 struct MHD_Response *resp = GNUNET_REST_create_json_response (NULL); 281 struct MHD_Response *resp;
282 char *json_error;
283
284 GNUNET_asprintf (&json_error,
285 "{Error while processing request: %s}",
286 &handle->emsg);
287
288 resp = GNUNET_REST_create_json_response (json_error);
221 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); 289 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
222 cleanup_handle (handle); 290 cleanup_handle (handle);
291 GNUNET_free (json_error);
292}
293
294/**
295 * Build a GNUid token for identity
296 * @param handle the handle
297 * @param ego_entry the ego to build the token for
298 * @param name name of the ego
299 * @param token_aud token audience
300 * @param token the resulting gnuid token
301 */
302static void
303make_gnuid_token (struct RequestHandle *handle,
304 struct EgoEntry *ego_entry,
305 const char *name,
306 const char *token_aud,
307 char **token)
308{
309 uint64_t time;
310 char *header_str;
311 char *payload_str;
312 char *header_base64;
313 char *payload_base64;
314 char *sig_str;
315 json_t *header;
316 json_t *payload;
317 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
318 struct GNUNET_CRYPTO_EcdsaSignature sig;
319 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
320
321 time = GNUNET_TIME_absolute_get().abs_value_us;
322 header = json_object ();
323 json_object_set_new (header, "alg", json_string ("ED512"));
324 json_object_set_new (header, "typ", json_string ("JWT"));
325
326 payload = json_object ();
327 json_object_set_new (payload, "iss", json_string (ego_entry->keystring));
328 json_object_set_new (payload, "sub", json_string (name));
329 json_object_set_new (payload, "nbf", json_integer (time));
330 json_object_set_new (payload, "iat", json_integer (time));
331 json_object_set_new (payload, "exp", json_integer (time+GNUNET_GNUID_TOKEN_EXPIRATION_SECONDS));
332 json_object_set_new (payload, "aud", json_string (token_aud));
333 header_str = json_dumps (header, JSON_COMPACT);
334 GNUNET_STRINGS_base64_encode (header_str,
335 strlen (header_str),
336 &header_base64);
337 char* padding = strtok(header_base64, "=");
338 while (NULL != padding)
339 padding = strtok(NULL, "=");
340
341 payload_str = json_dumps (payload, JSON_COMPACT);
342 GNUNET_STRINGS_base64_encode (payload_str,
343 strlen (payload_str),
344 &payload_base64);
345 padding = strtok(payload_base64, "=");
346 while (NULL != padding)
347 padding = strtok(NULL, "=");
348
349 GNUNET_asprintf (token, "%s,%s", header_base64, payload_base64);
350 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
351 purpose =
352 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
353 strlen (*token));
354 purpose->size =
355 htonl (strlen (*token) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
356 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
357 memcpy (&purpose[1], *token, strlen (*token));
358 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
359 purpose,
360 &sig))
361 GNUNET_break(0);
362 GNUNET_free (*token);
363 sig_str = GNUNET_STRINGS_data_to_string_alloc (&sig,
364 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
365 GNUNET_asprintf (token, "%s.%s.%s",
366 header_base64, payload_base64, sig_str);
367 GNUNET_free (sig_str);
368 GNUNET_free (header_str);
369 GNUNET_free (header_base64);
370 GNUNET_free (payload_str);
371 GNUNET_free (payload_base64);
372 GNUNET_free (purpose);
373 json_decref (header);
374 json_decref (payload);
223} 375}
224 376
225/** 377/**
@@ -241,12 +393,11 @@ get_ego_for_subsys (void *cls,
241 struct JsonApiResource *json_resource; 393 struct JsonApiResource *json_resource;
242 struct EgoEntry *ego_entry; 394 struct EgoEntry *ego_entry;
243 struct MHD_Response *resp; 395 struct MHD_Response *resp;
244 json_t *key_json; 396 json_t *name_json;
245 char *result_str; 397 char *result_str;
246 char *keystring;
247 398
248 json_object = GNUNET_REST_jsonapi_object_new (); 399 json_object = GNUNET_REST_jsonapi_object_new ();
249 400
250 for (ego_entry = handle->ego_head; 401 for (ego_entry = handle->ego_head;
251 NULL != ego_entry; 402 NULL != ego_entry;
252 ego_entry = ego_entry->next) 403 ego_entry = ego_entry->next)
@@ -255,18 +406,20 @@ get_ego_for_subsys (void *cls,
255 continue; 406 continue;
256 if (NULL == name) 407 if (NULL == name)
257 continue; 408 continue;
258 json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->identifier); 409 json_resource = GNUNET_REST_jsonapi_resource_new
259 keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ego_entry->pk); 410 (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->keystring);
260 key_json = json_string (keystring); 411 name_json = json_string (ego_entry->identifier);
261 GNUNET_REST_jsonapi_resource_add_attr (json_resource, GNUNET_REST_JSONAPI_IDENTITY_KEY, key_json); 412 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
262 json_decref (key_json); 413 GNUNET_REST_JSONAPI_IDENTITY_NAME,
263 GNUNET_free (keystring); 414 name_json);
415 json_decref (name_json);
264 GNUNET_REST_jsonapi_object_resource_add (json_object, json_resource); 416 GNUNET_REST_jsonapi_object_resource_add (json_object, json_resource);
265 break; 417 break;
266 } 418 }
267 if (0 == GNUNET_REST_jsonapi_object_resource_count (json_object)) 419 if (0 == GNUNET_REST_jsonapi_object_resource_count (json_object))
268 { 420 {
269 GNUNET_REST_jsonapi_object_delete (json_object); 421 GNUNET_REST_jsonapi_object_delete (json_object);
422 handle->emsg = GNUNET_strdup("No identity matches results!");
270 GNUNET_SCHEDULER_add_now (&do_error, handle); 423 GNUNET_SCHEDULER_add_now (&do_error, handle);
271 return; 424 return;
272 } 425 }
@@ -282,7 +435,9 @@ get_ego_for_subsys (void *cls,
282/** 435/**
283 * Create a response with requested ego(s) 436 * Create a response with requested ego(s)
284 * 437 *
285 * @param handle the RequestHandle 438 * @param con the Rest handle
439 * @param url the requested url
440 * @param cls the request handle
286 */ 441 */
287static void 442static void
288ego_info_response (struct RestConnectionDataHandle *con, 443ego_info_response (struct RestConnectionDataHandle *con,
@@ -290,16 +445,20 @@ ego_info_response (struct RestConnectionDataHandle *con,
290 void *cls) 445 void *cls)
291{ 446{
292 const char *egoname; 447 const char *egoname;
293 char *keystring;
294 char *result_str; 448 char *result_str;
295 char *subsys_val; 449 char *subsys_val;
450 char *create_token_for;
451 char *token;
452 char *keystring;
296 struct RequestHandle *handle = cls; 453 struct RequestHandle *handle = cls;
297 struct EgoEntry *ego_entry; 454 struct EgoEntry *ego_entry;
298 struct GNUNET_HashCode key; 455 struct GNUNET_HashCode key;
299 struct MHD_Response *resp; 456 struct MHD_Response *resp;
300 struct JsonApiObject *json_object; 457 struct JsonApiObject *json_object;
301 struct JsonApiResource *json_resource; 458 struct JsonApiResource *json_resource;
302 json_t *key_str; 459 json_t *name_str;
460 json_t *token_str;
461
303 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY)) 462 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY))
304 { 463 {
305 resp = GNUNET_REST_create_json_response (NULL); 464 resp = GNUNET_REST_create_json_response (NULL);
@@ -307,8 +466,26 @@ ego_info_response (struct RestConnectionDataHandle *con,
307 cleanup_handle (handle); 466 cleanup_handle (handle);
308 return; 467 return;
309 } 468 }
310 if ( (strlen (GNUNET_REST_API_NS_IDENTITY) == strlen (handle->url) )) { 469 egoname = NULL;
311 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM, strlen (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM), &key); 470 keystring = NULL;
471 if (strlen (GNUNET_REST_API_NS_IDENTITY) < strlen (handle->url))
472 {
473 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1];
474 //Return all egos
475 for (ego_entry = handle->ego_head;
476 NULL != ego_entry;
477 ego_entry = ego_entry->next)
478 {
479 if ( (NULL != keystring) && (0 != strcmp (keystring, ego_entry->keystring)) )
480 continue;
481 egoname = ego_entry->identifier;
482 }
483 }
484
485 if ( NULL == egoname ) {
486 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM,
487 strlen (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM),
488 &key);
312 if ( GNUNET_YES == 489 if ( GNUNET_YES ==
313 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 490 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
314 &key) ) 491 &key) )
@@ -327,13 +504,21 @@ ego_info_response (struct RestConnectionDataHandle *con,
327 } 504 }
328 } 505 }
329 } 506 }
507
508 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_CREATE_TOKEN,
509 strlen (GNUNET_REST_JSONAPI_IDENTITY_CREATE_TOKEN),
510 &key);
511
512 //Token audience
513 create_token_for = NULL;
514 if ( GNUNET_YES ==
515 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
516 &key) )
517 create_token_for = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
518 &key);
519
330 json_object = GNUNET_REST_jsonapi_object_new (); 520 json_object = GNUNET_REST_jsonapi_object_new ();
331 egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1];
332 521
333 if (strlen (GNUNET_REST_API_NS_IDENTITY) == strlen (handle->url))
334 {
335 egoname = NULL;
336 }
337 //Return all egos 522 //Return all egos
338 for (ego_entry = handle->ego_head; 523 for (ego_entry = handle->ego_head;
339 NULL != ego_entry; 524 NULL != ego_entry;
@@ -341,19 +526,34 @@ ego_info_response (struct RestConnectionDataHandle *con,
341 { 526 {
342 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) 527 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) )
343 continue; 528 continue;
344 keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ego_entry->pk); 529 json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO,
345 json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->identifier); 530 ego_entry->keystring);
346 key_str = json_string (keystring); 531 name_str = json_string (ego_entry->identifier);
347 GNUNET_REST_jsonapi_resource_add_attr (json_resource, 532 GNUNET_REST_jsonapi_resource_add_attr (
348 GNUNET_REST_JSONAPI_IDENTITY_KEY, 533 json_resource,
349 key_str); 534 GNUNET_REST_JSONAPI_IDENTITY_NAME,
350 json_decref (key_str); 535 name_str);
351 GNUNET_free (keystring); 536 json_decref (name_str);
537 if (NULL != create_token_for)
538 {
539 make_gnuid_token (handle,
540 ego_entry,
541 ego_entry->identifier,
542 create_token_for,
543 &token);
544 token_str = json_string (token);
545 GNUNET_free (token);
546 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
547 GNUNET_REST_JSONAPI_IDENTITY_GNUID,
548 token_str);
549 json_decref (token_str);
550 }
352 GNUNET_REST_jsonapi_object_resource_add (json_object, json_resource); 551 GNUNET_REST_jsonapi_object_resource_add (json_object, json_resource);
353 } 552 }
354 if (0 == GNUNET_REST_jsonapi_object_resource_count (json_object)) 553 if (0 == GNUNET_REST_jsonapi_object_resource_count (json_object))
355 { 554 {
356 GNUNET_REST_jsonapi_object_delete (json_object); 555 GNUNET_REST_jsonapi_object_delete (json_object);
556 handle->emsg = GNUNET_strdup ("No identities found!");
357 GNUNET_SCHEDULER_add_now (&do_error, handle); 557 GNUNET_SCHEDULER_add_now (&do_error, handle);
358 return; 558 return;
359 } 559 }
@@ -366,6 +566,12 @@ ego_info_response (struct RestConnectionDataHandle *con,
366 cleanup_handle (handle); 566 cleanup_handle (handle);
367} 567}
368 568
569/**
570 * Processing finished
571 *
572 * @param cls request handle
573 * @param emsg error message
574 */
369static void 575static void
370do_finished (void *cls, const char *emsg) 576do_finished (void *cls, const char *emsg)
371{ 577{
@@ -375,6 +581,7 @@ do_finished (void *cls, const char *emsg)
375 handle->op = NULL; 581 handle->op = NULL;
376 if (NULL != emsg) 582 if (NULL != emsg)
377 { 583 {
584 handle->emsg = GNUNET_strdup (emsg);
378 GNUNET_SCHEDULER_add_now (&do_error, handle); 585 GNUNET_SCHEDULER_add_now (&do_error, handle);
379 return; 586 return;
380 } 587 }
@@ -383,40 +590,13 @@ do_finished (void *cls, const char *emsg)
383 cleanup_handle (handle); 590 cleanup_handle (handle);
384} 591}
385 592
386static void 593/**
387edit_finished (void *cls, const char *emsg) 594 * Create a new ego
388{ 595 *
389 struct RequestHandle *handle = cls; 596 * @param con rest handle
390 struct MHD_Response *resp; 597 * @param url url
391 598 * @param cls request handle
392 handle->op = NULL; 599 */
393 if (NULL != emsg)
394 {
395 GNUNET_SCHEDULER_add_now (&do_error, handle);
396 return;
397 }
398 resp = GNUNET_REST_create_json_response (NULL);
399 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
400 cleanup_handle (handle);
401}
402
403static void
404create_finished (void *cls, const char *emsg)
405{
406 struct RequestHandle *handle = cls;
407 struct MHD_Response *resp;
408
409 handle->op = NULL;
410 if (NULL != emsg)
411 {
412 GNUNET_SCHEDULER_add_now (&do_error, handle);
413 return;
414 }
415 resp = GNUNET_REST_create_json_response (NULL);
416 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
417 cleanup_handle (handle);
418}
419
420static void 600static void
421ego_create_cont (struct RestConnectionDataHandle *con, 601ego_create_cont (struct RestConnectionDataHandle *con,
422 const char *url, 602 const char *url,
@@ -433,11 +613,13 @@ ego_create_cont (struct RestConnectionDataHandle *con,
433 613
434 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) 614 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
435 { 615 {
616 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
436 GNUNET_SCHEDULER_add_now (&do_error, handle); 617 GNUNET_SCHEDULER_add_now (&do_error, handle);
437 return; 618 return;
438 } 619 }
439 if (0 >= handle->data_size) 620 if (0 >= handle->data_size)
440 { 621 {
622 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
441 GNUNET_SCHEDULER_add_now (&do_error, handle); 623 GNUNET_SCHEDULER_add_now (&do_error, handle);
442 return; 624 return;
443 } 625 }
@@ -452,6 +634,7 @@ ego_create_cont (struct RestConnectionDataHandle *con,
452 if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj)) 634 if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj))
453 { 635 {
454 GNUNET_REST_jsonapi_object_delete (json_obj); 636 GNUNET_REST_jsonapi_object_delete (json_obj);
637 handle->emsg = GNUNET_strdup ("Provided resource count invalid");
455 GNUNET_SCHEDULER_add_now (&do_error, handle); 638 GNUNET_SCHEDULER_add_now (&do_error, handle);
456 return; 639 return;
457 } 640 }
@@ -464,10 +647,11 @@ ego_create_cont (struct RestConnectionDataHandle *con,
464 cleanup_handle (handle); 647 cleanup_handle (handle);
465 return; 648 return;
466 } 649 }
467 egoname_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_KEY_ID); 650 egoname_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NAME);
468 if (!json_is_string (egoname_json)) 651 if (!json_is_string (egoname_json))
469 { 652 {
470 GNUNET_REST_jsonapi_object_delete (json_obj); 653 GNUNET_REST_jsonapi_object_delete (json_obj);
654 handle->emsg = GNUNET_strdup ("No name provided");
471 GNUNET_SCHEDULER_add_now (&do_error, handle); 655 GNUNET_SCHEDULER_add_now (&do_error, handle);
472 return; 656 return;
473 } 657 }
@@ -489,7 +673,7 @@ ego_create_cont (struct RestConnectionDataHandle *con,
489 GNUNET_REST_jsonapi_object_delete (json_obj); 673 GNUNET_REST_jsonapi_object_delete (json_obj);
490 handle->op = GNUNET_IDENTITY_create (handle->identity_handle, 674 handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
491 handle->name, 675 handle->name,
492 &create_finished, 676 &do_finished,
493 handle); 677 handle);
494} 678}
495 679
@@ -503,8 +687,8 @@ ego_create_cont (struct RestConnectionDataHandle *con,
503 */ 687 */
504static void 688static void
505ego_edit_cont (struct RestConnectionDataHandle *con, 689ego_edit_cont (struct RestConnectionDataHandle *con,
506 const char *url, 690 const char *url,
507 void *cls) 691 void *cls)
508{ 692{
509 struct JsonApiObject *json_obj; 693 struct JsonApiObject *json_obj;
510 struct JsonApiResource *json_res; 694 struct JsonApiResource *json_res;
@@ -513,29 +697,31 @@ ego_edit_cont (struct RestConnectionDataHandle *con,
513 struct MHD_Response *resp; 697 struct MHD_Response *resp;
514 json_t *subsys_json; 698 json_t *subsys_json;
515 json_t *name_json; 699 json_t *name_json;
516 const char *egoname; 700 const char *keystring;
517 const char *subsys; 701 const char *subsys;
518 const char *newname; 702 const char *newname;
519 char term_data[handle->data_size+1]; 703 char term_data[handle->data_size+1];
520 int ego_exists = GNUNET_NO; 704 int ego_exists = GNUNET_NO;
521 705
522 if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url)) 706 if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url))
523 { 707 {
708 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
524 GNUNET_SCHEDULER_add_now (&do_error, handle); 709 GNUNET_SCHEDULER_add_now (&do_error, handle);
525 return; 710 return;
526 } 711 }
527 712
528 egoname = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; 713 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1];
714
529 for (ego_entry = handle->ego_head; 715 for (ego_entry = handle->ego_head;
530 NULL != ego_entry; 716 NULL != ego_entry;
531 ego_entry = ego_entry->next) 717 ego_entry = ego_entry->next)
532 { 718 {
533 if (0 == strcasecmp (egoname, ego_entry->identifier)) 719 if (0 != strcasecmp (keystring, ego_entry->keystring))
534 { 720 continue;
535 ego_exists = GNUNET_YES; 721 ego_exists = GNUNET_YES;
536 break; 722 break;
537 }
538 } 723 }
724
539 if (GNUNET_NO == ego_exists) 725 if (GNUNET_NO == ego_exists)
540 { 726 {
541 resp = GNUNET_REST_create_json_response (NULL); 727 resp = GNUNET_REST_create_json_response (NULL);
@@ -546,6 +732,7 @@ ego_edit_cont (struct RestConnectionDataHandle *con,
546 732
547 if (0 >= handle->data_size) 733 if (0 >= handle->data_size)
548 { 734 {
735 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
549 GNUNET_SCHEDULER_add_now (&do_error, handle); 736 GNUNET_SCHEDULER_add_now (&do_error, handle);
550 return; 737 return;
551 } 738 }
@@ -556,60 +743,75 @@ ego_edit_cont (struct RestConnectionDataHandle *con,
556 743
557 if (NULL == json_obj) 744 if (NULL == json_obj)
558 { 745 {
746 handle->emsg = GNUNET_strdup ("Data invalid");
559 GNUNET_SCHEDULER_add_now (&do_error, handle); 747 GNUNET_SCHEDULER_add_now (&do_error, handle);
560 return; 748 return;
561 } 749 }
750
562 if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj)) 751 if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj))
563 { 752 {
564 GNUNET_REST_jsonapi_object_delete (json_obj); 753 GNUNET_REST_jsonapi_object_delete (json_obj);
754 handle->emsg = GNUNET_strdup ("Resource amount invalid");
565 GNUNET_SCHEDULER_add_now (&do_error, handle); 755 GNUNET_SCHEDULER_add_now (&do_error, handle);
566 return; 756 return;
567 } 757 }
568 json_res = GNUNET_REST_jsonapi_object_get_resource (json_obj, 0); 758 json_res = GNUNET_REST_jsonapi_object_get_resource (json_obj, 0);
759
569 if (GNUNET_NO == GNUNET_REST_jsonapi_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) 760 if (GNUNET_NO == GNUNET_REST_jsonapi_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO))
570 { 761 {
571 GNUNET_REST_jsonapi_object_delete (json_obj); 762 GNUNET_REST_jsonapi_object_delete (json_obj);
763 handle->emsg = GNUNET_strdup ("Resource type invalid");
572 GNUNET_SCHEDULER_add_now (&do_error, handle); 764 GNUNET_SCHEDULER_add_now (&do_error, handle);
573 return; 765 return;
574 } 766 }
575 //This is a rename 767
576 name_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NEWNAME); 768 //This is a rename
577 if (NULL != name_json) 769 name_json = GNUNET_REST_jsonapi_resource_read_attr (json_res,
770 GNUNET_REST_JSONAPI_IDENTITY_NEWNAME);
771 if ((NULL != name_json) && json_is_string (name_json))
578 { 772 {
579 newname = NULL; 773 newname = json_string_value (name_json);
580 if (json_is_string (name_json)) 774 for (ego_entry = handle->ego_head;
775 NULL != ego_entry;
776 ego_entry = ego_entry->next)
581 { 777 {
582 newname = json_string_value (name_json); 778 if (0 == strcasecmp (newname, ego_entry->identifier) &&
583 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, 779 0 != strcasecmp (keystring, ego_entry->keystring))
584 egoname, 780 {
585 newname, 781 //Ego with same name not allowed
586 &edit_finished, 782 GNUNET_REST_jsonapi_object_delete (json_obj);
587 handle); 783 resp = GNUNET_REST_create_json_response (NULL);
588 GNUNET_REST_jsonapi_object_delete (json_obj); 784 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
589 return; 785 cleanup_handle (handle);
786 return;
787 }
590 } 788 }
789 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
790 ego_entry->identifier,
791 newname,
792 &do_finished,
793 handle);
794 GNUNET_REST_jsonapi_object_delete (json_obj);
795 return;
591 } 796 }
592 797
798 //Set subsystem
593 subsys_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM); 799 subsys_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM);
594 if (NULL != subsys_json) 800 if ( (NULL != subsys_json) && json_is_string (subsys_json))
595 { 801 {
596 subsys = NULL; 802 subsys = json_string_value (subsys_json);
597 if (json_is_string (subsys_json)) 803 GNUNET_asprintf (&handle->subsys, "%s", subsys);
598 { 804 GNUNET_REST_jsonapi_object_delete (json_obj);
599 subsys = json_string_value (subsys_json); 805 handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
600 GNUNET_asprintf (&handle->subsys, "%s", subsys); 806 handle->subsys,
601 GNUNET_REST_jsonapi_object_delete (json_obj); 807 ego_entry->ego,
602 handle->op = GNUNET_IDENTITY_set (handle->identity_handle, 808 &do_finished,
603 handle->subsys, 809 handle);
604 ego_entry->ego, 810 return;
605 &edit_finished,
606 handle);
607 return;
608 }
609 } 811 }
610 GNUNET_REST_jsonapi_object_delete (json_obj); 812 GNUNET_REST_jsonapi_object_delete (json_obj);
813 handle->emsg = GNUNET_strdup ("Subsystem not provided");
611 GNUNET_SCHEDULER_add_now (&do_error, handle); 814 GNUNET_SCHEDULER_add_now (&do_error, handle);
612
613} 815}
614 816
615void 817void
@@ -617,7 +819,7 @@ ego_delete_cont (struct RestConnectionDataHandle *con_handle,
617 const char* url, 819 const char* url,
618 void *cls) 820 void *cls)
619{ 821{
620 const char *egoname; 822 const char *keystring;
621 struct EgoEntry *ego_entry; 823 struct EgoEntry *ego_entry;
622 struct MHD_Response *resp; 824 struct MHD_Response *resp;
623 struct RequestHandle *handle = cls; 825 struct RequestHandle *handle = cls;
@@ -625,20 +827,20 @@ ego_delete_cont (struct RestConnectionDataHandle *con_handle,
625 827
626 if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url)) 828 if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url))
627 { 829 {
830 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
628 GNUNET_SCHEDULER_add_now (&do_error, handle); 831 GNUNET_SCHEDULER_add_now (&do_error, handle);
629 return; 832 return;
630 } 833 }
631 834
632 egoname = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; 835 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1];
633 for (ego_entry = handle->ego_head; 836 for (ego_entry = handle->ego_head;
634 NULL != ego_entry; 837 NULL != ego_entry;
635 ego_entry = ego_entry->next) 838 ego_entry = ego_entry->next)
636 { 839 {
637 if (0 == strcasecmp (egoname, ego_entry->identifier)) 840 if (0 != strcasecmp (keystring, ego_entry->keystring))
638 { 841 continue;
639 ego_exists = GNUNET_YES; 842 ego_exists = GNUNET_YES;
640 break; 843 break;
641 }
642 } 844 }
643 if (GNUNET_NO == ego_exists) 845 if (GNUNET_NO == ego_exists)
644 { 846 {
@@ -648,7 +850,7 @@ ego_delete_cont (struct RestConnectionDataHandle *con_handle,
648 return; 850 return;
649 } 851 }
650 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, 852 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
651 egoname, 853 ego_entry->identifier,
652 &do_finished, 854 &do_finished,
653 handle); 855 handle);
654 856
@@ -698,7 +900,10 @@ init_cont (struct RequestHandle *handle)
698 }; 900 };
699 901
700 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle)) 902 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
903 {
904 handle->emsg = GNUNET_strdup ("Request unsupported");
701 GNUNET_SCHEDULER_add_now (&do_error, handle); 905 GNUNET_SCHEDULER_add_now (&do_error, handle);
906 }
702} 907}
703 908
704/** 909/**
@@ -742,6 +947,7 @@ list_ego (void *cls,
742{ 947{
743 struct RequestHandle *handle = cls; 948 struct RequestHandle *handle = cls;
744 struct EgoEntry *ego_entry; 949 struct EgoEntry *ego_entry;
950 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
745 951
746 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) 952 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
747 { 953 {
@@ -751,7 +957,9 @@ list_ego (void *cls,
751 } 957 }
752 if (ID_REST_STATE_INIT == handle->state) { 958 if (ID_REST_STATE_INIT == handle->state) {
753 ego_entry = GNUNET_new (struct EgoEntry); 959 ego_entry = GNUNET_new (struct EgoEntry);
754 GNUNET_IDENTITY_ego_get_public_key (ego, &(ego_entry->pk)); 960 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
961 ego_entry->keystring =
962 GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
755 ego_entry->ego = ego; 963 ego_entry->ego = ego;
756 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier); 964 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
757 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); 965 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
@@ -795,7 +1003,8 @@ rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
795 "Connecting...\n"); 1003 "Connecting...\n");
796 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, 1004 handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
797 &list_ego, 1005 &list_ego,
798 handle); 1006 handle);
1007 GNUNET_strdup ("Timeout");
799 handle->timeout_task = 1008 handle->timeout_task =
800 GNUNET_SCHEDULER_add_delayed (handle->timeout, 1009 GNUNET_SCHEDULER_add_delayed (handle->timeout,
801 &do_error, 1010 &do_error,
@@ -816,9 +1025,9 @@ void *
816libgnunet_plugin_rest_identity_init (void *cls) 1025libgnunet_plugin_rest_identity_init (void *cls)
817{ 1026{
818 static struct Plugin plugin; 1027 static struct Plugin plugin;
819 cfg = cls;
820 struct GNUNET_REST_Plugin *api; 1028 struct GNUNET_REST_Plugin *api;
821 1029
1030 cfg = cls;
822 if (NULL != plugin.cfg) 1031 if (NULL != plugin.cfg)
823 return NULL; /* can only initialize once! */ 1032 return NULL; /* can only initialize once! */
824 memset (&plugin, 0, sizeof (struct Plugin)); 1033 memset (&plugin, 0, sizeof (struct Plugin));