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