aboutsummaryrefslogtreecommitdiff
path: root/src/identity
diff options
context:
space:
mode:
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-08-13 08:51:19 +0200
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-08-13 08:51:19 +0200
commit6371b64774428e83ff83ada88bda354356718aca (patch)
treea2a68aafcf1f6faa8a84648baaf0731da1136346 /src/identity
parent6656d6c3e7111075572c042ae714c9710f30273b (diff)
downloadgnunet-6371b64774428e83ff83ada88bda354356718aca.tar.gz
gnunet-6371b64774428e83ff83ada88bda354356718aca.zip
fix build; move rest plugins to separate folder
Diffstat (limited to 'src/identity')
-rw-r--r--src/identity/Makefile.am19
-rw-r--r--src/identity/plugin_rest_identity.c1319
2 files changed, 0 insertions, 1338 deletions
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index e7104f0c3..1f21fc65d 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -39,14 +39,6 @@ bin_PROGRAMS = \
39libexec_PROGRAMS = \ 39libexec_PROGRAMS = \
40 gnunet-service-identity 40 gnunet-service-identity
41 41
42if HAVE_MHD
43if HAVE_JSON
44plugin_LTLIBRARIES = \
45 libgnunet_plugin_rest_identity.la
46endif
47endif
48
49
50gnunet_service_identity_SOURCES = \ 42gnunet_service_identity_SOURCES = \
51 gnunet-service-identity.c 43 gnunet-service-identity.c
52gnunet_service_identity_LDADD = \ 44gnunet_service_identity_LDADD = \
@@ -55,17 +47,6 @@ gnunet_service_identity_LDADD = \
55 $(GN_LIBINTL) 47 $(GN_LIBINTL)
56 48
57 49
58libgnunet_plugin_rest_identity_la_SOURCES = \
59 plugin_rest_identity.c
60libgnunet_plugin_rest_identity_la_LIBADD = \
61 libgnunetidentity.la \
62 $(top_builddir)/src/rest/libgnunetrest.la \
63 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
64 $(LTLIBINTL) -ljansson -lmicrohttpd
65libgnunet_plugin_rest_identity_la_LDFLAGS = \
66 $(GN_PLUGIN_LDFLAGS)
67
68
69gnunet_identity_SOURCES = \ 50gnunet_identity_SOURCES = \
70 gnunet-identity.c 51 gnunet-identity.c
71gnunet_identity_LDADD = \ 52gnunet_identity_LDADD = \
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
deleted file mode 100644
index 9f1765a63..000000000
--- a/src/identity/plugin_rest_identity.c
+++ /dev/null
@@ -1,1319 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18/**
19 * @author Martin Schanzenbach
20 * @author Philippe Buschmann
21 * @file identity/plugin_rest_identity.c
22 * @brief GNUnet Identity REST plugin
23 */
24
25#include "platform.h"
26#include "gnunet_rest_plugin.h"
27#include "gnunet_identity_service.h"
28#include "gnunet_rest_lib.h"
29#include "microhttpd.h"
30#include <jansson.h>
31
32/**
33 * Identity Namespace
34 */
35#define GNUNET_REST_API_NS_IDENTITY "/identity"
36
37/**
38 * Identity Namespace with public key specifier
39 */
40#define GNUNET_REST_API_NS_IDENTITY_ALL "/identity/all"
41
42/**
43 * Identity Namespace with public key specifier
44 */
45#define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey"
46
47/**
48 * Identity Namespace with public key specifier
49 */
50#define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name"
51
52/**
53 * Identity Subsystem Namespace
54 */
55#define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem"
56
57/**
58 * Parameter public key
59 */
60#define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey"
61
62/**
63 * Parameter subsystem
64 */
65#define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem"
66
67/**
68 * Parameter name
69 */
70#define GNUNET_REST_IDENTITY_PARAM_NAME "name"
71
72/**
73 * Parameter new name
74 */
75#define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname"
76
77/**
78 * Error message Unknown Error
79 */
80#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
81
82/**
83 * Error message No identity found
84 */
85#define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
86
87/**
88 * Error message Missing identity name
89 */
90#define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name"
91
92/**
93 * Error message Missing identity name
94 */
95#define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key"
96
97/**
98 * Error message No data
99 */
100#define GNUNET_REST_ERROR_NO_DATA "No data"
101
102/**
103 * Error message Data invalid
104 */
105#define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
106
107/**
108 * State while collecting all egos
109 */
110#define ID_REST_STATE_INIT 0
111
112/**
113 * Done collecting egos
114 */
115#define ID_REST_STATE_POST_INIT 1
116
117/**
118 * The configuration handle
119 */
120const struct GNUNET_CONFIGURATION_Handle *cfg;
121
122/**
123 * HTTP methods allows for this plugin
124 */
125static char* allow_methods;
126
127/**
128 * @brief struct returned by the initialization function of the plugin
129 */
130struct Plugin
131{
132 const struct GNUNET_CONFIGURATION_Handle *cfg;
133};
134
135/**
136 * The ego list
137 */
138struct EgoEntry
139{
140 /**
141 * DLL
142 */
143 struct EgoEntry *next;
144
145 /**
146 * DLL
147 */
148 struct EgoEntry *prev;
149
150 /**
151 * Ego Identifier
152 */
153 char *identifier;
154
155 /**
156 * Public key string
157 */
158 char *keystring;
159
160 /**
161 * The Ego
162 */
163 struct GNUNET_IDENTITY_Ego *ego;
164};
165
166/**
167 * The request handle
168 */
169struct RequestHandle
170{
171 /**
172 * The data from the REST request
173 */
174 const char* data;
175
176 /**
177 * The name to look up
178 */
179 char *name;
180
181 /**
182 * the length of the REST data
183 */
184 size_t data_size;
185
186
187 /**
188 * Ego list
189 */
190 struct EgoEntry *ego_head;
191
192 /**
193 * Ego list
194 */
195 struct EgoEntry *ego_tail;
196
197 /**
198 * The processing state
199 */
200 int state;
201
202 /**
203 * Handle to Identity service.
204 */
205 struct GNUNET_IDENTITY_Handle *identity_handle;
206
207 /**
208 * IDENTITY Operation
209 */
210 struct GNUNET_IDENTITY_Operation *op;
211
212 /**
213 * Rest connection
214 */
215 struct GNUNET_REST_RequestHandle *rest_handle;
216
217 /**
218 * Desired timeout for the lookup (default is no timeout).
219 */
220 struct GNUNET_TIME_Relative timeout;
221
222 /**
223 * ID of a task associated with the resolution process.
224 */
225 struct GNUNET_SCHEDULER_Task *timeout_task;
226
227 /**
228 * The plugin result processor
229 */
230 GNUNET_REST_ResultProcessor proc;
231
232 /**
233 * The closure of the result processor
234 */
235 void *proc_cls;
236
237 /**
238 * The url
239 */
240 char *url;
241
242 /**
243 * Error response message
244 */
245 char *emsg;
246
247 /**
248 * Response code
249 */
250 int response_code;
251
252};
253
254/**
255 * Cleanup lookup handle
256 * @param handle Handle to clean up
257 */
258static void
259cleanup_handle (void *cls)
260{
261 struct RequestHandle *handle = cls;
262 struct EgoEntry *ego_entry;
263 struct EgoEntry *ego_tmp;
264
265 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
266 if (NULL != handle->timeout_task)
267 {
268 GNUNET_SCHEDULER_cancel (handle->timeout_task);
269 handle->timeout_task = NULL;
270 }
271
272 if (NULL != handle->url)
273 GNUNET_free(handle->url);
274 if (NULL != handle->emsg)
275 GNUNET_free(handle->emsg);
276 if (NULL != handle->name)
277 GNUNET_free (handle->name);
278 if (NULL != handle->identity_handle)
279 GNUNET_IDENTITY_disconnect (handle->identity_handle);
280
281 for (ego_entry = handle->ego_head;
282 NULL != ego_entry;)
283 {
284 ego_tmp = ego_entry;
285 ego_entry = ego_entry->next;
286 GNUNET_free(ego_tmp->identifier);
287 GNUNET_free(ego_tmp->keystring);
288 GNUNET_free(ego_tmp);
289 }
290
291 GNUNET_free(handle);
292}
293
294/**
295 * Task run on errors. Reports an error and cleans up everything.
296 *
297 * @param cls the `struct RequestHandle`
298 */
299static void
300do_error (void *cls)
301{
302 struct RequestHandle *handle = cls;
303 struct MHD_Response *resp;
304 json_t *json_error = json_object();
305 char *response;
306
307 if (NULL == handle->emsg)
308 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_ERROR_UNKNOWN);
309
310 json_object_set_new(json_error,"error", json_string(handle->emsg));
311
312 if (0 == handle->response_code)
313 handle->response_code = MHD_HTTP_OK;
314 response = json_dumps (json_error, 0);
315 resp = GNUNET_REST_create_response (response);
316 handle->proc (handle->proc_cls, resp, handle->response_code);
317 json_decref(json_error);
318 GNUNET_free(response);
319 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
320}
321
322
323
324/**
325 * Get EgoEntry from list with either a public key or a name
326 * If public key and name are not NULL, it returns the public key result first
327 *
328 * @param handle the RequestHandle
329 * @param pubkey the public key of an identity (only one can be NULL)
330 * @param name the name of an identity (only one can be NULL)
331 * @return EgoEntry or NULL if not found
332 */
333struct EgoEntry*
334get_egoentry(struct RequestHandle *handle, char* pubkey, char *name)
335{
336 struct EgoEntry *ego_entry;
337 if (NULL != pubkey)
338 {
339 for (ego_entry = handle->ego_head;
340 NULL != ego_entry;
341 ego_entry = ego_entry->next)
342 {
343 if (0 != strcasecmp (pubkey, ego_entry->keystring))
344 continue;
345 return ego_entry;
346 }
347 }
348 if (NULL != name)
349 {
350 for (ego_entry = handle->ego_head;
351 NULL != ego_entry;
352 ego_entry = ego_entry->next)
353 {
354 if (0 != strcasecmp (name, ego_entry->identifier))
355 continue;
356 return ego_entry;
357 }
358 }
359 return NULL;
360}
361
362
363/**
364 * Callback for GET Request with subsystem
365 *
366 * @param cls the RequestHandle
367 * @param ego the Ego found
368 * @param ctx the context
369 * @param name the id of the ego
370 */
371static void
372ego_get_for_subsystem (void *cls,
373 struct GNUNET_IDENTITY_Ego *ego,
374 void **ctx,
375 const char *name)
376{
377 struct RequestHandle *handle = cls;
378 struct MHD_Response *resp;
379 struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
380 json_t *json_root;
381 char *result_str;
382 char *public_key_string;
383
384 if(NULL == ego)
385 {
386 handle->response_code = MHD_HTTP_NOT_FOUND;
387 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
388 GNUNET_SCHEDULER_add_now (&do_error, handle);
389 return;
390 }
391
392 GNUNET_IDENTITY_ego_get_public_key(ego,&public_key);
393 public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key);
394
395 // create json with subsystem identity
396 json_root = json_object ();
397 json_object_set_new (json_root,
398 GNUNET_REST_IDENTITY_PARAM_PUBKEY,
399 json_string(public_key_string));
400 json_object_set_new (json_root,
401 GNUNET_REST_IDENTITY_PARAM_NAME,
402 json_string(name));
403
404 result_str = json_dumps (json_root, 0);
405 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
406 resp = GNUNET_REST_create_response (result_str);
407
408 json_decref (json_root);
409 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
410 GNUNET_free(result_str);
411 GNUNET_free(public_key_string);
412 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
413}
414
415/**
416 * Handle identity GET request for subsystem
417 *
418 * @param con_handle the connection handle
419 * @param url the url
420 * @param cls the RequestHandle
421 */
422void
423ego_get_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
424 const char* url,
425 void *cls)
426{
427 struct RequestHandle *handle = cls;
428 char *subsystem;
429
430 if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
431 {
432 handle->emsg = GNUNET_strdup("Missing subsystem name");
433 GNUNET_SCHEDULER_add_now (&do_error, handle);
434 return;
435 }
436 subsystem = &handle->url[strlen (
437 GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
438 //requested default identity of subsystem
439 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
440
441 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
442 subsystem,
443 &ego_get_for_subsystem,
444 handle);
445
446 if (NULL == handle->op)
447 {
448 handle->response_code = MHD_HTTP_NOT_FOUND;
449 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
450 GNUNET_SCHEDULER_add_now (&do_error, handle);
451 return;
452 }
453}
454
455
456/**
457 * Handle identity GET request - responds with all identities
458 *
459 * @param con_handle the connection handle
460 * @param url the url
461 * @param cls the RequestHandle
462 */
463void
464ego_get_all (struct GNUNET_REST_RequestHandle *con_handle,
465 const char* url,
466 void *cls)
467{
468 struct RequestHandle *handle = cls;
469 struct EgoEntry *ego_entry;
470 struct MHD_Response *resp;
471 json_t *json_root;
472 json_t *json_ego;
473 char *result_str;
474
475 json_root = json_array ();
476 //Return ego/egos
477 for (ego_entry = handle->ego_head;
478 NULL != ego_entry; ego_entry = ego_entry->next)
479 {
480 json_ego = json_object ();
481 json_object_set_new (json_ego,
482 GNUNET_REST_IDENTITY_PARAM_PUBKEY,
483 json_string (ego_entry->keystring));
484 json_object_set_new (json_ego,
485 GNUNET_REST_IDENTITY_PARAM_NAME,
486 json_string (ego_entry->identifier));
487 json_array_append (json_root, json_ego);
488 json_decref (json_ego);
489 }
490
491 if ((size_t) 0 == json_array_size (json_root))
492 {
493 json_decref (json_root);
494 handle->response_code = MHD_HTTP_NOT_FOUND;
495 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
496 GNUNET_SCHEDULER_add_now (&do_error, handle);
497 return;
498 }
499
500 result_str = json_dumps (json_root, 0);
501 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
502 resp = GNUNET_REST_create_response (result_str);
503
504 json_decref (json_root);
505 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
506 GNUNET_free(result_str);
507 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
508}
509
510
511/**
512 * Responds with the ego_entry identity
513 *
514 * @param handle the struct RequestHandle
515 * @param ego_entry the struct EgoEntry for the response
516 */
517void
518ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
519{
520 struct MHD_Response *resp;
521 json_t *json_ego;
522 char *result_str;
523
524 json_ego = json_object ();
525 json_object_set_new (json_ego,
526 GNUNET_REST_IDENTITY_PARAM_PUBKEY,
527 json_string (ego_entry->keystring));
528 json_object_set_new (json_ego,
529 GNUNET_REST_IDENTITY_PARAM_NAME,
530 json_string (ego_entry->identifier));
531
532 result_str = json_dumps (json_ego, 0);
533 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
534 resp = GNUNET_REST_create_response (result_str);
535 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
536
537 json_decref (json_ego);
538 GNUNET_free(result_str);
539 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
540}
541
542
543/**
544 * Handle identity GET request with a public key
545 *
546 * @param con_handle the connection handle
547 * @param url the url
548 * @param cls the RequestHandle
549 */
550void
551ego_get_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
552 const char* url,
553 void *cls)
554{
555 struct RequestHandle *handle = cls;
556 struct EgoEntry *ego_entry;
557 char *keystring;
558
559 keystring = NULL;
560
561 if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
562 {
563 handle->response_code = MHD_HTTP_NOT_FOUND;
564 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
565 GNUNET_SCHEDULER_add_now (&do_error, handle);
566 return;
567 }
568 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
569 ego_entry = get_egoentry(handle, keystring, NULL);
570
571 if (NULL == ego_entry)
572 {
573 handle->response_code = MHD_HTTP_NOT_FOUND;
574 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
575 GNUNET_SCHEDULER_add_now (&do_error, handle);
576 return;
577 }
578
579 ego_get_response(handle, ego_entry);
580}
581
582/**
583 * Handle identity GET request with a name
584 *
585 * @param con_handle the connection handle
586 * @param url the url
587 * @param cls the RequestHandle
588 */
589void
590ego_get_name (struct GNUNET_REST_RequestHandle *con_handle,
591 const char* url,
592 void *cls)
593{
594 struct RequestHandle *handle = cls;
595 struct EgoEntry *ego_entry;
596 char *egoname;
597
598 egoname = NULL;
599
600 if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
601 {
602 handle->response_code = MHD_HTTP_NOT_FOUND;
603 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
604 GNUNET_SCHEDULER_add_now (&do_error, handle);
605 return;
606 }
607 egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
608 ego_entry = get_egoentry(handle, NULL, egoname);
609
610 if (NULL == ego_entry)
611 {
612 handle->response_code = MHD_HTTP_NOT_FOUND;
613 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
614 GNUNET_SCHEDULER_add_now (&do_error, handle);
615 return;
616 }
617
618 ego_get_response(handle, ego_entry);
619}
620
621
622/**
623 * Processing finished
624 *
625 * @param cls request handle
626 * @param emsg error message
627 */
628static void
629do_finished (void *cls, const char *emsg)
630{
631 struct RequestHandle *handle = cls;
632 struct MHD_Response *resp;
633
634 handle->op = NULL;
635 if (NULL != emsg)
636 {
637 handle->emsg = GNUNET_strdup(emsg);
638 GNUNET_SCHEDULER_add_now (&do_error, handle);
639 return;
640 }
641 if (0 == handle->response_code)
642 {
643 handle->response_code = MHD_HTTP_NO_CONTENT;
644 }
645 resp = GNUNET_REST_create_response (NULL);
646 handle->proc (handle->proc_cls, resp, handle->response_code);
647 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
648}
649
650
651/**
652 * Processing edit ego with EgoEntry ego_entry
653 *
654 * @param handle the struct RequestHandle
655 * @param ego_entry the struct EgoEntry we want to edit
656 */
657void
658ego_edit (struct RequestHandle *handle, struct EgoEntry *ego_entry)
659{
660 struct EgoEntry *ego_entry_tmp;
661 struct MHD_Response *resp;
662 json_t *data_js;
663 json_error_t err;
664 char *newname;
665 char term_data[handle->data_size + 1];
666 int json_state;
667
668 //if no data
669 if (0 >= handle->data_size)
670 {
671 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
672 GNUNET_SCHEDULER_add_now (&do_error, handle);
673 return;
674 }
675 //if not json
676 term_data[handle->data_size] = '\0';
677 GNUNET_memcpy(term_data, handle->data, handle->data_size);
678 data_js = json_loads (term_data,JSON_DECODE_ANY,&err);
679
680 if (NULL == data_js)
681 {
682 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
683 GNUNET_SCHEDULER_add_now (&do_error, handle);
684 return;
685 }
686
687 newname = NULL;
688 //NEW NAME
689 json_state = 0;
690 json_state = json_unpack(data_js,
691 "{s:s!}",
692 GNUNET_REST_IDENTITY_PARAM_NEWNAME,
693 &newname);
694 //Change name with pubkey or name identifier
695 if (0 != json_state)
696 {
697
698 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
699 GNUNET_SCHEDULER_add_now (&do_error, handle);
700 json_decref (data_js);
701 return;
702 }
703
704 if (NULL == newname)
705 {
706 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
707 GNUNET_SCHEDULER_add_now (&do_error, handle);
708 json_decref (data_js);
709 return;
710 }
711
712 if (0 >= strlen (newname))
713 {
714 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
715 GNUNET_SCHEDULER_add_now (&do_error, handle);
716 json_decref (data_js);
717 return;
718 }
719
720 ego_entry_tmp = get_egoentry (handle, NULL, newname);
721 if (NULL != ego_entry_tmp)
722 {
723 //Ego with same name not allowed (even if its the ego we change)
724 resp = GNUNET_REST_create_response (NULL);
725 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
726 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
727 json_decref (data_js);
728 return;
729 }
730 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
731 ego_entry->identifier,
732 newname,
733 &do_finished,
734 handle);
735 if (NULL == handle->op)
736 {
737 handle->emsg = GNUNET_strdup("Rename failed");
738 GNUNET_SCHEDULER_add_now (&do_error, handle);
739 json_decref (data_js);
740 return;
741 }
742 json_decref (data_js);
743 return;
744
745}
746
747
748/**
749 * Handle identity PUT request with public key
750 *
751 * @param con_handle the connection handle
752 * @param url the url
753 * @param cls the RequestHandle
754 */
755void
756ego_edit_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
757 const char* url,
758 void *cls)
759{
760 struct RequestHandle *handle = cls;
761 struct EgoEntry *ego_entry;
762 char *keystring;
763
764 keystring = NULL;
765
766 if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
767 {
768 handle->response_code = MHD_HTTP_NOT_FOUND;
769 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
770 GNUNET_SCHEDULER_add_now (&do_error, handle);
771 return;
772 }
773 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
774 ego_entry = get_egoentry(handle, keystring, NULL);
775
776 if (NULL == ego_entry)
777 {
778 handle->response_code = MHD_HTTP_NOT_FOUND;
779 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
780 GNUNET_SCHEDULER_add_now (&do_error, handle);
781 return;
782 }
783
784 ego_edit(handle,ego_entry);
785}
786
787/**
788 * Handle identity PUT request with name
789 *
790 * @param con_handle the connection handle
791 * @param url the url
792 * @param cls the RequestHandle
793 */
794void
795ego_edit_name (struct GNUNET_REST_RequestHandle *con_handle,
796 const char* url,
797 void *cls)
798{
799 struct RequestHandle *handle = cls;
800 struct EgoEntry *ego_entry;
801 char *name;
802
803 name = NULL;
804
805 if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
806 {
807 handle->response_code = MHD_HTTP_NOT_FOUND;
808 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
809 GNUNET_SCHEDULER_add_now (&do_error, handle);
810 return;
811 }
812 name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
813 ego_entry = get_egoentry(handle, NULL, name);
814
815 if (NULL == ego_entry)
816 {
817 handle->response_code = MHD_HTTP_NOT_FOUND;
818 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
819 GNUNET_SCHEDULER_add_now (&do_error, handle);
820 return;
821 }
822
823 ego_edit(handle,ego_entry);
824}
825
826/**
827 * Handle identity subsystem PUT request with name
828 *
829 * @param con_handle the connection handle
830 * @param url the url
831 * @param cls the RequestHandle
832 */
833void
834ego_edit_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
835 const char* url,
836 void *cls)
837{
838 struct RequestHandle *handle = cls;
839 struct EgoEntry *ego_entry;
840 json_t *data_js;
841 json_error_t err;
842 char *newsubsys;
843 char *name;
844 char term_data[handle->data_size + 1];
845 int json_state;
846
847 name = NULL;
848
849 if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
850 {
851 handle->response_code = MHD_HTTP_NOT_FOUND;
852 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
853 GNUNET_SCHEDULER_add_now (&do_error, handle);
854 return;
855 }
856 name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM)+1];
857 ego_entry = get_egoentry(handle, NULL, name);
858
859 if (NULL == ego_entry)
860 {
861 handle->response_code = MHD_HTTP_NOT_FOUND;
862 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
863 GNUNET_SCHEDULER_add_now (&do_error, handle);
864 return;
865 }
866
867 //if no data
868 if (0 >= handle->data_size)
869 {
870 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
871 GNUNET_SCHEDULER_add_now (&do_error, handle);
872 return;
873 }
874 //if not json
875 term_data[handle->data_size] = '\0';
876 GNUNET_memcpy(term_data, handle->data, handle->data_size);
877 data_js = json_loads (term_data,JSON_DECODE_ANY,&err);
878
879 if (NULL == data_js)
880 {
881 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
882 GNUNET_SCHEDULER_add_now (&do_error, handle);
883 return;
884 }
885
886 newsubsys = NULL;
887 //SUBSYSTEM
888 json_state = 0;
889 json_state = json_unpack(data_js,
890 "{s:s!}",
891 GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM,
892 &newsubsys);
893 //Change subsystem with pubkey or name identifier
894 if (0 != json_state)
895 {
896 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
897 GNUNET_SCHEDULER_add_now (&do_error, handle);
898 json_decref (data_js);
899 return;
900 }
901
902 if (NULL == newsubsys)
903 {
904 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
905 GNUNET_SCHEDULER_add_now (&do_error, handle);
906 json_decref (data_js);
907 return;
908 }
909
910 if (0 >= strlen (newsubsys))
911 {
912 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
913 GNUNET_SCHEDULER_add_now (&do_error, handle);
914 json_decref (data_js);
915 return;
916 }
917
918 handle->response_code = MHD_HTTP_NO_CONTENT;
919 handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
920 newsubsys,
921 ego_entry->ego,
922 &do_finished,
923 handle);
924 if (NULL == handle->op)
925 {
926 handle->emsg = GNUNET_strdup("Setting subsystem failed");
927 GNUNET_SCHEDULER_add_now (&do_error, handle);
928 return;
929 }
930 json_decref (data_js);
931 return;
932
933}
934
935/**
936 * Handle identity POST request
937 *
938 * @param con_handle the connection handle
939 * @param url the url
940 * @param cls the RequestHandle
941 */
942void
943ego_create (struct GNUNET_REST_RequestHandle *con_handle,
944 const char* url,
945 void *cls)
946{
947 struct RequestHandle *handle = cls;
948 struct EgoEntry *ego_entry;
949 struct MHD_Response *resp;
950 json_t *data_js;
951 json_error_t err;
952 char* egoname;
953 int json_unpack_state;
954 char term_data[handle->data_size + 1];
955
956 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
957 {
958 GNUNET_SCHEDULER_add_now (&do_error, handle);
959 return;
960 }
961
962 if (0 >= handle->data_size)
963 {
964 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
965 GNUNET_SCHEDULER_add_now (&do_error, handle);
966 return;
967 }
968 term_data[handle->data_size] = '\0';
969 GNUNET_memcpy(term_data, handle->data, handle->data_size);
970 data_js = json_loads (term_data,
971 JSON_DECODE_ANY,
972 &err);
973 if (NULL == data_js)
974 {
975 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
976 GNUNET_SCHEDULER_add_now (&do_error, handle);
977 json_decref (data_js);
978 return;
979 }
980 json_unpack_state = 0;
981 json_unpack_state = json_unpack(data_js,
982 "{s:s!}",
983 GNUNET_REST_IDENTITY_PARAM_NAME,
984 &egoname);
985 if (0 != json_unpack_state)
986 {
987 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
988 GNUNET_SCHEDULER_add_now (&do_error, handle);
989 json_decref (data_js);
990 return;
991 }
992
993 if (NULL == egoname)
994 {
995 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
996 GNUNET_SCHEDULER_add_now (&do_error, handle);
997 json_decref (data_js);
998 return;
999 }
1000 if (0 >= strlen (egoname))
1001 {
1002 json_decref (data_js);
1003 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
1004 GNUNET_SCHEDULER_add_now (&do_error, handle);
1005 return;
1006 }
1007 GNUNET_STRINGS_utf8_tolower(egoname, egoname);
1008 for (ego_entry = handle->ego_head;
1009 NULL != ego_entry; ego_entry = ego_entry->next)
1010 {
1011 if (0 == strcasecmp (egoname, ego_entry->identifier))
1012 {
1013 resp = GNUNET_REST_create_response (NULL);
1014 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
1015 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
1016 json_decref (data_js);
1017 return;
1018 }
1019 }
1020 handle->name = GNUNET_strdup(egoname);
1021 json_decref (data_js);
1022 handle->response_code = MHD_HTTP_CREATED;
1023 handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name,
1024 &do_finished, handle);
1025}
1026
1027/**
1028 * Handle identity DELETE request with public key
1029 *
1030 * @param con_handle the connection handle
1031 * @param url the url
1032 * @param cls the RequestHandle
1033 */
1034void
1035ego_delete_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
1036 const char* url,
1037 void *cls)
1038{
1039 struct RequestHandle *handle = cls;
1040 struct EgoEntry *ego_entry;
1041 char *keystring;
1042
1043 keystring = NULL;
1044
1045 if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
1046 {
1047 handle->response_code = MHD_HTTP_NOT_FOUND;
1048 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
1049 GNUNET_SCHEDULER_add_now (&do_error, handle);
1050 return;
1051 }
1052 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
1053 ego_entry = get_egoentry(handle, keystring, NULL);
1054
1055 if (NULL == ego_entry)
1056 {
1057 handle->response_code = MHD_HTTP_NOT_FOUND;
1058 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
1059 GNUNET_SCHEDULER_add_now (&do_error, handle);
1060 return;
1061 }
1062
1063 handle->response_code = MHD_HTTP_NO_CONTENT;
1064 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
1065 ego_entry->identifier,
1066 &do_finished,
1067 handle);
1068}
1069
1070
1071/**
1072 * Handle identity DELETE request with name
1073 *
1074 * @param con_handle the connection handle
1075 * @param url the url
1076 * @param cls the RequestHandle
1077 */
1078void
1079ego_delete_name (struct GNUNET_REST_RequestHandle *con_handle,
1080 const char* url,
1081 void *cls)
1082{
1083 struct RequestHandle *handle = cls;
1084 struct EgoEntry *ego_entry;
1085 char *name;
1086
1087 name = NULL;
1088
1089 if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
1090 {
1091 handle->response_code = MHD_HTTP_NOT_FOUND;
1092 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
1093 GNUNET_SCHEDULER_add_now (&do_error, handle);
1094 return;
1095 }
1096 name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
1097 ego_entry = get_egoentry(handle, NULL, name);
1098
1099 if (NULL == ego_entry)
1100 {
1101 handle->response_code = MHD_HTTP_NOT_FOUND;
1102 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
1103 GNUNET_SCHEDULER_add_now (&do_error, handle);
1104 return;
1105 }
1106
1107 handle->response_code = MHD_HTTP_NO_CONTENT;
1108 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
1109 ego_entry->identifier,
1110 &do_finished,
1111 handle);
1112}
1113
1114
1115/**
1116 * Respond to OPTIONS request
1117 *
1118 * @param con_handle the connection handle
1119 * @param url the url
1120 * @param cls the RequestHandle
1121 */
1122static void
1123options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
1124 void *cls)
1125{
1126 struct MHD_Response *resp;
1127 struct RequestHandle *handle = cls;
1128
1129 //For now, independent of path return all options
1130 resp = GNUNET_REST_create_response (NULL);
1131 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1132 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1133 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
1134 return;
1135}
1136
1137/**
1138 * Handle rest request
1139 *
1140 * @param handle the request handle
1141 */
1142static void
1143init_cont (struct RequestHandle *handle)
1144{
1145 struct GNUNET_REST_RequestHandlerError err;
1146 static const struct GNUNET_REST_RequestHandler handlers[] = {
1147 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ALL, &ego_get_all },
1148 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_get_pubkey },
1149 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1150 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, &ego_get_subsystem },
1151 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_edit_pubkey },
1152 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1153 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, &ego_edit_subsystem },
1154 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1155 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_delete_pubkey },
1156 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_delete_name },
1157 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1158 GNUNET_REST_HANDLER_END
1159 };
1160
1161 if (GNUNET_NO
1162 == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
1163 handle))
1164 {
1165 handle->response_code = err.error_code;
1166 GNUNET_SCHEDULER_add_now (&do_error, handle);
1167 }
1168}
1169
1170/**
1171 * If listing is enabled, prints information about the egos.
1172 *
1173 * This function is initially called for all egos and then again
1174 * whenever a ego's identifier changes or if it is deleted. At the
1175 * end of the initial pass over all egos, the function is once called
1176 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
1177 * be invoked in the future or that there was an error.
1178 *
1179 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
1180 * this function is only called ONCE, and 'NULL' being passed in
1181 * 'ego' does indicate an error (i.e. name is taken or no default
1182 * value is known). If 'ego' is non-NULL and if '*ctx'
1183 * is set in those callbacks, the value WILL be passed to a subsequent
1184 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
1185 * that one was not NULL).
1186 *
1187 * When an identity is renamed, this function is called with the
1188 * (known) ego but the NEW identifier.
1189 *
1190 * When an identity is deleted, this function is called with the
1191 * (known) ego and "NULL" for the 'identifier'. In this case,
1192 * the 'ego' is henceforth invalid (and the 'ctx' should also be
1193 * cleaned up).
1194 *
1195 * @param cls closure
1196 * @param ego ego handle
1197 * @param ctx context for application to store data for this ego
1198 * (during the lifetime of this process, initially NULL)
1199 * @param identifier identifier assigned by the user for this ego,
1200 * NULL if the user just deleted the ego and it
1201 * must thus no longer be used
1202 */
1203static void
1204init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx,
1205 const char *identifier)
1206{
1207 struct RequestHandle *handle = cls;
1208 struct EgoEntry *ego_entry;
1209 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1210
1211 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1212 {
1213 handle->state = ID_REST_STATE_POST_INIT;
1214 init_cont (handle);
1215 return;
1216 }
1217 if (ID_REST_STATE_INIT == handle->state)
1218 {
1219 ego_entry = GNUNET_new(struct EgoEntry);
1220 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1221 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
1222 ego_entry->ego = ego;
1223 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
1224 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail,
1225 ego_entry);
1226 }
1227}
1228
1229/**
1230 * Function processing the REST call
1231 *
1232 * @param method HTTP method
1233 * @param url URL of the HTTP request
1234 * @param data body of the HTTP request (optional)
1235 * @param data_size length of the body
1236 * @param proc callback function for the result
1237 * @param proc_cls closure for callback function
1238 * @return GNUNET_OK if request accepted
1239 */
1240static void
1241rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1242 GNUNET_REST_ResultProcessor proc, void *proc_cls)
1243{
1244 struct RequestHandle *handle = GNUNET_new(struct RequestHandle);
1245
1246 handle->response_code = 0;
1247 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1248 handle->proc_cls = proc_cls;
1249 handle->proc = proc;
1250 handle->rest_handle = rest_handle;
1251 handle->data = rest_handle->data;
1252 handle->data_size = rest_handle->data_size;
1253
1254 handle->url = GNUNET_strdup(rest_handle->url);
1255 if (handle->url[strlen (handle->url) - 1] == '/')
1256 handle->url[strlen (handle->url) - 1] = '\0';
1257 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1258
1259 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
1260
1261 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1262 &do_error, handle);
1263
1264 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1265}
1266
1267/**
1268 * Entry point for the plugin.
1269 *
1270 * @param cls Config info
1271 * @return NULL on error, otherwise the plugin context
1272 */
1273void *
1274libgnunet_plugin_rest_identity_init (void *cls)
1275{
1276 static struct Plugin plugin;
1277 struct GNUNET_REST_Plugin *api;
1278
1279 cfg = cls;
1280 if (NULL != plugin.cfg)
1281 return NULL; /* can only initialize once! */
1282 memset (&plugin, 0, sizeof(struct Plugin));
1283 plugin.cfg = cfg;
1284 api = GNUNET_new(struct GNUNET_REST_Plugin);
1285 api->cls = &plugin;
1286 api->name = GNUNET_REST_API_NS_IDENTITY;
1287 api->process_request = &rest_process_request;
1288 GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s",
1289 MHD_HTTP_METHOD_GET,
1290 MHD_HTTP_METHOD_POST,
1291 MHD_HTTP_METHOD_PUT,
1292 MHD_HTTP_METHOD_DELETE,
1293 MHD_HTTP_METHOD_OPTIONS);
1294
1295 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n"));
1296 return api;
1297}
1298
1299/**
1300 * Exit point from the plugin.
1301 *
1302 * @param cls the plugin context (as returned by "init")
1303 * @return always NULL
1304 */
1305void *
1306libgnunet_plugin_rest_identity_done (void *cls)
1307{
1308 struct GNUNET_REST_Plugin *api = cls;
1309 struct Plugin *plugin = api->cls;
1310 plugin->cfg = NULL;
1311
1312 GNUNET_free_non_null(allow_methods);
1313 GNUNET_free(api);
1314 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
1315 return NULL;
1316}
1317
1318/* end of plugin_rest_identity.c */
1319