aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/credential/Makefile.am43
-rw-r--r--src/credential/plugin_rest_credential.c418
2 files changed, 434 insertions, 27 deletions
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
index 47204ae26..13da9dc0f 100644
--- a/src/credential/Makefile.am
+++ b/src/credential/Makefile.am
@@ -4,16 +4,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
4EXTRA_DIST = \ 4EXTRA_DIST = \
5 test_credential_defaults.conf \ 5 test_credential_defaults.conf \
6 test_credential_lookup.conf 6 test_credential_lookup.conf
7# test_gns_nick_shorten.conf \
8#### test_gns_proxy.conf \
9# test_gns_simple_lookup.conf \
10# gns-helper-service-w32.conf \
11# w32nsp.def \
12# gnunet-gns-proxy-setup-ca \
13# zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey \
14# zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \
15# zonefiles/test_zonekey \
16# $(check_SCRIPTS)
17 7
18 8
19if USE_COVERAGE 9if USE_COVERAGE
@@ -45,11 +35,11 @@ plugin_LTLIBRARIES = \
45 libgnunet_plugin_gnsrecord_credential.la 35 libgnunet_plugin_gnsrecord_credential.la
46 36
47 37
48#if HAVE_MHD 38if HAVE_MHD
49#if HAVE_JSON 39if HAVE_JSON
50#plugin_LTLIBRARIES += libgnunet_plugin_rest_gns.la 40plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la
51#endif 41endif
52#endif 42endif
53 43
54 44
55gnunet_credential_SOURCES = \ 45gnunet_credential_SOURCES = \
@@ -89,18 +79,17 @@ libgnunetcredential_la_LDFLAGS = \
89 $(GN_LIB_LDFLAGS) 79 $(GN_LIB_LDFLAGS)
90 80
91 81
92#libgnunet_plugin_rest_gns_la_SOURCES = \ 82libgnunet_plugin_rest_credential_la_SOURCES = \
93# plugin_rest_gns.c 83 plugin_rest_credential.c
94#libgnunet_plugin_rest_gns_la_LIBADD = \ 84libgnunet_plugin_rest_credential_la_LIBADD = \
95# libgnunetgns.la \ 85 libgnunetcredential.la \
96# $(top_builddir)/src/rest/libgnunetrest.la \ 86 $(top_builddir)/src/rest/libgnunetrest.la \
97# $(top_builddir)/src/identity/libgnunetidentity.la \ 87 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
98# $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ 88 $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
99# $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \ 89 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
100# $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ 90 $(LTLIBINTL) -ljansson -lmicrohttpd
101# $(LTLIBINTL) -ljansson -lmicrohttpd 91libgnunet_plugin_rest_credential_la_LDFLAGS = \
102#libgnunet_plugin_rest_gns_la_LDFLAGS = \ 92 $(GN_PLUGIN_LDFLAGS)
103# $(GN_PLUGIN_LDFLAGS)
104 93
105 94
106check_SCRIPTS = \ 95check_SCRIPTS = \
diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c
new file mode 100644
index 000000000..51d91079a
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,418 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2016 GNUnet e.V.
4
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.
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 General Public License for more details.
14
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.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file gns/plugin_rest_credential.c
23 * @brief GNUnet CREDENTIAL REST plugin
24 *
25 */
26
27#include "platform.h"
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>
36#include <jansson.h>
37
38#define GNUNET_REST_API_NS_CREDENTIAL "/credential"
39
40#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
41
42#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
43
44/**
45 * @brief struct returned by the initialization function of the plugin
46 */
47struct Plugin
48{
49 const struct GNUNET_CONFIGURATION_Handle *cfg;
50};
51
52const struct GNUNET_CONFIGURATION_Handle *cfg;
53
54struct VerifyHandle
55{
56 /**
57 * Handle to Credential service.
58 */
59 struct GNUNET_CREDENTIAL_Handle *credential;
60
61 /**
62 * Handle to lookup request
63 */
64 struct GNUNET_CREDENTIAL_Request *verify_request;
65
66 /**
67 * Handle to rest request
68 */
69 struct GNUNET_REST_RequestHandle *rest_handle;
70
71 /**
72 * ID of a task associated with the resolution process.
73 */
74 struct GNUNET_SCHEDULER_Task * timeout_task;
75
76 /**
77 * The root of the received JSON or NULL
78 */
79 json_t *json_root;
80
81 /**
82 * The plugin result processor
83 */
84 GNUNET_REST_ResultProcessor proc;
85
86 /**
87 * The closure of the result processor
88 */
89 void *proc_cls;
90
91 /**
92 * The issuer attribute to verify
93 */
94 char *issuer_attr;
95
96 /**
97 * The subject attribute
98 */
99 char *subject_attr;
100
101 /**
102 * The public key of the issuer
103 */
104 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
105
106 /**
107 * The public key of the subject
108 */
109 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
110
111 /**
112 * HTTP response code
113 */
114 int response_code;
115
116 /**
117 * Timeout
118 */
119 struct GNUNET_TIME_Relative timeout;
120
121};
122
123
124/**
125 * Cleanup lookup handle.
126 *
127 * @param handle Handle to clean up
128 */
129static void
130cleanup_handle (struct VerifyHandle *handle)
131{
132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
133 "Cleaning up\n");
134 if (NULL != handle->json_root)
135 json_decref (handle->json_root);
136
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)
142 {
143 GNUNET_CREDENTIAL_verify_cancel (handle->verify_request);
144 handle->verify_request = NULL;
145 }
146 if (NULL != handle->credential)
147 {
148 GNUNET_CREDENTIAL_disconnect (handle->credential);
149 handle->credential = NULL;
150 }
151
152 if (NULL != handle->timeout_task)
153 {
154 GNUNET_SCHEDULER_cancel (handle->timeout_task);
155 }
156 GNUNET_free (handle);
157}
158
159
160/**
161 * Task run on shutdown. Cleans up everything.
162 *
163 * @param cls unused
164 * @param tc scheduler context
165 */
166static void
167do_error (void *cls)
168{
169 struct VerifyHandle *handle = cls;
170 struct MHD_Response *resp;
171
172 resp = GNUNET_REST_create_response (NULL);
173 handle->proc (handle->proc_cls, resp, handle->response_code);
174 cleanup_handle (handle);
175}
176
177
178static void
179verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
180 const char* url,
181 void *cls)
182{
183 struct VerifyHandle *handle = cls;
184 struct GNUNET_HashCode key;
185 char *tmp;
186 char *entity_attr;
187
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189 "Connecting...\n");
190 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
191 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
192 &do_error, handle);
193 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
194 "Connected\n");
195 if (NULL == handle->credential)
196 {
197 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
198 "Connecting to CREDENTIAL failed\n");
199 GNUNET_SCHEDULER_add_now (&do_error, handle);
200 return;
201 }
202 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
203 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
204 &key);
205 if ( GNUNET_NO ==
206 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
207 &key) )
208 {
209 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
210 "Missing issuer attribute\n");
211 GNUNET_SCHEDULER_add_now (&do_error, handle);
212 return;
213 }
214 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
215 &key);
216 entity_attr = GNUNET_strdup (tmp);
217 tmp = strtok(entity_attr, ".");
218 if (NULL == tmp)
219 {
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);
224 return;
225 }
226 if (GNUNET_OK !=
227 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
228 strlen (tmp),
229 &handle->issuer_key))
230 {
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);
235 return;
236 }
237 tmp = strtok (NULL, "."); //Issuer attribute
238 if (NULL == tmp)
239 {
240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
241 "Malformed attribute\n");
242 GNUNET_free (entity_attr);
243 GNUNET_SCHEDULER_add_now (&do_error, handle);
244 return;
245 }
246 handle->issuer_attr = GNUNET_strdup (tmp);
247 GNUNET_free (entity_attr);
248
249 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR,
250 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR),
251 &key);
252 if ( GNUNET_NO ==
253 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
254 &key) )
255 {
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);
260 return;
261 }
262 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
263 &key);
264 entity_attr = GNUNET_strdup (tmp);
265 tmp = strtok(entity_attr, ".");
266 if (NULL == tmp)
267 {
268 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
269 "Malformed subject\n");
270 GNUNET_free (entity_attr);
271 GNUNET_SCHEDULER_add_now (&do_error, handle);
272 return;
273 }
274 if (GNUNET_OK !=
275 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
276 strlen (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);
282 return;
283 }
284 tmp = strtok (NULL, ".");
285 if (NULL == tmp)
286 {
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);
291 return;
292 }
293 handle->subject_attr = GNUNET_strdup (tmp);
294 GNUNET_free (entity_attr);
295
296 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
297 &handle->issuer_key,
298 handle->issuer_attr,
299 &handle->subject_key,
300 handle->subject_attr,
301 NULL,
302 NULL);
303
304}
305
306/**
307 * Handle rest request
308 *
309 * @param handle the lookup handle
310 */
311static void
312options_cont (struct GNUNET_REST_RequestHandle *con_handle,
313 const char* url,
314 void *cls)
315{
316 struct MHD_Response *resp;
317 struct VerifyHandle *handle = cls;
318
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,
325 resp,
326 MHD_HTTP_OK);
327 cleanup_handle (handle);
328}
329
330
331/**
332 * Function processing the REST call
333 *
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
341 */
342static void
343rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
344 GNUNET_REST_ResultProcessor proc,
345 void *proc_cls)
346{
347 struct VerifyHandle *handle = GNUNET_new (struct VerifyHandle);
348 struct GNUNET_REST_RequestHandlerError err;
349
350 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
351 handle->proc_cls = proc_cls;
352 handle->proc = proc;
353 handle->rest_handle = conndata_handle;
354
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
359 };
360
361 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
362 handlers,
363 &err,
364 handle))
365 {
366 handle->response_code = err.error_code;
367 GNUNET_SCHEDULER_add_now (&do_error, handle);
368 }
369}
370
371
372/**
373 * Entry point for the plugin.
374 *
375 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
376 * @return NULL on error, otherwise the plugin context
377 */
378void *
379libgnunet_plugin_rest_credential_init (void *cls)
380{
381 static struct Plugin plugin;
382 cfg = cls;
383 struct GNUNET_REST_Plugin *api;
384
385 if (NULL != plugin.cfg)
386 return NULL; /* can only initialize once! */
387 memset (&plugin, 0, sizeof (struct Plugin));
388 plugin.cfg = cfg;
389 api = GNUNET_new (struct GNUNET_REST_Plugin);
390 api->cls = &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"));
395 return api;
396}
397
398
399/**
400 * Exit point from the plugin.
401 *
402 * @param cls the plugin context (as returned by "init")
403 * @return always NULL
404 */
405void *
406libgnunet_plugin_rest_credential_done (void *cls)
407{
408 struct GNUNET_REST_Plugin *api = cls;
409 struct Plugin *plugin = api->cls;
410
411 plugin->cfg = NULL;
412 GNUNET_free (api);
413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
414 "GNS REST plugin is finished\n");
415 return NULL;
416}
417
418/* end of plugin_rest_gns.c */