2 This file is part of GNUnet.
3 Copyright (C) 2012-2016 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 * @author Martin Schanzenbach
22 * @file gns/plugin_rest_credential.c
23 * @brief GNUnet CREDENTIAL REST plugin
28 #include "gnunet_rest_plugin.h"
29 #include <gnunet_identity_service.h>
30 #include <gnunet_gnsrecord_lib.h>
31 #include <gnunet_namestore_service.h>
32 #include <gnunet_credential_service.h>
33 #include <gnunet_rest_lib.h>
34 #include <gnunet_jsonapi_lib.h>
35 #include <gnunet_jsonapi_util.h>
38 #define GNUNET_REST_API_NS_CREDENTIAL "/credential"
40 #define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
42 #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
45 * @brief struct returned by the initialization function of the plugin
49 const struct GNUNET_CONFIGURATION_Handle *cfg;
52 const struct GNUNET_CONFIGURATION_Handle *cfg;
57 * Handle to Credential service.
59 struct GNUNET_CREDENTIAL_Handle *credential;
62 * Handle to lookup request
64 struct GNUNET_CREDENTIAL_Request *verify_request;
67 * Handle to rest request
69 struct GNUNET_REST_RequestHandle *rest_handle;
72 * ID of a task associated with the resolution process.
74 struct GNUNET_SCHEDULER_Task * timeout_task;
77 * The root of the received JSON or NULL
82 * The plugin result processor
84 GNUNET_REST_ResultProcessor proc;
87 * The closure of the result processor
92 * The issuer attribute to verify
97 * The subject attribute
102 * The public key of the issuer
104 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
107 * The public key of the subject
109 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
119 struct GNUNET_TIME_Relative timeout;
125 * Cleanup lookup handle.
127 * @param handle Handle to clean up
130 cleanup_handle (struct VerifyHandle *handle)
132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
134 if (NULL != handle->json_root)
135 json_decref (handle->json_root);
137 if (NULL != handle->issuer_attr)
138 GNUNET_free (handle->issuer_attr);
139 if (NULL != handle->subject_attr)
140 GNUNET_free (handle->subject_attr);
141 if (NULL != handle->verify_request)
143 GNUNET_CREDENTIAL_verify_cancel (handle->verify_request);
144 handle->verify_request = NULL;
146 if (NULL != handle->credential)
148 GNUNET_CREDENTIAL_disconnect (handle->credential);
149 handle->credential = NULL;
152 if (NULL != handle->timeout_task)
154 GNUNET_SCHEDULER_cancel (handle->timeout_task);
156 GNUNET_free (handle);
161 * Task run on shutdown. Cleans up everything.
164 * @param tc scheduler context
169 struct VerifyHandle *handle = cls;
170 struct MHD_Response *resp;
172 resp = GNUNET_REST_create_response (NULL);
173 handle->proc (handle->proc_cls, resp, handle->response_code);
174 cleanup_handle (handle);
179 verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
183 struct VerifyHandle *handle = cls;
184 struct GNUNET_HashCode key;
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
190 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
191 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
193 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
195 if (NULL == handle->credential)
197 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
198 "Connecting to CREDENTIAL failed\n");
199 GNUNET_SCHEDULER_add_now (&do_error, handle);
202 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
203 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
206 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
209 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
210 "Missing issuer attribute\n");
211 GNUNET_SCHEDULER_add_now (&do_error, handle);
214 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
216 entity_attr = GNUNET_strdup (tmp);
217 tmp = strtok(entity_attr, ".");
220 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
221 "Malformed issuer or attribute\n");
222 GNUNET_free (entity_attr);
223 GNUNET_SCHEDULER_add_now (&do_error, handle);
227 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
229 &handle->issuer_key))
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 "Malformed issuer key\n");
233 GNUNET_free (entity_attr);
234 GNUNET_SCHEDULER_add_now (&do_error, handle);
237 tmp = strtok (NULL, "."); //Issuer attribute
240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
241 "Malformed attribute\n");
242 GNUNET_free (entity_attr);
243 GNUNET_SCHEDULER_add_now (&do_error, handle);
246 handle->issuer_attr = GNUNET_strdup (tmp);
247 GNUNET_free (entity_attr);
249 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR,
250 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR),
253 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
256 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
257 "Missing subject or attribute\n");
258 GNUNET_free (entity_attr);
259 GNUNET_SCHEDULER_add_now (&do_error, handle);
262 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
264 entity_attr = GNUNET_strdup (tmp);
265 tmp = strtok(entity_attr, ".");
268 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
269 "Malformed subject\n");
270 GNUNET_free (entity_attr);
271 GNUNET_SCHEDULER_add_now (&do_error, handle);
275 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
277 &handle->subject_key)) {
278 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
279 "Malformed subject key\n");
280 GNUNET_free (entity_attr);
281 GNUNET_SCHEDULER_add_now (&do_error, handle);
284 tmp = strtok (NULL, ".");
287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
288 "Malformed subject attribute\n");
289 GNUNET_free (entity_attr);
290 GNUNET_SCHEDULER_add_now (&do_error, handle);
293 handle->subject_attr = GNUNET_strdup (tmp);
294 GNUNET_free (entity_attr);
296 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
299 &handle->subject_key,
300 handle->subject_attr,
307 * Handle rest request
309 * @param handle the lookup handle
312 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
316 struct MHD_Response *resp;
317 struct VerifyHandle *handle = cls;
319 //For GNS, independent of path return all options
320 resp = GNUNET_REST_create_response (NULL);
321 MHD_add_response_header (resp,
322 "Access-Control-Allow-Methods",
323 MHD_HTTP_METHOD_GET);
324 handle->proc (handle->proc_cls,
327 cleanup_handle (handle);
332 * Function processing the REST call
334 * @param method HTTP method
335 * @param url URL of the HTTP request
336 * @param data body of the HTTP request (optional)
337 * @param data_size length of the body
338 * @param proc callback function for the result
339 * @param proc_cls closure for callback function
340 * @return GNUNET_OK if request accepted
343 rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
344 GNUNET_REST_ResultProcessor proc,
347 struct VerifyHandle *handle = GNUNET_new (struct VerifyHandle);
348 struct GNUNET_REST_RequestHandlerError err;
350 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
351 handle->proc_cls = proc_cls;
353 handle->rest_handle = conndata_handle;
355 static const struct GNUNET_REST_RequestHandler handlers[] = {
356 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL, &verify_cred_cont},
357 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
358 GNUNET_REST_HANDLER_END
361 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
366 handle->response_code = err.error_code;
367 GNUNET_SCHEDULER_add_now (&do_error, handle);
373 * Entry point for the plugin.
375 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
376 * @return NULL on error, otherwise the plugin context
379 libgnunet_plugin_rest_credential_init (void *cls)
381 static struct Plugin plugin;
383 struct GNUNET_REST_Plugin *api;
385 if (NULL != plugin.cfg)
386 return NULL; /* can only initialize once! */
387 memset (&plugin, 0, sizeof (struct Plugin));
389 api = GNUNET_new (struct GNUNET_REST_Plugin);
391 api->name = GNUNET_REST_API_NS_CREDENTIAL;
392 api->process_request = &rest_credential_process_request;
393 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
394 _("GNS REST API initialized\n"));
400 * Exit point from the plugin.
402 * @param cls the plugin context (as returned by "init")
403 * @return always NULL
406 libgnunet_plugin_rest_credential_done (void *cls)
408 struct GNUNET_REST_Plugin *api = cls;
409 struct Plugin *plugin = api->cls;
413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
414 "GNS REST plugin is finished\n");
418 /* end of plugin_rest_gns.c */