diff options
Diffstat (limited to 'src/reclaim/plugin_rest_pabc.c')
-rw-r--r-- | src/reclaim/plugin_rest_pabc.c | 666 |
1 files changed, 666 insertions, 0 deletions
diff --git a/src/reclaim/plugin_rest_pabc.c b/src/reclaim/plugin_rest_pabc.c new file mode 100644 index 000000000..6603fb888 --- /dev/null +++ b/src/reclaim/plugin_rest_pabc.c | |||
@@ -0,0 +1,666 @@ | |||
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 | * @file reclaim/plugin_rest_pabc.c | ||
23 | * @brief GNUnet pabc REST plugin | ||
24 | * | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "microhttpd.h" | ||
28 | #include <inttypes.h> | ||
29 | #include <jansson.h> | ||
30 | #include <pabc/pabc.h> | ||
31 | #include "gnunet_reclaim_lib.h" | ||
32 | #include "gnunet_reclaim_service.h" | ||
33 | #include "gnunet_rest_lib.h" | ||
34 | #include "gnunet_rest_plugin.h" | ||
35 | #include "gnunet_signatures.h" | ||
36 | #include "pabc_helper.h" | ||
37 | |||
38 | /** | ||
39 | * REST root namespace | ||
40 | */ | ||
41 | #define GNUNET_REST_API_NS_PABC "/pabc" | ||
42 | |||
43 | /** | ||
44 | * Credential request endpoint | ||
45 | */ | ||
46 | #define GNUNET_REST_API_NS_PABC_CR "/pabc/cr" | ||
47 | |||
48 | /** | ||
49 | * The configuration handle | ||
50 | */ | ||
51 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
52 | |||
53 | /** | ||
54 | * HTTP methods allows for this plugin | ||
55 | */ | ||
56 | static char *allow_methods; | ||
57 | |||
58 | /** | ||
59 | * @brief struct returned by the initialization function of the plugin | ||
60 | */ | ||
61 | struct Plugin | ||
62 | { | ||
63 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
64 | }; | ||
65 | |||
66 | |||
67 | struct RequestHandle | ||
68 | { | ||
69 | /** | ||
70 | * DLL | ||
71 | */ | ||
72 | struct RequestHandle *next; | ||
73 | |||
74 | /** | ||
75 | * DLL | ||
76 | */ | ||
77 | struct RequestHandle *prev; | ||
78 | |||
79 | /** | ||
80 | * Rest connection | ||
81 | */ | ||
82 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
83 | |||
84 | /** | ||
85 | * Desired timeout for the lookup (default is no timeout). | ||
86 | */ | ||
87 | struct GNUNET_TIME_Relative timeout; | ||
88 | |||
89 | /** | ||
90 | * ID of a task associated with the resolution process. | ||
91 | */ | ||
92 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
93 | |||
94 | /** | ||
95 | * The plugin result processor | ||
96 | */ | ||
97 | GNUNET_REST_ResultProcessor proc; | ||
98 | |||
99 | /** | ||
100 | * The closure of the result processor | ||
101 | */ | ||
102 | void *proc_cls; | ||
103 | |||
104 | /** | ||
105 | * The url | ||
106 | */ | ||
107 | char *url; | ||
108 | |||
109 | /** | ||
110 | * Error response message | ||
111 | */ | ||
112 | char *emsg; | ||
113 | |||
114 | /** | ||
115 | * Reponse code | ||
116 | */ | ||
117 | int response_code; | ||
118 | |||
119 | /** | ||
120 | * Response object | ||
121 | */ | ||
122 | json_t *resp_object; | ||
123 | }; | ||
124 | |||
125 | /** | ||
126 | * DLL | ||
127 | */ | ||
128 | static struct RequestHandle *requests_head; | ||
129 | |||
130 | /** | ||
131 | * DLL | ||
132 | */ | ||
133 | static struct RequestHandle *requests_tail; | ||
134 | |||
135 | |||
136 | /** | ||
137 | * Cleanup lookup handle | ||
138 | * @param handle Handle to clean up | ||
139 | */ | ||
140 | static void | ||
141 | cleanup_handle (void *cls) | ||
142 | { | ||
143 | struct RequestHandle *handle = cls; | ||
144 | |||
145 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); | ||
146 | if (NULL != handle->resp_object) | ||
147 | json_decref (handle->resp_object); | ||
148 | if (NULL != handle->timeout_task) | ||
149 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
150 | if (NULL != handle->url) | ||
151 | GNUNET_free (handle->url); | ||
152 | if (NULL != handle->emsg) | ||
153 | GNUNET_free (handle->emsg); | ||
154 | GNUNET_CONTAINER_DLL_remove (requests_head, | ||
155 | requests_tail, | ||
156 | handle); | ||
157 | GNUNET_free (handle); | ||
158 | } | ||
159 | |||
160 | |||
161 | /** | ||
162 | * Task run on error, sends error message. Cleans up everything. | ||
163 | * | ||
164 | * @param cls the `struct RequestHandle` | ||
165 | */ | ||
166 | static void | ||
167 | do_error (void *cls) | ||
168 | { | ||
169 | struct RequestHandle *handle = cls; | ||
170 | struct MHD_Response *resp; | ||
171 | char *json_error; | ||
172 | |||
173 | GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", handle->emsg); | ||
174 | if (0 == handle->response_code) | ||
175 | { | ||
176 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
177 | } | ||
178 | resp = GNUNET_REST_create_response (json_error); | ||
179 | MHD_add_response_header (resp, "Content-Type", "application/json"); | ||
180 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
181 | cleanup_handle (handle); | ||
182 | GNUNET_free (json_error); | ||
183 | } | ||
184 | |||
185 | |||
186 | /** | ||
187 | * Task run on timeout, sends error message. Cleans up everything. | ||
188 | * | ||
189 | * @param cls the `struct RequestHandle` | ||
190 | */ | ||
191 | static void | ||
192 | do_timeout (void *cls) | ||
193 | { | ||
194 | struct RequestHandle *handle = cls; | ||
195 | |||
196 | handle->timeout_task = NULL; | ||
197 | do_error (handle); | ||
198 | } | ||
199 | |||
200 | |||
201 | static void | ||
202 | return_response (void *cls) | ||
203 | { | ||
204 | char *result_str; | ||
205 | struct RequestHandle *handle = cls; | ||
206 | struct MHD_Response *resp; | ||
207 | |||
208 | result_str = json_dumps (handle->resp_object, 0); | ||
209 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
210 | resp = GNUNET_REST_create_response (result_str); | ||
211 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); | ||
212 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
213 | GNUNET_free (result_str); | ||
214 | cleanup_handle (handle); | ||
215 | } | ||
216 | |||
217 | |||
218 | static enum pabc_status | ||
219 | set_attributes_from_idtoken (const struct pabc_context *ctx, | ||
220 | const struct pabc_public_parameters *pp, | ||
221 | struct pabc_user_context *usr_ctx, | ||
222 | const char *id_token) | ||
223 | { | ||
224 | json_t *payload_json; | ||
225 | json_t *value; | ||
226 | json_error_t json_err; | ||
227 | const char *key; | ||
228 | const char *jwt_body; | ||
229 | char *decoded_jwt; | ||
230 | char delim[] = "."; | ||
231 | char *jwt_string; | ||
232 | const char *pabc_key; | ||
233 | enum pabc_status status; | ||
234 | |||
235 | // FIXME parse JWT | ||
236 | jwt_string = GNUNET_strndup (id_token, strlen (id_token)); | ||
237 | jwt_body = strtok (jwt_string, delim); | ||
238 | jwt_body = strtok (NULL, delim); | ||
239 | GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), | ||
240 | (void **) &decoded_jwt); | ||
241 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded ID Token: %s\n", decoded_jwt); | ||
242 | payload_json = json_loads (decoded_jwt, JSON_DECODE_ANY, &json_err); | ||
243 | GNUNET_free (decoded_jwt); | ||
244 | |||
245 | json_object_foreach (payload_json, key, value) | ||
246 | { | ||
247 | pabc_key = key; | ||
248 | if (0 == strcmp ("iss", key)) | ||
249 | pabc_key = "issuer"; // rename | ||
250 | if (0 == strcmp ("sub", key)) | ||
251 | pabc_key = "subject"; // rename | ||
252 | if (0 == strcmp ("jti", key)) | ||
253 | continue; | ||
254 | if (0 == strcmp ("exp", key)) | ||
255 | pabc_key = "expiration"; // rename | ||
256 | if (0 == strcmp ("iat", key)) | ||
257 | continue; | ||
258 | if (0 == strcmp ("nbf", key)) | ||
259 | continue; | ||
260 | if (0 == strcmp ("aud", key)) | ||
261 | continue; | ||
262 | char *tmp_val; | ||
263 | if (json_is_string (value)) | ||
264 | tmp_val = GNUNET_strdup (json_string_value (value)); | ||
265 | else | ||
266 | tmp_val = json_dumps (value, JSON_ENCODE_ANY); | ||
267 | if (NULL == tmp_val) | ||
268 | { | ||
269 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
270 | "Unable to encode JSON value for `%s'\n", key); | ||
271 | continue; | ||
272 | } | ||
273 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
274 | "Setting `%s' to `%s'\n", key, tmp_val); | ||
275 | status = pabc_set_attribute_value_by_name (ctx, pp, usr_ctx, | ||
276 | pabc_key, | ||
277 | tmp_val); | ||
278 | GNUNET_free (tmp_val); | ||
279 | if (PABC_OK != status) | ||
280 | { | ||
281 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
282 | "Failed to set attribute `%s'.\n", key); | ||
283 | } | ||
284 | } | ||
285 | return PABC_OK; | ||
286 | } | ||
287 | |||
288 | |||
289 | static enum GNUNET_GenericReturnValue | ||
290 | setup_new_user_context (struct pabc_context *ctx, | ||
291 | struct pabc_public_parameters *pp, | ||
292 | struct pabc_user_context **usr_ctx) | ||
293 | { | ||
294 | if (PABC_OK != pabc_new_user_context (ctx, pp, usr_ctx)) | ||
295 | return GNUNET_SYSERR; | ||
296 | |||
297 | if (PABC_OK != pabc_populate_user_context (ctx, *usr_ctx)) | ||
298 | { | ||
299 | pabc_free_user_context (ctx, pp, usr_ctx); | ||
300 | return GNUNET_SYSERR; | ||
301 | } | ||
302 | return GNUNET_OK; | ||
303 | } | ||
304 | |||
305 | |||
306 | static void | ||
307 | cr_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
308 | const char *url, | ||
309 | void *cls) | ||
310 | { | ||
311 | struct RequestHandle *handle = cls; | ||
312 | char term_data[handle->rest_handle->data_size + 1]; | ||
313 | char *response_str; | ||
314 | json_t *data_json; | ||
315 | json_t *nonce_json; | ||
316 | json_t *pp_json; | ||
317 | json_t *idtoken_json; | ||
318 | json_t *iss_json; | ||
319 | json_t *identity_json; | ||
320 | json_error_t err; | ||
321 | struct pabc_public_parameters *pp = NULL; | ||
322 | struct pabc_context *ctx = NULL; | ||
323 | struct pabc_user_context *usr_ctx = NULL; | ||
324 | struct pabc_credential_request *cr = NULL; | ||
325 | struct pabc_nonce *nonce = NULL; | ||
326 | enum pabc_status status; | ||
327 | |||
328 | |||
329 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
330 | "Credential request...\n"); | ||
331 | |||
332 | if (0 >= handle->rest_handle->data_size) | ||
333 | { | ||
334 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | term_data[handle->rest_handle->data_size] = '\0'; | ||
339 | GNUNET_memcpy (term_data, | ||
340 | handle->rest_handle->data, | ||
341 | handle->rest_handle->data_size); | ||
342 | data_json = json_loads (term_data, JSON_DECODE_ANY, &err); | ||
343 | if (NULL == data_json) | ||
344 | { | ||
345 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
346 | "Unable to parse %s\n", term_data); | ||
347 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
348 | return; | ||
349 | } | ||
350 | if (! json_is_object (data_json)) | ||
351 | { | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
353 | "Unable to parse %s\n", term_data); | ||
354 | json_decref (data_json); | ||
355 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
356 | return; | ||
357 | } | ||
358 | |||
359 | nonce_json = json_object_get (data_json, "nonce"); | ||
360 | if (NULL == nonce_json) | ||
361 | { | ||
362 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
363 | "Unable to parse nonce\n"); | ||
364 | json_decref (data_json); | ||
365 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
366 | return; | ||
367 | } | ||
368 | iss_json = json_object_get (data_json, "issuer"); | ||
369 | if (NULL == iss_json) | ||
370 | { | ||
371 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
372 | "Unable to parse issuer\n"); | ||
373 | json_decref (data_json); | ||
374 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
375 | return; | ||
376 | } | ||
377 | identity_json = json_object_get (data_json, "identity"); | ||
378 | if (NULL == identity_json) | ||
379 | { | ||
380 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
381 | "Unable to parse identity\n"); | ||
382 | json_decref (data_json); | ||
383 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
384 | return; | ||
385 | } | ||
386 | idtoken_json = json_object_get (data_json, "id_token"); | ||
387 | if (NULL == idtoken_json) | ||
388 | { | ||
389 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
390 | "Unable to parse id_token\n"); | ||
391 | json_decref (data_json); | ||
392 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
393 | return; | ||
394 | } | ||
395 | pp_json = json_object_get (data_json, "public_params"); | ||
396 | if (NULL == pp_json) | ||
397 | { | ||
398 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
399 | "Unable to parse public parameters\n"); | ||
400 | json_decref (data_json); | ||
401 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
402 | return; | ||
403 | } | ||
404 | |||
405 | PABC_ASSERT (pabc_new_ctx (&ctx)); | ||
406 | char *pp_str = json_dumps (pp_json, JSON_ENCODE_ANY); | ||
407 | status = pabc_decode_and_new_public_parameters (ctx, | ||
408 | &pp, | ||
409 | pp_str); | ||
410 | char *ppid; | ||
411 | GNUNET_assert (PABC_OK == pabc_cred_get_ppid_from_pp (pp_str, &ppid)); | ||
412 | GNUNET_free (pp_str); | ||
413 | if (status != PABC_OK) | ||
414 | { | ||
415 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
416 | "Failed to read public parameters: %s\n", | ||
417 | pp_str); | ||
418 | json_decref (data_json); | ||
419 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
420 | return; | ||
421 | } | ||
422 | // (Over)write parameters | ||
423 | status = PABC_write_public_parameters (json_string_value (iss_json), | ||
424 | pp); | ||
425 | if (status != PABC_OK) | ||
426 | { | ||
427 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
428 | "Failed to write public parameters.\n"); | ||
429 | json_decref (data_json); | ||
430 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
431 | return; | ||
432 | } | ||
433 | status = PABC_read_usr_ctx (json_string_value (identity_json), | ||
434 | json_string_value (iss_json), | ||
435 | ctx, pp, &usr_ctx); | ||
436 | if (PABC_OK != status) | ||
437 | { | ||
438 | if (GNUNET_OK != setup_new_user_context (ctx, pp, &usr_ctx)) | ||
439 | { | ||
440 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup user context.\n"); | ||
441 | pabc_free_public_parameters (ctx, &pp); | ||
442 | json_decref (data_json); | ||
443 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
444 | return; | ||
445 | } | ||
446 | PABC_write_usr_ctx (json_string_value (identity_json), | ||
447 | json_string_value (iss_json), | ||
448 | ctx, pp, usr_ctx); | ||
449 | } | ||
450 | |||
451 | // Set attributes from JWT to context | ||
452 | status = set_attributes_from_idtoken (ctx, | ||
453 | pp, | ||
454 | usr_ctx, | ||
455 | json_string_value (idtoken_json)); | ||
456 | if (status != PABC_OK) | ||
457 | { | ||
458 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to set attributes.\n"); | ||
459 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
460 | pabc_free_public_parameters (ctx, &pp); | ||
461 | json_decref (data_json); | ||
462 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
463 | return; | ||
464 | } | ||
465 | |||
466 | |||
467 | // nonce | ||
468 | status = pabc_new_nonce (ctx, &nonce); | ||
469 | if (status != PABC_OK) | ||
470 | { | ||
471 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to allocate nonce.\n"); | ||
472 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
473 | pabc_free_public_parameters (ctx, &pp); | ||
474 | json_decref (data_json); | ||
475 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
476 | return; | ||
477 | } | ||
478 | char *nonce_str = json_dumps (nonce_json, JSON_ENCODE_ANY); | ||
479 | status = pabc_decode_nonce (ctx, nonce, nonce_str); | ||
480 | if (status != PABC_OK) | ||
481 | { | ||
482 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to decode nonce.\n"); | ||
483 | pabc_free_nonce (ctx, &nonce); | ||
484 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
485 | pabc_free_public_parameters (ctx, &pp); | ||
486 | json_decref (data_json); | ||
487 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | // cr | ||
492 | status = pabc_new_credential_request (ctx, pp, &cr); | ||
493 | if (PABC_OK != status) | ||
494 | { | ||
495 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to allocate cr.\n"); | ||
496 | pabc_free_nonce (ctx, &nonce); | ||
497 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
498 | pabc_free_public_parameters (ctx, &pp); | ||
499 | json_decref (data_json); | ||
500 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | status = pabc_gen_credential_request (ctx, pp, usr_ctx, nonce, cr); | ||
505 | if (PABC_OK != status) | ||
506 | { | ||
507 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to generate cr.\n"); | ||
508 | pabc_free_nonce (ctx, &nonce); | ||
509 | pabc_free_credential_request (ctx, pp, &cr); | ||
510 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
511 | pabc_free_public_parameters (ctx, &pp); | ||
512 | json_decref (data_json); | ||
513 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
514 | return; | ||
515 | } | ||
516 | handle->resp_object = json_object (); | ||
517 | GNUNET_assert (PABC_OK == pabc_cred_encode_cr (ctx, pp, cr, | ||
518 | json_string_value ( | ||
519 | identity_json), | ||
520 | ppid, &response_str)); | ||
521 | if (PABC_OK != status) | ||
522 | { | ||
523 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to serialize cr.\n"); | ||
524 | pabc_free_nonce (ctx, &nonce); | ||
525 | pabc_free_credential_request (ctx, pp, &cr); | ||
526 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
527 | pabc_free_public_parameters (ctx, &pp); | ||
528 | json_decref (data_json); | ||
529 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
530 | return; | ||
531 | } | ||
532 | json_decref (handle->resp_object); | ||
533 | handle->resp_object = json_loads (response_str, JSON_DECODE_ANY, &err); | ||
534 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", response_str); | ||
535 | GNUNET_free (response_str); | ||
536 | |||
537 | // clean up | ||
538 | pabc_free_nonce (ctx, &nonce); | ||
539 | pabc_free_credential_request (ctx, pp, &cr); | ||
540 | pabc_free_user_context (ctx, pp, &usr_ctx); | ||
541 | pabc_free_public_parameters (ctx, &pp); | ||
542 | GNUNET_SCHEDULER_add_now (&return_response, handle); | ||
543 | json_decref (data_json); | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Respond to OPTIONS request | ||
549 | * | ||
550 | * @param con_handle the connection handle | ||
551 | * @param url the url | ||
552 | * @param cls the RequestHandle | ||
553 | */ | ||
554 | static void | ||
555 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
556 | const char *url, | ||
557 | void *cls) | ||
558 | { | ||
559 | struct MHD_Response *resp; | ||
560 | struct RequestHandle *handle = cls; | ||
561 | |||
562 | // For now, independent of path return all options | ||
563 | resp = GNUNET_REST_create_response (NULL); | ||
564 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); | ||
565 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
566 | cleanup_handle (handle); | ||
567 | return; | ||
568 | } | ||
569 | |||
570 | |||
571 | static enum GNUNET_GenericReturnValue | ||
572 | rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | ||
573 | GNUNET_REST_ResultProcessor proc, | ||
574 | void *proc_cls) | ||
575 | { | ||
576 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
577 | struct GNUNET_REST_RequestHandlerError err; | ||
578 | static const struct GNUNET_REST_RequestHandler handlers[] = { | ||
579 | {MHD_HTTP_METHOD_POST, | ||
580 | GNUNET_REST_API_NS_PABC_CR, &cr_cont }, | ||
581 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PABC, &options_cont }, | ||
582 | GNUNET_REST_HANDLER_END | ||
583 | }; | ||
584 | |||
585 | handle->response_code = 0; | ||
586 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
587 | handle->proc_cls = proc_cls; | ||
588 | handle->proc = proc; | ||
589 | handle->rest_handle = rest_handle; | ||
590 | |||
591 | handle->url = GNUNET_strdup (rest_handle->url); | ||
592 | if (handle->url[strlen (handle->url) - 1] == '/') | ||
593 | handle->url[strlen (handle->url) - 1] = '\0'; | ||
594 | handle->timeout_task = | ||
595 | GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle); | ||
596 | GNUNET_CONTAINER_DLL_insert (requests_head, | ||
597 | requests_tail, | ||
598 | handle); | ||
599 | if (GNUNET_NO == | ||
600 | GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) | ||
601 | { | ||
602 | cleanup_handle (handle); | ||
603 | return GNUNET_NO; | ||
604 | } | ||
605 | |||
606 | return GNUNET_YES; | ||
607 | } | ||
608 | |||
609 | |||
610 | /** | ||
611 | * Entry point for the plugin. | ||
612 | * | ||
613 | * @param cls Config info | ||
614 | * @return NULL on error, otherwise the plugin context | ||
615 | */ | ||
616 | void * | ||
617 | libgnunet_plugin_rest_pabc_init (void *cls) | ||
618 | { | ||
619 | static struct Plugin plugin; | ||
620 | struct GNUNET_REST_Plugin *api; | ||
621 | |||
622 | cfg = cls; | ||
623 | if (NULL != plugin.cfg) | ||
624 | return NULL; /* can only initialize once! */ | ||
625 | memset (&plugin, 0, sizeof(struct Plugin)); | ||
626 | plugin.cfg = cfg; | ||
627 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
628 | api->cls = &plugin; | ||
629 | api->name = GNUNET_REST_API_NS_PABC; | ||
630 | api->process_request = &rest_identity_process_request; | ||
631 | GNUNET_asprintf (&allow_methods, | ||
632 | "%s, %s", | ||
633 | MHD_HTTP_METHOD_POST, | ||
634 | MHD_HTTP_METHOD_OPTIONS); | ||
635 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
636 | _ ("Identity Provider REST API initialized\n")); | ||
637 | return api; | ||
638 | } | ||
639 | |||
640 | |||
641 | /** | ||
642 | * Exit point from the plugin. | ||
643 | * | ||
644 | * @param cls the plugin context (as returned by "init") | ||
645 | * @return always NULL | ||
646 | */ | ||
647 | void * | ||
648 | libgnunet_plugin_rest_reclaim_done (void *cls) | ||
649 | { | ||
650 | struct GNUNET_REST_Plugin *api = cls; | ||
651 | struct Plugin *plugin = api->cls; | ||
652 | struct RequestHandle *request; | ||
653 | |||
654 | plugin->cfg = NULL; | ||
655 | while (NULL != (request = requests_head)) | ||
656 | do_error (request); | ||
657 | |||
658 | GNUNET_free (allow_methods); | ||
659 | GNUNET_free (api); | ||
660 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
661 | "PABC REST plugin is finished\n"); | ||
662 | return NULL; | ||
663 | } | ||
664 | |||
665 | |||
666 | /* end of plugin_rest_reclaim.c */ | ||