summaryrefslogtreecommitdiff
path: root/src/credential
diff options
context:
space:
mode:
Diffstat (limited to 'src/credential')
-rw-r--r--src/credential/Makefile.am111
-rw-r--r--src/credential/credential.conf.in5
-rw-r--r--src/credential/credential.h186
-rw-r--r--src/credential/credential_api.c433
-rw-r--r--src/credential/credential_misc.c168
-rw-r--r--src/credential/credential_misc.h35
-rw-r--r--src/credential/credential_serialization.c390
-rw-r--r--src/credential/credential_serialization.h142
-rw-r--r--src/credential/gnunet-credential.c446
-rw-r--r--src/credential/gnunet-service-credential.c1028
-rw-r--r--src/credential/plugin_gnsrecord_credential.c342
-rw-r--r--src/credential/plugin_rest_credential.c821
-rw-r--r--src/credential/test_credential_defaults.conf24
-rwxr-xr-xsrc/credential/test_credential_issue.sh44
-rw-r--r--src/credential/test_credential_lookup.conf28
-rwxr-xr-xsrc/credential/test_credential_verify.sh78
-rwxr-xr-xsrc/credential/test_credential_verify_and.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_rest.sh84
-rwxr-xr-xsrc/credential/test_credential_verify_simple.sh50
19 files changed, 4496 insertions, 0 deletions
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
new file mode 100644
index 000000000..db3bc8027
--- /dev/null
+++ b/src/credential/Makefile.am
@@ -0,0 +1,111 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4EXTRA_DIST = \
5 test_credential_defaults.conf \
6 test_credential_lookup.conf
7
8
9if USE_COVERAGE
10 AM_CFLAGS = --coverage -O0
11endif
12
13pkgcfgdir = $(pkgdatadir)/config.d/
14
15libexecdir= $(pkglibdir)/libexec/
16
17plugindir = $(libdir)/gnunet
18
19pkgcfg_DATA = \
20 credential.conf
21
22
23# /usr/lib - compiles a layer which can be used to be communicagte with the service
24lib_LTLIBRARIES = \
25 libgnunetcredential.la
26
27# /usr/lib/gnunet/libexec - Business logic . Separate process
28libexec_PROGRAMS = \
29 gnunet-service-credential
30
31bin_PROGRAMS = \
32 gnunet-credential
33
34plugin_LTLIBRARIES = \
35 libgnunet_plugin_gnsrecord_credential.la
36
37
38if HAVE_MHD
39if HAVE_JSON
40plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la
41endif
42endif
43
44
45gnunet_credential_SOURCES = \
46 gnunet-credential.c
47gnunet_credential_LDADD = \
48 libgnunetcredential.la \
49 $(top_builddir)/src/util/libgnunetutil.la \
50 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
51 $(top_builddir)/src/identity/libgnunetidentity.la \
52 $(GN_LIBINTL)
53
54
55libgnunet_plugin_gnsrecord_credential_la_SOURCES = \
56 plugin_gnsrecord_credential.c
57libgnunet_plugin_gnsrecord_credential_la_LIBADD = \
58 libgnunetcredential.la \
59 $(top_builddir)/src/util/libgnunetutil.la \
60 $(LTLIBINTL)
61libgnunet_plugin_gnsrecord_credential_la_LDFLAGS = \
62 $(GN_PLUGIN_LDFLAGS)
63
64
65
66gnunet_service_credential_SOURCES = \
67 gnunet-service-credential.c
68gnunet_service_credential_LDADD = \
69 libgnunetcredential.la \
70 $(top_builddir)/src/util/libgnunetutil.la \
71 $(top_builddir)/src/gns/libgnunetgns.la \
72 $(top_builddir)/src/statistics/libgnunetstatistics.la \
73 $(GN_LIBINTL)
74
75
76libgnunetcredential_la_SOURCES = \
77 credential_api.c \
78 credential_serialization.c \
79 credential_misc.c
80libgnunetcredential_la_LIBADD = \
81 $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
82libgnunetcredential_la_LDFLAGS = \
83 $(GN_LIB_LDFLAGS)
84
85
86libgnunet_plugin_rest_credential_la_SOURCES = \
87 plugin_rest_credential.c
88libgnunet_plugin_rest_credential_la_LIBADD = \
89 libgnunetcredential.la \
90 $(top_builddir)/src/rest/libgnunetrest.la \
91 $(top_builddir)/src/identity/libgnunetidentity.la \
92 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
93 $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
94 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
95 $(LTLIBINTL) -ljansson -lmicrohttpd
96libgnunet_plugin_rest_credential_la_LDFLAGS = \
97 $(GN_PLUGIN_LDFLAGS)
98
99
100check_SCRIPTS = \
101 test_credential_issue.sh \
102 test_credential_verify_simple.sh \
103 test_credential_verify.sh \
104 test_credential_verify_and.sh
105
106if ENABLE_TEST_RUN
107if HAVE_SQLITE
108 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
109 TESTS = $(check_SCRIPTS)
110endif
111endif
diff --git a/src/credential/credential.conf.in b/src/credential/credential.conf.in
new file mode 100644
index 000000000..71f3066ca
--- /dev/null
+++ b/src/credential/credential.conf.in
@@ -0,0 +1,5 @@
1[credential]
2BINARY = gnunet-service-credential
3UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-credential.sock
4USER_SERVICE = YES
5OPTIONS = -L DEBUG \ No newline at end of file
diff --git a/src/credential/credential.h b/src/credential/credential.h
new file mode 100644
index 000000000..c5c0183cc
--- /dev/null
+++ b/src/credential/credential.h
@@ -0,0 +1,186 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 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 * @file credential/credential.h
22 * @brief IPC messages between CREDENTIAL API and CREDENTIAL service
23 * @author Adnan Husain
24 */
25#ifndef CREDENTIAL_H
26#define CREDENTIAL_H
27
28#include "gnunet_credential_service.h"
29
30GNUNET_NETWORK_STRUCT_BEGIN
31
32/**
33 * Message from client to Credential service to verify attributes.
34 */
35struct VerifyMessage
36{
37 /**
38 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
39 */
40 struct GNUNET_MessageHeader header;
41
42 /**
43 * Subject public key
44 */
45 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
46
47 /**
48 * Trust anchor
49 */
50 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
51
52 /**
53 * Length of the issuer attribute
54 */
55 uint16_t issuer_attribute_len;
56
57 /**
58 * Length of the subject attribute
59 */
60 uint16_t subject_attribute_len;
61
62 /**
63 * Unique identifier for this request (for key collisions).
64 */
65 uint32_t id GNUNET_PACKED;
66
67 /* Followed by the zero-terminated attributes to look up */
68
69};
70
71
72/**
73 * Message from CREDENTIAL service to client: new results.
74 */
75struct VerifyResultMessage
76{
77 /**
78 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT
79 */
80 struct GNUNET_MessageHeader header;
81
82 /**
83 * Unique identifier for this request (for key collisions).
84 */
85 uint32_t id GNUNET_PACKED;
86
87 /**
88 * Indicates if credential has been found at all
89 */
90 uint32_t cred_found GNUNET_PACKED;
91
92 /**
93 * The number of delegations in the response
94 */
95 uint32_t d_count GNUNET_PACKED;
96
97 /**
98 * The number of credentials in the response
99 */
100 uint32_t c_count GNUNET_PACKED;
101
102 /* followed by ad_count GNUNET_CREDENTIAL_RecordData structs*/
103
104};
105
106struct DelegationRecordData
107{
108 /**
109 * Subject key
110 */
111 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
112
113 /**
114 * Subject attributes
115 */
116 uint32_t subject_attribute_len GNUNET_PACKED;
117};
118
119
120struct ChainEntry
121{
122 /**
123 * Issuer key
124 */
125 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
126
127 /**
128 * Subject key
129 */
130 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
131
132 /**
133 * Issuer attributes
134 */
135 uint32_t issuer_attribute_len GNUNET_PACKED;
136
137 /**
138 * Subject attributes
139 */
140 uint32_t subject_attribute_len GNUNET_PACKED;
141};
142
143
144struct CredentialEntry
145{
146
147 /**
148 * The signature for this credential by the issuer
149 */
150 struct GNUNET_CRYPTO_EcdsaSignature signature;
151
152 /**
153 * Signature meta
154 */
155 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
156
157 /**
158 * Public key of the issuer
159 */
160 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
161
162 /**
163 * Public key of the subject this credential was issued to
164 */
165 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
166
167 /**
168 * Expiration time of this credential
169 */
170 uint64_t expiration GNUNET_PACKED;
171
172 /**
173 * Issuer attribute length
174 */
175 uint32_t issuer_attribute_len;
176
177 /**
178 * Followed by the attribute string
179 */
180};
181
182
183GNUNET_NETWORK_STRUCT_END
184
185#endif
186
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
new file mode 100644
index 000000000..e991b4153
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,433 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 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 * @file credential/credential_api.c
22 * @brief library to access the CREDENTIAL service
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_constants.h"
28#include "gnunet_arm_service.h"
29#include "gnunet_hello_lib.h"
30#include "gnunet_protocols.h"
31#include "gnunet_signatures.h"
32#include "credential.h"
33#include "credential_serialization.h"
34#include "gnunet_credential_service.h"
35#include "gnunet_identity_service.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
39
40/**
41 * Handle to a verify request
42 */
43struct GNUNET_CREDENTIAL_Request
44{
45
46 /**
47 * DLL
48 */
49 struct GNUNET_CREDENTIAL_Request *next;
50
51 /**
52 * DLL
53 */
54 struct GNUNET_CREDENTIAL_Request *prev;
55
56 /**
57 * handle to credential service
58 */
59 struct GNUNET_CREDENTIAL_Handle *credential_handle;
60
61 /**
62 * processor to call on verify result
63 */
64 GNUNET_CREDENTIAL_VerifyResultProcessor verify_proc;
65
66 /**
67 * @e verify_proc closure
68 */
69 void *proc_cls;
70
71 /**
72 * Envelope with the message for this queue entry.
73 */
74 struct GNUNET_MQ_Envelope *env;
75
76 /**
77 * request id
78 */
79 uint32_t r_id;
80
81};
82
83
84/**
85 * Connection to the CREDENTIAL service.
86 */
87struct GNUNET_CREDENTIAL_Handle
88{
89
90 /**
91 * Configuration to use.
92 */
93 const struct GNUNET_CONFIGURATION_Handle *cfg;
94
95 /**
96 * Connection to service (if available).
97 */
98 struct GNUNET_MQ_Handle *mq;
99
100 /**
101 * Head of linked list of active verify requests.
102 */
103 struct GNUNET_CREDENTIAL_Request *verify_head;
104
105 /**
106 * Tail of linked list of active verify requests.
107 */
108 struct GNUNET_CREDENTIAL_Request *verify_tail;
109
110 /**
111 * Reconnect task
112 */
113 struct GNUNET_SCHEDULER_Task *reconnect_task;
114
115 /**
116 * How long do we wait until we try to reconnect?
117 */
118 struct GNUNET_TIME_Relative reconnect_backoff;
119
120 /**
121 * Request Id generator. Incremented by one for each request.
122 */
123 uint32_t r_id_gen;
124
125};
126
127
128/**
129 * Reconnect to CREDENTIAL service.
130 *
131 * @param handle the handle to the CREDENTIAL service
132 */
133static void
134reconnect (struct GNUNET_CREDENTIAL_Handle *handle);
135
136
137/**
138 * Reconnect to CREDENTIAL
139 *
140 * @param cls the handle
141 */
142static void
143reconnect_task (void *cls)
144{
145 struct GNUNET_CREDENTIAL_Handle *handle = cls;
146
147 handle->reconnect_task = NULL;
148 reconnect (handle);
149}
150
151
152/**
153 * Disconnect from service and then reconnect.
154 *
155 * @param handle our handle
156 */
157static void
158force_reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
159{
160 GNUNET_MQ_destroy (handle->mq);
161 handle->mq = NULL;
162 handle->reconnect_backoff
163 = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
164 handle->reconnect_task
165 = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
166 &reconnect_task,
167 handle);
168}
169
170
171/**
172 * Generic error handler, called with the appropriate error code and
173 * the same closure specified at the creation of the message queue.
174 * Not every message queue implementation supports an error handler.
175 *
176 * @param cls closure with the `struct GNUNET_CREDENTIAL_Handle *`
177 * @param error error code
178 */
179static void
180mq_error_handler (void *cls,
181 enum GNUNET_MQ_Error error)
182{
183 struct GNUNET_CREDENTIAL_Handle *handle = cls;
184
185 force_reconnect (handle);
186}
187
188
189/**
190 * Check validity of message received from the CREDENTIAL service
191 *
192 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
193 * @param loookup_msg the incoming message
194 */
195static int
196check_result (void *cls,
197 const struct VerifyResultMessage *vr_msg)
198{
199 //TODO
200 return GNUNET_OK;
201}
202
203
204/**
205 * Handler for messages received from the CREDENTIAL service
206 *
207 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
208 * @param loookup_msg the incoming message
209 */
210static void
211handle_result (void *cls,
212 const struct VerifyResultMessage *vr_msg)
213{
214 struct GNUNET_CREDENTIAL_Handle *handle = cls;
215 uint32_t r_id = ntohl (vr_msg->id);
216 struct GNUNET_CREDENTIAL_Request *vr;
217 size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg);
218 uint32_t d_count = ntohl (vr_msg->d_count);
219 uint32_t c_count = ntohl (vr_msg->c_count);
220 struct GNUNET_CREDENTIAL_Delegation d_chain[d_count];
221 struct GNUNET_CREDENTIAL_Credential creds[c_count];
222 GNUNET_CREDENTIAL_VerifyResultProcessor proc;
223 void *proc_cls;
224
225 LOG (GNUNET_ERROR_TYPE_DEBUG,
226 "Received verify reply from CREDENTIAL service\n");
227 for (vr = handle->verify_head; NULL != vr; vr = vr->next)
228 if (vr->r_id == r_id)
229 break;
230 if (NULL == vr)
231 return;
232 proc = vr->verify_proc;
233 proc_cls = vr->proc_cls;
234 GNUNET_CONTAINER_DLL_remove (handle->verify_head,
235 handle->verify_tail,
236 vr);
237 GNUNET_MQ_discard (vr->env);
238 GNUNET_free (vr);
239 GNUNET_assert (GNUNET_OK ==
240 GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen,
241 (const char*) &vr_msg[1],
242 d_count,
243 d_chain,
244 c_count,
245 creds));
246 if (GNUNET_NO == ntohl (vr_msg->cred_found))
247 {
248 proc (proc_cls,
249 0,
250 NULL,
251 0,
252 NULL); // TODO
253 } else {
254 proc (proc_cls,
255 d_count,
256 d_chain,
257 c_count,
258 creds);
259 }
260}
261
262
263/**
264 * Reconnect to CREDENTIAL service.
265 *
266 * @param handle the handle to the CREDENTIAL service
267 */
268static void
269reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
270{
271 struct GNUNET_MQ_MessageHandler handlers[] = {
272 GNUNET_MQ_hd_var_size (result,
273 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
274 struct VerifyResultMessage,
275 handle),
276 GNUNET_MQ_handler_end ()
277 };
278 struct GNUNET_CREDENTIAL_Request *vr;
279
280 GNUNET_assert (NULL == handle->mq);
281 LOG (GNUNET_ERROR_TYPE_DEBUG,
282 "Trying to connect to CREDENTIAL\n");
283 handle->mq = GNUNET_CLIENT_connecT (handle->cfg,
284 "credential",
285 handlers,
286 &mq_error_handler,
287 handle);
288 if (NULL == handle->mq)
289 return;
290 for (vr = handle->verify_head; NULL != vr; vr = vr->next)
291 GNUNET_MQ_send_copy (handle->mq,
292 vr->env);
293}
294
295
296/**
297 * Initialize the connection with the CREDENTIAL service.
298 *
299 * @param cfg configuration to use
300 * @return handle to the CREDENTIAL service, or NULL on error
301 */
302struct GNUNET_CREDENTIAL_Handle *
303GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
304{
305 struct GNUNET_CREDENTIAL_Handle *handle;
306
307 handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
308 handle->cfg = cfg;
309 reconnect (handle);
310 if (NULL == handle->mq)
311 {
312 GNUNET_free (handle);
313 return NULL;
314 }
315 return handle;
316}
317
318
319/**
320 * Shutdown connection with the CREDENTIAL service.
321 *
322 * @param handle handle of the CREDENTIAL connection to stop
323 */
324void
325GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle)
326{
327 if (NULL != handle->mq)
328 {
329 GNUNET_MQ_destroy (handle->mq);
330 handle->mq = NULL;
331 }
332 if (NULL != handle->reconnect_task)
333 {
334 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
335 handle->reconnect_task = NULL;
336 }
337 GNUNET_assert (NULL == handle->verify_head);
338 GNUNET_free (handle);
339}
340
341
342/**
343 * Cancel pending verify request
344 *
345 * @param lr the verify request to cancel
346 */
347void
348GNUNET_CREDENTIAL_verify_cancel (struct GNUNET_CREDENTIAL_Request *vr)
349{
350 struct GNUNET_CREDENTIAL_Handle *handle = vr->credential_handle;
351
352 GNUNET_CONTAINER_DLL_remove (handle->verify_head,
353 handle->verify_tail,
354 vr);
355 GNUNET_MQ_discard (vr->env);
356 GNUNET_free (vr);
357}
358
359/**
360 * Performs attribute verification.
361 * Checks if there is a delegation chain from
362 * attribute ``issuer_attribute'' issued by the issuer
363 * with public key ``issuer_key'' maps to the attribute
364 * ``subject_attribute'' claimed by the subject with key
365 * ``subject_key''
366 *
367 * @param handle handle to the Credential service
368 * @param issuer_key the issuer public key
369 * @param issuer_attribute the issuer attribute
370 * @param subject_key the subject public key
371 * @param subject_attribute the attribute claimed by the subject
372 * @param proc function to call on result
373 * @param proc_cls closure for processor
374 * @return handle to the queued request
375 */
376struct GNUNET_CREDENTIAL_Request*
377GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
378 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
379 const char *issuer_attribute,
380 const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
381 const char *subject_attribute,
382 GNUNET_CREDENTIAL_VerifyResultProcessor proc,
383 void *proc_cls)
384{
385 /* IPC to shorten credential names, return shorten_handle */
386 struct VerifyMessage *v_msg;
387 struct GNUNET_CREDENTIAL_Request *vr;
388 size_t nlen;
389
390 if (NULL == issuer_attribute || NULL == subject_attribute)
391 {
392 GNUNET_break (0);
393 return NULL;
394 }
395 //DEBUG LOG
396 LOG (GNUNET_ERROR_TYPE_DEBUG,
397 "Trying to verify `%s' in CREDENTIAL\n",
398 issuer_attribute);
399 nlen = strlen (issuer_attribute) + strlen (subject_attribute) + 1;
400 if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*vr))
401 {
402 GNUNET_break (0);
403 return NULL;
404 }
405 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
406 vr->credential_handle = handle;
407 vr->verify_proc = proc;
408 vr->proc_cls = proc_cls;
409 vr->r_id = handle->r_id_gen++;
410 vr->env = GNUNET_MQ_msg_extra (v_msg,
411 nlen,
412 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
413 v_msg->id = htonl (vr->r_id);
414 v_msg->subject_key = *subject_key;
415 v_msg->issuer_key = *issuer_key;
416 v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
417 v_msg->subject_attribute_len = htons(strlen(subject_attribute));
418 GNUNET_memcpy (&v_msg[1],
419 issuer_attribute,
420 strlen (issuer_attribute));
421 GNUNET_memcpy (((char*)&v_msg[1]) + strlen (issuer_attribute),
422 subject_attribute,
423 strlen (subject_attribute));
424 GNUNET_CONTAINER_DLL_insert (handle->verify_head,
425 handle->verify_tail,
426 vr);
427 if (NULL != handle->mq)
428 GNUNET_MQ_send_copy (handle->mq,
429 vr->env);
430 return vr;
431}
432
433/* end of credential_api.c */
diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c
new file mode 100644
index 000000000..f1be433e0
--- /dev/null
+++ b/src/credential/credential_misc.c
@@ -0,0 +1,168 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 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
22/**
23 * @file credential/credential_mic.c
24 * @brief Misc API for credentials
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34#include <inttypes.h>
35
36char*
37GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred)
38{
39 char *cred_str;
40 char *subject_pkey;
41 char *issuer_pkey;
42 char *signature;
43
44
45 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
46 issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
47 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
48 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
49 &signature);
50 GNUNET_asprintf (&cred_str,
51 "%s.%s -> %s | %s | %"SCNu64,
52 issuer_pkey,
53 cred->issuer_attribute,
54 subject_pkey,
55 signature,
56 cred->expiration.abs_value_us);
57 GNUNET_free (subject_pkey);
58 GNUNET_free (issuer_pkey);
59 GNUNET_free (signature);
60 return cred_str;
61}
62
63struct GNUNET_CREDENTIAL_Credential*
64GNUNET_CREDENTIAL_credential_from_string (const char* s)
65{
66 struct GNUNET_CREDENTIAL_Credential *cred;
67 size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
68 if (enclen % 5 > 0)
69 enclen += 5 - enclen % 5;
70 enclen /= 5; /* 260/5 = 52 */
71 char subject_pkey[enclen + 1];
72 char issuer_pkey[enclen + 1];
73 char name[253 + 1];
74 char signature[256]; //TODO max payload size
75
76 struct GNUNET_CRYPTO_EcdsaSignature *sig;
77 struct GNUNET_TIME_Absolute etime_abs;
78
79 if (5 != SSCANF (s,
80 "%52s.%253s -> %52s | %s | %"SCNu64,
81 issuer_pkey,
82 name,
83 subject_pkey,
84 signature,
85 &etime_abs.abs_value_us))
86 {
87 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
88 _("Unable to parse CRED record string `%s'\n"),
89 s);
90 return NULL;
91 }
92 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1);
93 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
94 strlen (subject_pkey),
95 &cred->subject_key);
96 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
97 strlen (issuer_pkey),
98 &cred->issuer_key);
99 GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature,
100 strlen (signature),
101 (char**)&sig));
102 cred->signature = *sig;
103 cred->expiration = etime_abs;
104 GNUNET_free (sig);
105 GNUNET_memcpy (&cred[1],
106 name,
107 strlen (name)+1);
108 cred->issuer_attribute = (char*)&cred[1];
109 return cred;
110}
111
112/**
113 * Issue an attribute to a subject
114 *
115 * @param handle handle to the Credential service
116 * @param issuer the ego that should be used to issue the attribute
117 * @param subject the subject of the attribute
118 * @param attribute the name of the attribute
119 * @return handle to the queued request
120 */
121struct GNUNET_CREDENTIAL_Credential *
122GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
123 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
124 const char *attribute,
125 struct GNUNET_TIME_Absolute *expiration)
126{
127 struct CredentialEntry *crd;
128 struct GNUNET_CREDENTIAL_Credential *cred;
129 size_t size;
130
131 size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
132 crd = GNUNET_malloc (size);
133 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1);
134 crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
135
136 crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
137 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
138 &crd->issuer_key);
139 crd->subject_key = *subject;
140 crd->expiration = GNUNET_htonll (expiration->abs_value_us);
141 crd->issuer_attribute_len = htonl (strlen (attribute)+1);
142 GNUNET_memcpy ((char*)&crd[1],
143 attribute,
144 strlen (attribute)+1);
145 if (GNUNET_OK !=
146 GNUNET_CRYPTO_ecdsa_sign (issuer,
147 &crd->purpose,
148 &crd->signature))
149 {
150 GNUNET_break (0);
151 GNUNET_free (crd);
152 return NULL;
153 }
154 cred->signature = crd->signature;
155 cred->expiration = *expiration;
156 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
157 &cred->issuer_key);
158
159 cred->subject_key = *subject;
160 GNUNET_memcpy (&cred[1],
161 attribute,
162 strlen (attribute)+1);
163 cred->issuer_attribute = (char*)&cred[1];
164 GNUNET_free (crd);
165 return cred;
166}
167
168
diff --git a/src/credential/credential_misc.h b/src/credential/credential_misc.h
new file mode 100644
index 000000000..c3aa8c214
--- /dev/null
+++ b/src/credential/credential_misc.h
@@ -0,0 +1,35 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 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 * @file credential/credential_misc.h
22 * @brief Credential helper functions
23 */
24#ifndef CREDENTIAL_MISC_H
25#define CREDENTIAL_MISC_H
26
27
28
29char*
30GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred);
31
32struct GNUNET_CREDENTIAL_Credential*
33GNUNET_CREDENTIAL_credential_from_string (const char* str);
34
35#endif
diff --git a/src/credential/credential_serialization.c b/src/credential/credential_serialization.c
new file mode 100644
index 000000000..0586e6baa
--- /dev/null
+++ b/src/credential/credential_serialization.c
@@ -0,0 +1,390 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 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
22/**
23 * @file credential/credential_serialization.c
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34
35/**
36 * Calculate how many bytes we will need to serialize
37 * the given delegation chain and credential
38 *
39 * @param d_count number of delegation chain entries
40 * @param dd array of #GNUNET_CREDENTIAL_Delegation
41 * @param cd a #GNUNET_CREDENTIAL_Credential
42 * @return the required size to serialize
43 */
44size_t
45GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
46 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
47{
48 unsigned int i;
49 size_t ret;
50
51 ret = sizeof (struct DelegationRecordData) * (ds_count);
52
53 for (i=0; i<ds_count;i++)
54 {
55 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
56 ret += dsr[i].subject_attribute_len;
57 }
58 return ret;
59}
60
61/**
62 * Serizalize the given delegation chain entries and credential
63 *
64 * @param d_count number of delegation chain entries
65 * @param dd array of #GNUNET_CREDENTIAL_Delegation
66 * @param cd a #GNUNET_CREDENTIAL_Credential
67 * @param dest_size size of the destination
68 * @param dest where to store the result
69 * @return the size of the data, -1 on failure
70 */
71ssize_t
72GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
73 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
74 size_t dest_size,
75 char *dest)
76{
77 struct DelegationRecordData rec;
78 unsigned int i;
79 size_t off;
80
81 off = 0;
82 for (i=0;i<d_count;i++)
83 {
84 rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
85 rec.subject_key = dsr[i].subject_key;
86 if (off + sizeof (rec) > dest_size)
87 return -1;
88 GNUNET_memcpy (&dest[off],
89 &rec,
90 sizeof (rec));
91 off += sizeof (rec);
92 if (0 == dsr[i].subject_attribute_len)
93 continue;
94 if (off + dsr[i].subject_attribute_len > dest_size)
95 return -1;
96 GNUNET_memcpy (&dest[off],
97 dsr[i].subject_attribute,
98 dsr[i].subject_attribute_len);
99 off += dsr[i].subject_attribute_len;
100 }
101 return off;
102}
103
104
105/**
106 * Deserialize the given destination
107 *
108 * @param len size of the serialized delegation chain and cred
109 * @param src the serialized data
110 * @param d_count the number of delegation chain entries
111 * @param dd where to put the delegation chain entries
112 * @param cd where to put the credential data
113 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
114 */
115int
116GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
117 const char *src,
118 unsigned int d_count,
119 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
120{
121 struct DelegationRecordData rec;
122 unsigned int i;
123 size_t off;
124
125 off = 0;
126 for (i=0;i<d_count;i++)
127 {
128 if (off + sizeof (rec) > len)
129 return GNUNET_SYSERR;
130 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
131 dsr[i].subject_key = rec.subject_key;
132 off += sizeof (rec);
133 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
134 if (off + dsr[i].subject_attribute_len > len)
135 return GNUNET_SYSERR;
136 dsr[i].subject_attribute = (char*)&src[off];
137 off += dsr[i].subject_attribute_len;
138 }
139 return GNUNET_OK;
140}
141/**
142 * Calculate how many bytes we will need to serialize
143 * the given delegation chain and credential
144 *
145 * @param d_count number of delegation chain entries
146 * @param dd array of #GNUNET_CREDENTIAL_Delegation
147 * @param c_count number of credential entries
148 * @param cd a #GNUNET_CREDENTIAL_Credential
149 * @return the required size to serialize
150 */
151size_t
152GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
153 const struct GNUNET_CREDENTIAL_Delegation *dd,
154 unsigned int c_count,
155 const struct GNUNET_CREDENTIAL_Credential *cd)
156{
157 unsigned int i;
158 size_t ret;
159
160 ret = sizeof (struct ChainEntry) * (d_count);
161 ret += sizeof (struct CredentialEntry) * (c_count);
162
163 for (i=0; i<d_count;i++)
164 {
165 GNUNET_assert ((ret +
166 dd[i].issuer_attribute_len +
167 dd[i].subject_attribute_len) >= ret);
168 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
169 }
170 for (i=0; i<c_count;i++)
171 {
172 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
173 ret += cd[i].issuer_attribute_len;
174 }
175 return ret;
176}
177
178/**
179 * Serizalize the given delegation chain entries and credential
180 *
181 * @param d_count number of delegation chain entries
182 * @param dd array of #GNUNET_CREDENTIAL_Delegation
183 * @param c_count number of credential entries
184 * @param cd a #GNUNET_CREDENTIAL_Credential
185 * @param dest_size size of the destination
186 * @param dest where to store the result
187 * @return the size of the data, -1 on failure
188 */
189ssize_t
190GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
191 const struct GNUNET_CREDENTIAL_Delegation *dd,
192 unsigned int c_count,
193 const struct GNUNET_CREDENTIAL_Credential *cd,
194 size_t dest_size,
195 char *dest)
196{
197 struct ChainEntry rec;
198 struct CredentialEntry c_rec;
199 unsigned int i;
200 size_t off;
201
202 off = 0;
203 for (i=0;i<d_count;i++)
204 {
205 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
206 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
207 rec.issuer_key = dd[i].issuer_key;
208 rec.subject_key = dd[i].subject_key;
209 if (off + sizeof (rec) > dest_size)
210 return -1;
211 GNUNET_memcpy (&dest[off],
212 &rec,
213 sizeof (rec));
214 off += sizeof (rec);
215 if (off + dd[i].issuer_attribute_len > dest_size)
216 return -1;
217 GNUNET_memcpy (&dest[off],
218 dd[i].issuer_attribute,
219 dd[i].issuer_attribute_len);
220 off += dd[i].issuer_attribute_len;
221 if (0 == dd[i].subject_attribute_len)
222 continue;
223 if (off + dd[i].subject_attribute_len > dest_size)
224 return -1;
225 GNUNET_memcpy (&dest[off],
226 dd[i].subject_attribute,
227 dd[i].subject_attribute_len);
228 off += dd[i].subject_attribute_len;
229 }
230 for (i=0;i<c_count;i++)
231 {
232 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
233 c_rec.issuer_key = cd[i].issuer_key;
234 c_rec.subject_key = cd[i].subject_key;
235 c_rec.signature = cd[i].signature;
236 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
237 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
238 c_rec.expiration = htonl ((uint32_t) cd[i].expiration.abs_value_us);
239 if (off + sizeof (c_rec) > dest_size)
240 return -1;
241 GNUNET_memcpy (&dest[off],
242 &c_rec,
243 sizeof (c_rec));
244 off += sizeof (c_rec);
245 if (off + cd[i].issuer_attribute_len > dest_size)
246 return -1;
247 GNUNET_memcpy (&dest[off],
248 cd[i].issuer_attribute,
249 cd[i].issuer_attribute_len);
250 off += cd[i].issuer_attribute_len;
251 }
252
253 return off;
254}
255
256
257/**
258 * Deserialize the given destination
259 *
260 * @param len size of the serialized delegation chain and cred
261 * @param src the serialized data
262 * @param d_count the number of delegation chain entries
263 * @param dd where to put the delegation chain entries
264 * @param c_count the number of credential entries
265 * @param cd where to put the credential data
266 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
267 */
268int
269GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
270 const char *src,
271 unsigned int d_count,
272 struct GNUNET_CREDENTIAL_Delegation *dd,
273 unsigned int c_count,
274 struct GNUNET_CREDENTIAL_Credential *cd)
275{
276 struct ChainEntry rec;
277 struct CredentialEntry c_rec;
278 unsigned int i;
279 size_t off;
280
281 off = 0;
282 for (i=0;i<d_count;i++)
283 {
284 if (off + sizeof (rec) > len)
285 return GNUNET_SYSERR;
286 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
287 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
288 dd[i].issuer_key = rec.issuer_key;
289 dd[i].subject_key = rec.subject_key;
290 off += sizeof (rec);
291 if (off + dd[i].issuer_attribute_len > len)
292 return GNUNET_SYSERR;
293 dd[i].issuer_attribute = &src[off];
294 off += dd[i].issuer_attribute_len;
295 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
296 if (off + dd[i].subject_attribute_len > len)
297 return GNUNET_SYSERR;
298 dd[i].subject_attribute = &src[off];
299 off += dd[i].subject_attribute_len;
300 }
301 for (i=0;i<c_count;i++)
302 {
303 if (off + sizeof (c_rec) > len)
304 return GNUNET_SYSERR;
305 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
306 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
307 cd[i].issuer_key = c_rec.issuer_key;
308 cd[i].subject_key = c_rec.subject_key;
309 cd[i].signature = c_rec.signature;
310 cd[i].expiration.abs_value_us = ntohl((uint32_t) c_rec.expiration);
311 off += sizeof (c_rec);
312 if (off + cd[i].issuer_attribute_len > len)
313 return GNUNET_SYSERR;
314 cd[i].issuer_attribute = &src[off];
315 off += cd[i].issuer_attribute_len;
316 }
317 return GNUNET_OK;
318}
319
320
321int
322GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
323 char **data)
324{
325 size_t size;
326 struct CredentialEntry *cdata;
327
328 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
329 *data = GNUNET_malloc (size);
330 cdata = (struct CredentialEntry*)*data;
331 cdata->subject_key = cred->subject_key;
332 cdata->issuer_key = cred->issuer_key;
333 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
334 cdata->signature = cred->signature;
335 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
336 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
337 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
338 GNUNET_memcpy (&cdata[1],
339 cred->issuer_attribute,
340 strlen (cred->issuer_attribute));
341
342 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
343 &cdata->purpose,
344 &cdata->signature,
345 &cdata->issuer_key))
346 {
347 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
348 "Invalid credential\n");
349 //return NULL;
350 }
351 return size;
352}
353
354struct GNUNET_CREDENTIAL_Credential*
355GNUNET_CREDENTIAL_credential_deserialize (const char* data,
356 size_t data_size)
357{
358 struct GNUNET_CREDENTIAL_Credential *cred;
359 struct CredentialEntry *cdata;
360 char *issuer_attribute;
361
362 if (data_size < sizeof (struct CredentialEntry))
363 return NULL;
364 cdata = (struct CredentialEntry*)data;
365 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
366 &cdata->purpose,
367 &cdata->signature,
368 &cdata->issuer_key))
369 {
370 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
371 "Invalid credential\n");
372 //return NULL;
373 }
374 issuer_attribute = (char*)&cdata[1];
375
376 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
377
378 cred->issuer_key = cdata->issuer_key;
379 cred->subject_key = cdata->subject_key;
380 GNUNET_memcpy (&cred[1],
381 issuer_attribute,
382 ntohl (cdata->issuer_attribute_len));
383 cred->signature = cdata->signature;
384 cred->issuer_attribute = (char*)&cred[1];
385 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
386 return cred;
387}
388
389
390/* end of credential_serialization.c */
diff --git a/src/credential/credential_serialization.h b/src/credential/credential_serialization.h
new file mode 100644
index 000000000..eb1327f34
--- /dev/null
+++ b/src/credential/credential_serialization.h
@@ -0,0 +1,142 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 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
22/**
23 * @file credential/credential_serialization.h
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#ifndef CREDENTIAL_SERIALIZATION_H
29#define CREDENTIAL_SERIALIZATION_H
30
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_constants.h"
34#include "gnunet_credential_service.h"
35
36/**
37 * Calculate how many bytes we will need to serialize
38 * the given delegation record
39 *
40 * @param ds_count number of delegation chain entries
41 * @param dsr array of #GNUNET_CREDENTIAL_Delegation
42 * @return the required size to serialize
43 */
44size_t
45GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
46 const struct GNUNET_CREDENTIAL_DelegationSet *dsr);
47
48/**
49 * Serizalize the given delegation record entries
50 *
51 * @param d_count number of delegation chain entries
52 * @param dsr array of #GNUNET_CREDENTIAL_Delegation
53 * @param dest_size size of the destination
54 * @param dest where to store the result
55 * @return the size of the data, -1 on failure
56 */
57ssize_t
58GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
59 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
60 size_t dest_size,
61 char *dest);
62
63
64/**
65 * Deserialize the given destination
66 *
67 * @param len size of the serialized delegation recird
68 * @param src the serialized data
69 * @param d_count the number of delegation chain entries
70 * @param dsr where to put the delegation chain entries
71 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
72 */
73int
74GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
75 const char *src,
76 unsigned int d_count,
77 struct GNUNET_CREDENTIAL_DelegationSet *dsr);
78
79 /**
80 * Calculate how many bytes we will need to serialize
81 * the given delegation chain and credential
82 *
83 * @param d_count number of delegation chain entries
84 * @param dd array of #GNUNET_CREDENTIAL_Delegation
85 * @param c_count number of credential entries
86 * @param cd a #GNUNET_CREDENTIAL_Credential
87 * @return the required size to serialize
88 */
89 size_t
90 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
91 const struct GNUNET_CREDENTIAL_Delegation *dd,
92 unsigned int c_count,
93 const struct GNUNET_CREDENTIAL_Credential *cd);
94
95 /**
96 * Serizalize the given delegation chain entries and credential
97 *
98 * @param d_count number of delegation chain entries
99 * @param dd array of #GNUNET_CREDENTIAL_Delegation
100 * @param c_count number of credential entries
101 * @param cd a #GNUNET_CREDENTIAL_Credential
102 * @param dest_size size of the destination
103 * @param dest where to store the result
104 * @return the size of the data, -1 on failure
105 */
106 ssize_t
107 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
108 const struct GNUNET_CREDENTIAL_Delegation *dd,
109 unsigned int c_count,
110 const struct GNUNET_CREDENTIAL_Credential *cd,
111 size_t dest_size,
112 char *dest);
113
114
115 /**
116 * Deserialize the given destination
117 *
118 * @param len size of the serialized delegation chain and cred
119 * @param src the serialized data
120 * @param d_count the number of delegation chain entries
121 * @param dd where to put the delegation chain entries
122 * @param c_count number of credential entries
123 * @param cd where to put the credential data
124 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
125 */
126 int
127 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
128 const char *src,
129 unsigned int d_count,
130 struct GNUNET_CREDENTIAL_Delegation *dd,
131 unsigned int c_count,
132 struct GNUNET_CREDENTIAL_Credential *cd);
133
134int
135GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
136 char **data);
137
138struct GNUNET_CREDENTIAL_Credential*
139GNUNET_CREDENTIAL_credential_deserialize (const char* data,
140 size_t data_size);
141#endif
142/* end of credential_serialization.h */
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c
new file mode 100644
index 000000000..b31c2f66e
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,446 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2013 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 * @file gnunet-credential.c
22 * @brief command line tool to access command line Credential service
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include <gnunet_util_lib.h>
27#include <gnunet_credential_service.h>
28#include <gnunet_gnsrecord_lib.h>
29#include "credential_misc.h"
30#include "credential_serialization.h"
31
32/**
33 * Configuration we are using.
34 */
35static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37/**
38 * EgoLookup
39 */
40static struct GNUNET_IDENTITY_EgoLookup *el;
41
42/**
43 * Handle to Credential service.
44 */
45static struct GNUNET_CREDENTIAL_Handle *credential;
46
47/**
48 * Desired timeout for the lookup (default is no timeout).
49 */
50static struct GNUNET_TIME_Relative timeout;
51
52/**
53 * Handle to verify request
54 */
55static struct GNUNET_CREDENTIAL_Request *verify_request;
56
57/**
58 * Task scheduled to handle timeout.
59 */
60static struct GNUNET_SCHEDULER_Task *tt;
61
62/**
63 * Subject pubkey string
64 */
65static char *subject_key;
66
67/**
68 * Subject credential string
69 */
70static char *subject_credential;
71
72/**
73 * Credential TTL
74 */
75static char *expiration;
76
77/**
78 * Subject key
79 */
80struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
81
82/**
83 * Issuer key
84 */
85struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
86
87
88/**
89 * Issuer pubkey string
90 */
91static char *issuer_key;
92
93/**
94 * Issuer ego
95 */
96static char *issuer_ego_name;
97
98/**
99 * Issuer attribute
100 */
101static char *issuer_attr;
102
103/**
104 * Verify mode
105 */
106static uint32_t verify;
107
108/**
109 * Issue mode
110 */
111static uint32_t create_cred;
112
113
114/**
115 * Task run on shutdown. Cleans up everything.
116 *
117 * @param cls unused
118 */
119static void
120do_shutdown (void *cls)
121{
122 if (NULL != verify_request)
123 {
124 GNUNET_CREDENTIAL_verify_cancel (verify_request);
125 verify_request = NULL;
126 }
127 if (NULL != credential)
128 {
129 GNUNET_CREDENTIAL_disconnect (credential);
130 credential = NULL;
131 }
132 if (NULL != tt)
133 {
134 GNUNET_SCHEDULER_cancel (tt);
135 tt = NULL;
136 }
137}
138
139
140/**
141 * Task run on timeout. Triggers shutdown.
142 *
143 * @param cls unused
144 */
145static void
146do_timeout (void *cls)
147{
148 tt = NULL;
149 GNUNET_SCHEDULER_shutdown ();
150}
151
152
153/**
154 * Function called with the result of a Credential lookup.
155 *
156 * @param cls the 'const char *' name that was resolved
157 * @param cd_count number of records returned
158 * @param cd array of @a cd_count records with the results
159 */
160static void
161handle_verify_result (void *cls,
162 unsigned int d_count,
163 struct GNUNET_CREDENTIAL_Delegation *dc,
164 unsigned int c_count,
165 struct GNUNET_CREDENTIAL_Credential *cred)
166{
167 int i;
168 char* iss_key;
169 char* sub_key;
170
171 verify_request = NULL;
172 if (NULL == cred)
173 printf ("Failed.\n");
174 else
175 {
176 printf("Delegation Chain:\n");
177 for (i=0;i<d_count;i++)
178 {
179 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
180 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
181 if (0 != dc[i].subject_attribute_len)
182 {
183 printf ("(%d) %s.%s <- %s.%s\n", i,
184 iss_key, dc[i].issuer_attribute,
185 sub_key, dc[i].subject_attribute);
186 } else {
187 printf ("(%d) %s.%s <- %s\n", i,
188 iss_key, dc[i].issuer_attribute,
189 sub_key);
190 }
191 GNUNET_free (iss_key);
192 GNUNET_free (sub_key);
193 }
194 printf("\nCredentials:\n");
195 for (i=0;i<c_count;i++)
196 {
197 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
198 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
199 printf ("%s.%s <- %s\n",
200 iss_key, cred[i].issuer_attribute,
201 sub_key);
202 GNUNET_free (iss_key);
203 GNUNET_free (sub_key);
204
205 }
206 printf ("Successful.\n");
207 }
208
209
210 GNUNET_SCHEDULER_shutdown ();
211}
212
213/**
214 * Callback invoked from identity service with ego information.
215 * An @a ego of NULL means the ego was not found.
216 *
217 * @param cls closure with the configuration
218 * @param ego an ego known to identity service, or NULL
219 */
220static void
221identity_cb (void *cls,
222 const struct GNUNET_IDENTITY_Ego *ego)
223{
224 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
225 struct GNUNET_CREDENTIAL_Credential *crd;
226 struct GNUNET_TIME_Absolute etime_abs;
227 struct GNUNET_TIME_Relative etime_rel;
228 char *res;
229
230 el = NULL;
231 if (NULL == ego)
232 {
233 if (NULL != issuer_ego_name)
234 {
235 fprintf (stderr,
236 _("Ego `%s' not known to identity service\n"),
237 issuer_ego_name);
238 }
239 GNUNET_SCHEDULER_shutdown ();
240 return;
241 }
242 if (NULL == expiration)
243 {
244 fprintf (stderr,
245 "Please specify a TTL\n");
246 GNUNET_SCHEDULER_shutdown ();
247 return;
248 } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
249 &etime_rel))
250 {
251 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
252 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
253 &etime_abs))
254 {
255 fprintf (stderr,
256 "%s is not a valid ttl!\n",
257 expiration);
258 GNUNET_SCHEDULER_shutdown ();
259 return;
260 }
261
262
263 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
264 GNUNET_free_non_null (issuer_ego_name);
265 issuer_ego_name = NULL;
266 crd = GNUNET_CREDENTIAL_credential_issue (privkey,
267 &subject_pkey,
268 issuer_attr,
269 &etime_abs);
270
271 res = GNUNET_CREDENTIAL_credential_to_string (crd);
272 GNUNET_free (crd);
273 printf ("%s\n", res);
274 GNUNET_SCHEDULER_shutdown ();
275}
276
277
278
279
280/**
281 * Main function that will be run.
282 *
283 * @param cls closure
284 * @param args remaining command-line arguments
285 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
286 * @param c configuration
287 */
288static void
289run (void *cls,
290 char *const *args,
291 const char *cfgfile,
292 const struct GNUNET_CONFIGURATION_Handle *c)
293{
294
295 cfg = c;
296
297
298 tt = GNUNET_SCHEDULER_add_delayed (timeout,
299 &do_timeout, NULL);
300 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
301
302
303
304 if (NULL == subject_key)
305 {
306 fprintf (stderr,
307 _("Subject public key needed\n"));
308 GNUNET_SCHEDULER_shutdown ();
309 return;
310
311 }
312 if (GNUNET_OK !=
313 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
314 strlen (subject_key),
315 &subject_pkey))
316 {
317 fprintf (stderr,
318 _("Subject public key `%s' is not well-formed\n"),
319 subject_key);
320 GNUNET_SCHEDULER_shutdown ();
321 return;
322 }
323
324 if (GNUNET_YES == verify) {
325 if (NULL == issuer_key)
326 {
327 fprintf (stderr,
328 _("Issuer public key not well-formed\n"));
329 GNUNET_SCHEDULER_shutdown ();
330 return;
331
332 }
333 if (GNUNET_OK !=
334 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
335 strlen (issuer_key),
336 &issuer_pkey))
337 {
338 fprintf (stderr,
339 _("Issuer public key `%s' is not well-formed\n"),
340 issuer_key);
341 GNUNET_SCHEDULER_shutdown ();
342 }
343 credential = GNUNET_CREDENTIAL_connect (cfg);
344
345 if (NULL == credential)
346 {
347 fprintf (stderr,
348 _("Failed to connect to CREDENTIAL\n"));
349 GNUNET_SCHEDULER_shutdown ();
350 }
351
352 if (NULL == issuer_attr || NULL == subject_credential)
353 {
354 fprintf (stderr,
355 _("You must provide issuer and subject attributes\n"));
356 GNUNET_SCHEDULER_shutdown ();
357 }
358
359 printf ("Trying to find a chain from a credential under %s of %s to the attribute %s issued by %s\n",
360 subject_credential, subject_key, issuer_attr, issuer_key);
361
362 verify_request = GNUNET_CREDENTIAL_verify(credential,
363 &issuer_pkey,
364 issuer_attr, //TODO argument
365 &subject_pkey,
366 subject_credential,
367 &handle_verify_result,
368 NULL);
369 } else if (GNUNET_YES == create_cred) {
370 if (NULL == issuer_ego_name)
371 {
372 fprintf (stderr,
373 _("Issuer ego required\n"));
374 GNUNET_SCHEDULER_shutdown ();
375 return;
376
377 }
378 el = GNUNET_IDENTITY_ego_lookup (cfg,
379 issuer_ego_name,
380 &identity_cb,
381 (void *) cfg);
382 return;
383 } else {
384 fprintf (stderr,
385 _("Please specify name to lookup, subject key and issuer key!\n"));
386 GNUNET_SCHEDULER_shutdown ();
387 }
388 return;
389}
390
391
392/**
393 * The main function for gnunet-gns.
394 *
395 * @param argc number of arguments from the command line
396 * @param argv command line arguments
397 * @return 0 ok, 1 on error
398 */
399int
400main (int argc, char *const *argv)
401{
402 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
403 {'I', "issue", NULL,
404 gettext_noop ("create credential"), 0,
405 &GNUNET_GETOPT_set_one, &create_cred},
406 {'V', "verify", NULL,
407 gettext_noop ("verify credential against attribute"), 0,
408 &GNUNET_GETOPT_set_one, &verify},
409 {'s', "subject", "PKEY",
410 gettext_noop ("The public key of the subject to lookup the credential for"), 1,
411 &GNUNET_GETOPT_set_string, &subject_key},
412 {'b', "credential", "CRED",
413 gettext_noop ("The name of the credential presented by the subject"), 1,
414 &GNUNET_GETOPT_set_string, &subject_credential},
415 {'i', "issuer", "PKEY",
416 gettext_noop ("The public key of the authority to verify the credential against"), 1,
417 &GNUNET_GETOPT_set_string, &issuer_key},
418 {'e', "ego", "EGO",
419 gettext_noop ("The ego to use to issue"), 1,
420 &GNUNET_GETOPT_set_string, &issuer_ego_name},
421 {'a', "attribute", "ATTR",
422 gettext_noop ("The issuer attribute to verify against or to issue"), 1,
423 &GNUNET_GETOPT_set_string, &issuer_attr},
424 {'T', "ttl", "EXP",
425 gettext_noop ("The time to live for the credential"), 1,
426 &GNUNET_GETOPT_set_string, &expiration},
427 GNUNET_GETOPT_OPTION_END
428 };
429 int ret;
430
431 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
432 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
433 return 2;
434
435 GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
436 ret =
437 (GNUNET_OK ==
438 GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
439 _("GNUnet credential resolver tool"),
440 options,
441 &run, NULL)) ? 0 : 1;
442 GNUNET_free ((void*) argv);
443 return ret;
444}
445
446/* end of gnunet-credential.c */
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c
new file mode 100644
index 000000000..942b38652
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1028 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 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 * @file gns/gnunet-service-credential.c
22 * @brief GNU Credential Service (main service)
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_credential_service.h"
28#include "gnunet_statistics_service.h"
29#include "credential.h"
30#include "credential_serialization.h"
31#include "gnunet_protocols.h"
32#include "gnunet_signatures.h"
33
34// For Looking up GNS request
35#include <gnunet_dnsparser_lib.h>
36#include <gnunet_identity_service.h>
37#include <gnunet_gnsrecord_lib.h>
38#include <gnunet_namestore_service.h>
39#include <gnunet_gns_service.h>
40#include "gnunet_gns_service.h"
41
42
43
44
45#define GNUNET_CREDENTIAL_MAX_LENGTH 255
46
47struct VerifyRequestHandle;
48
49struct DelegationSetQueueEntry;
50
51
52struct DelegationChainEntry
53{
54 /**
55 * DLL
56 */
57 struct DelegationChainEntry *next;
58
59 /**
60 * DLL
61 */
62 struct DelegationChainEntry *prev;
63
64 /**
65 * The issuer
66 */
67 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
68
69 /**
70 * The subject
71 */
72 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
73
74 /**
75 * The issued attribute
76 */
77 char *issuer_attribute;
78
79 /**
80 * The delegated attribute
81 */
82 char *subject_attribute;
83};
84
85/**
86 * DLL for record
87 */
88struct CredentialRecordEntry
89{
90 /**
91 * DLL
92 */
93 struct CredentialRecordEntry *next;
94
95 /**
96 * DLL
97 */
98 struct CredentialRecordEntry *prev;
99
100
101 /**
102 * Payload
103 */
104 struct GNUNET_CREDENTIAL_Credential *credential;
105};
106
107/**
108 * DLL used for delegations
109 * Used for OR delegations
110 */
111struct DelegationQueueEntry
112{
113 /**
114 * DLL
115 */
116 struct DelegationQueueEntry *next;
117
118 /**
119 * DLL
120 */
121 struct DelegationQueueEntry *prev;
122
123 /**
124 * Sets under this Queue
125 */
126 struct DelegationSetQueueEntry *set_entries_head;
127
128 /**
129 * Sets under this Queue
130 */
131 struct DelegationSetQueueEntry *set_entries_tail;
132
133 /**
134 * Parent set
135 */
136 struct DelegationSetQueueEntry *parent_set;
137
138 /**
139 * Required solutions
140 */
141 uint32_t required_solutions;
142};
143
144/**
145 * DLL for delegation sets
146 * Used for AND delegation set
147 */
148struct DelegationSetQueueEntry
149{
150 /**
151 * DLL
152 */
153 struct DelegationSetQueueEntry *next;
154
155 /**
156 * DLL
157 */
158 struct DelegationSetQueueEntry *prev;
159
160 /**
161 * GNS handle
162 */
163 struct GNUNET_GNS_LookupRequest *lookup_request;
164
165 /**
166 * Verify handle
167 */
168 struct VerifyRequestHandle *handle;
169
170 /**
171 * Parent attribute delegation
172 */
173 struct DelegationQueueEntry *parent;
174
175 /**
176 * Issuer key
177 */
178 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
179
180 /**
181 * Queue entries of this set
182 */
183 struct DelegationQueueEntry *queue_entries_head;
184
185 /**
186 * Queue entries of this set
187 */
188 struct DelegationQueueEntry *queue_entries_tail;
189
190 /**
191 * Parent QueueEntry
192 */
193 struct DelegationQueueEntry *parent_queue_entry;
194
195 /**
196 * Issuer attribute delegated to
197 */
198 char *issuer_attribute;
199
200 /**
201 * The current attribute to look up
202 */
203 char *lookup_attribute;
204
205 /**
206 * Trailing attribute context
207 */
208 char *attr_trailer;
209
210 /**
211 * Still to resolve delegation as string
212 */
213 char *unresolved_attribute_delegation;
214
215 /**
216 * The delegation chain entry
217 */
218 struct DelegationChainEntry *delegation_chain_entry;
219
220};
221
222
223/**
224 * Handle to a lookup operation from api
225 */
226struct VerifyRequestHandle
227{
228
229 /**
230 * We keep these in a DLL.
231 */
232 struct VerifyRequestHandle *next;
233
234 /**
235 * We keep these in a DLL.
236 */
237 struct VerifyRequestHandle *prev;
238
239 /**
240 * Handle to the requesting client
241 */
242 struct GNUNET_SERVICE_Client *client;
243
244 /**
245 * GNS handle
246 */
247 struct GNUNET_GNS_LookupRequest *lookup_request;
248
249 /**
250 * Size of delegation tree
251 */
252 uint32_t delegation_chain_size;
253
254 /**
255 * Children of this attribute
256 */
257 struct DelegationChainEntry *delegation_chain_head;
258
259 /**
260 * Children of this attribute
261 */
262 struct DelegationChainEntry *delegation_chain_tail;
263
264 /**
265 * Issuer public key
266 */
267 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
268
269 /**
270 * Issuer attribute
271 */
272 char *issuer_attribute;
273
274 /**
275 * Subject public key
276 */
277 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
278
279 /**
280 * Credential DLL
281 */
282 struct CredentialRecordEntry *cred_chain_head;
283
284 /**
285 * Credential DLL
286 */
287 struct CredentialRecordEntry *cred_chain_tail;
288
289 /**
290 * Credential DLL size
291 */
292 uint32_t cred_chain_size;
293
294 /**
295 * Root Delegation Set
296 */
297 struct DelegationSetQueueEntry *root_set;
298
299 /**
300 * Current Delegation Pointer
301 */
302 struct DelegationQueueEntry *current_delegation;
303
304 /**
305 * request id
306 */
307 uint32_t request_id;
308
309 /**
310 * Pending lookups
311 */
312 uint64_t pending_lookups;
313
314};
315
316
317/**
318 * Head of the DLL.
319 */
320static struct VerifyRequestHandle *vrh_head;
321
322/**
323 * Tail of the DLL.
324 */
325static struct VerifyRequestHandle *vrh_tail;
326
327/**
328 * Handle to the statistics service
329 */
330static struct GNUNET_STATISTICS_Handle *statistics;
331
332/**
333 * Handle to GNS service.
334 */
335static struct GNUNET_GNS_Handle *gns;
336
337
338static void
339cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
340{
341 struct DelegationQueueEntry *dq_entry;
342 struct DelegationSetQueueEntry *child;
343
344 if (NULL == ds_entry)
345 return;
346
347 for (dq_entry = ds_entry->queue_entries_head;
348 NULL != dq_entry;
349 dq_entry = ds_entry->queue_entries_head)
350 {
351 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
352 ds_entry->queue_entries_tail,
353 dq_entry);
354 for (child = dq_entry->set_entries_head;
355 NULL != child;
356 child = dq_entry->set_entries_head)
357 {
358 GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
359 dq_entry->set_entries_tail,
360 child);
361 cleanup_delegation_set (child);
362 }
363 GNUNET_free (dq_entry);
364 }
365 if (NULL != ds_entry->issuer_key)
366 GNUNET_free (ds_entry->issuer_key);
367 if (NULL != ds_entry->lookup_attribute)
368 GNUNET_free (ds_entry->lookup_attribute);
369 if (NULL != ds_entry->issuer_attribute)
370 GNUNET_free (ds_entry->issuer_attribute);
371 if (NULL != ds_entry->unresolved_attribute_delegation)
372 GNUNET_free (ds_entry->unresolved_attribute_delegation);
373 if (NULL != ds_entry->attr_trailer)
374 GNUNET_free (ds_entry->attr_trailer);
375 if (NULL != ds_entry->lookup_request)
376 {
377 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
378 ds_entry->lookup_request = NULL;
379 }
380 if (NULL != ds_entry->delegation_chain_entry)
381 {
382 if (NULL != ds_entry->delegation_chain_entry->subject_attribute)
383 GNUNET_free (ds_entry->delegation_chain_entry->subject_attribute);
384 if (NULL != ds_entry->delegation_chain_entry->issuer_attribute)
385 GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
386 GNUNET_free (ds_entry->delegation_chain_entry);
387 }
388 GNUNET_free (ds_entry);
389}
390
391static void
392cleanup_handle (struct VerifyRequestHandle *vrh)
393{
394 struct CredentialRecordEntry *cr_entry;
395 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
396 "Cleaning up...\n");
397 if (NULL != vrh->lookup_request)
398 {
399 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
400 vrh->lookup_request = NULL;
401 }
402 cleanup_delegation_set (vrh->root_set);
403 if (NULL != vrh->issuer_attribute)
404 GNUNET_free (vrh->issuer_attribute);
405 for (cr_entry = vrh->cred_chain_head;
406 NULL != vrh->cred_chain_head;
407 cr_entry = vrh->cred_chain_head)
408 {
409 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
410 vrh->cred_chain_tail,
411 cr_entry);
412 if (NULL != cr_entry->credential);
413 GNUNET_free (cr_entry->credential);
414 GNUNET_free (cr_entry);
415 }
416 GNUNET_free (vrh);
417}
418
419/**
420 * Task run during shutdown.
421 *
422 * @param cls unused
423 * @param tc unused
424 */
425static void
426shutdown_task (void *cls)
427{
428 struct VerifyRequestHandle *vrh;
429
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
431 "Shutting down!\n");
432
433 while (NULL != (vrh = vrh_head))
434 {
435 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
436 GNUNET_CONTAINER_DLL_remove (vrh_head,
437 vrh_tail,
438 vrh);
439 cleanup_handle (vrh);
440 }
441
442 if (NULL != gns)
443 {
444 GNUNET_GNS_disconnect (gns);
445 gns = NULL;
446 }
447 if (NULL != statistics)
448 {
449 GNUNET_STATISTICS_destroy (statistics,
450 GNUNET_NO);
451 statistics = NULL;
452 }
453
454}
455
456/**
457 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
458 *
459 * @param cls client sending the message
460 * @param v_msg message of type `struct VerifyMessage`
461 * @return #GNUNET_OK if @a v_msg is well-formed
462 */
463static int
464check_verify (void *cls,
465 const struct VerifyMessage *v_msg)
466{
467 size_t msg_size;
468 const char* attrs;
469
470 msg_size = ntohs (v_msg->header.size);
471 if (msg_size < sizeof (struct VerifyMessage))
472 {
473 GNUNET_break (0);
474 return GNUNET_SYSERR;
475 }
476 if ((ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) ||
477 (ntohs (v_msg->subject_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH))
478 {
479 GNUNET_break (0);
480 return GNUNET_SYSERR;
481 }
482 attrs = (const char *) &v_msg[1];
483
484 if ( ('\0' != attrs[ntohs(v_msg->header.size) - sizeof (struct VerifyMessage) - 1]) ||
485 (strlen (attrs) > GNUNET_CREDENTIAL_MAX_LENGTH * 2) )
486 {
487 GNUNET_break (0);
488 return GNUNET_SYSERR;
489 }
490 return GNUNET_OK;
491}
492
493/**
494 * Send.
495 *
496 * @param handle the handle to the request
497 */
498static void
499send_lookup_response (struct VerifyRequestHandle *vrh)
500{
501 struct GNUNET_MQ_Envelope *env;
502 struct VerifyResultMessage *rmsg;
503 struct DelegationChainEntry *dce;
504 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
505 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
506 struct CredentialRecordEntry *cd;
507 size_t size;
508 int i;
509
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511 "Sending response\n");
512 dce = vrh->delegation_chain_head;
513 for (i=0;i<vrh->delegation_chain_size;i++)
514 {
515 dd[i].issuer_key = dce->issuer_key;
516 dd[i].subject_key = dce->subject_key;
517 dd[i].issuer_attribute = dce->issuer_attribute;
518 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
519 dd[i].subject_attribute_len = 0;
520 dd[i].subject_attribute = NULL;
521 if (NULL != dce->subject_attribute)
522 {
523 dd[i].subject_attribute = dce->subject_attribute;
524 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
525 }
526 dce = dce->next;
527 }
528
529 /**
530 * Get serialized record data
531 * Append at the end of rmsg
532 */
533 cd = vrh->cred_chain_head;
534 for (i=0;i<vrh->cred_chain_size;i++)
535 {
536 cred[i].issuer_key = cd->credential->issuer_key;
537 cred[i].subject_key = cd->credential->subject_key;
538 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
539 cred[i].issuer_attribute = cd->credential->issuer_attribute;
540 cred[i].expiration = cd->credential->expiration;
541 cred[i].signature = cd->credential->signature;
542 cd = cd->next;
543 }
544 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
545 dd,
546 vrh->cred_chain_size,
547 cred);
548 env = GNUNET_MQ_msg_extra (rmsg,
549 size,
550 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
551 //Assign id so that client can find associated request
552 rmsg->id = vrh->request_id;
553 rmsg->d_count = htonl (vrh->delegation_chain_size);
554 rmsg->c_count = htonl (vrh->cred_chain_size);
555
556 if (0 < vrh->cred_chain_size)
557 rmsg->cred_found = htonl (GNUNET_YES);
558 else
559 rmsg->cred_found = htonl (GNUNET_NO);
560
561 GNUNET_assert (-1 !=
562 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
563 dd,
564 vrh->cred_chain_size,
565 cred,
566 size,
567 (char*)&rmsg[1]));
568
569 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
570 env);
571 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
572 cleanup_handle(vrh);
573
574 GNUNET_STATISTICS_update (statistics,
575 "Completed verifications", 1,
576 GNUNET_NO);
577}
578
579
580static void
581backward_resolution (void* cls,
582 uint32_t rd_count,
583 const struct GNUNET_GNSRECORD_Data *rd)
584{
585
586 struct VerifyRequestHandle *vrh;
587 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
588 struct CredentialRecordEntry *cred_pointer;
589 struct DelegationSetQueueEntry *current_set;
590 struct DelegationSetQueueEntry *ds_entry;
591 struct DelegationSetQueueEntry *tmp_set;
592 struct DelegationQueueEntry *dq_entry;
593 char *expanded_attr;
594 char *lookup_attribute;
595 int i;
596 int j;
597
598
599 current_set = cls;
600 current_set->lookup_request = NULL;
601 vrh = current_set->handle;
602 vrh->pending_lookups--;
603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
604 "Got %d attrs\n", rd_count);
605
606 // Each OR
607 for (i=0; i < rd_count; i++)
608 {
609 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
610 continue;
611
612 sets = rd[i].data;
613 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
615 "Found new attribute delegation with %d sets. Creating new Job...\n",
616 ntohl (sets->set_count));
617
618 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
619 (const char*)&sets[1],
620 ntohl(sets->set_count),
621 set))
622 {
623 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
624 "Failed to deserialize!\n");
625 continue;
626 }
627 dq_entry = GNUNET_new (struct DelegationQueueEntry);
628 dq_entry->required_solutions = ntohl(sets->set_count);
629 dq_entry->parent_set = current_set;
630 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
631 current_set->queue_entries_tail,
632 dq_entry);
633 // Each AND
634 for (j=0; j<ntohl(sets->set_count); j++)
635 {
636 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
637 if (NULL != current_set->attr_trailer)
638 {
639 if (0 == set[j].subject_attribute_len)
640 {
641 GNUNET_asprintf (&expanded_attr,
642 "%s",
643 current_set->attr_trailer);
644
645 } else {
646 GNUNET_asprintf (&expanded_attr,
647 "%s.%s",
648 set[j].subject_attribute,
649 current_set->attr_trailer);
650 }
651 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
652 "Expanded to %s\n", expanded_attr);
653 ds_entry->unresolved_attribute_delegation = expanded_attr;
654 } else {
655 if (0 != set[j].subject_attribute_len)
656 {
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658 "Not Expanding %s\n", set[j].subject_attribute);
659 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
660 }
661 }
662
663 //Add a credential chain entry
664 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
665 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
666 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
667 GNUNET_memcpy (ds_entry->issuer_key,
668 &set[j].subject_key,
669 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
670 if (0 < set[j].subject_attribute_len)
671 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
672 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
673 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
674
675 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
676 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
677 dq_entry->set_entries_tail,
678 ds_entry);
679
680 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
681 "Checking for cred match\n");
682 /**
683 * Check if this delegation already matches one of our credentials
684 */
685 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
686 cred_pointer = cred_pointer->next)
687 {
688 if(0 != memcmp (&set->subject_key,
689 &cred_pointer->credential->issuer_key,
690 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
691 continue;
692 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
693 "Checking if %s matches %s\n",
694 ds_entry->unresolved_attribute_delegation,
695 cred_pointer->credential->issuer_attribute);
696
697 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
698 cred_pointer->credential->issuer_attribute))
699 continue;
700
701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
702 "Found issuer\n");
703
704 //Backtrack
705 for (tmp_set = ds_entry;
706 NULL != tmp_set->parent_queue_entry;
707 tmp_set = tmp_set->parent_queue_entry->parent_set)
708 {
709 tmp_set->parent_queue_entry->required_solutions--;
710 if (NULL != tmp_set->delegation_chain_entry)
711 {
712 vrh->delegation_chain_size++;
713 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
714 vrh->delegation_chain_tail,
715 tmp_set->delegation_chain_entry);
716 }
717 if (0 < tmp_set->parent_queue_entry->required_solutions)
718 break;
719 }
720
721 if (NULL == tmp_set->parent_queue_entry)
722 {
723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
724 "All solutions found\n");
725 //Found match
726 send_lookup_response (vrh);
727 return;
728 }
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "Not all solutions found yet.\n");
731 continue;
732
733 }
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
735 "Building new lookup request from %s\n",
736 ds_entry->unresolved_attribute_delegation);
737 //Continue with backward resolution
738 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
739 strcpy (issuer_attribute_name,
740 ds_entry->unresolved_attribute_delegation);
741 char *next_attr = strtok (issuer_attribute_name, ".");
742 GNUNET_asprintf (&lookup_attribute,
743 "%s.gnu",
744 next_attr);
745 GNUNET_asprintf (&ds_entry->lookup_attribute,
746 "%s",
747 next_attr);
748 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
749 {
750 ds_entry->attr_trailer = NULL;
751 } else {
752 next_attr += strlen (next_attr) + 1;
753 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
754 }
755
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
757 "Looking up %s\n", ds_entry->lookup_attribute);
758 if (NULL != ds_entry->attr_trailer)
759 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
760 "%s still to go...\n", ds_entry->attr_trailer);
761
762 vrh->pending_lookups++;
763 ds_entry->handle = vrh;
764 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
765 lookup_attribute,
766 ds_entry->issuer_key, //issuer_key,
767 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
768 GNUNET_GNS_LO_DEFAULT,
769 NULL, //shorten_key, always NULL
770 &backward_resolution,
771 ds_entry);
772 GNUNET_free (lookup_attribute);
773 }
774 }
775
776 if(0 == vrh->pending_lookups)
777 {
778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
779 "We are all out of attributes...\n");
780 send_lookup_response (vrh);
781 return;
782
783 }
784}
785
786
787/**
788 * Result from GNS lookup.
789 *
790 * @param cls the closure (our client lookup handle)
791 * @param rd_count the number of records in @a rd
792 * @param rd the record data
793 */
794static void
795handle_credential_query (void* cls,
796 uint32_t rd_count,
797 const struct GNUNET_GNSRECORD_Data *rd)
798{
799 struct VerifyRequestHandle *vrh = cls;
800 struct DelegationSetQueueEntry *ds_entry;
801 struct GNUNET_CREDENTIAL_Credential *crd;
802 struct CredentialRecordEntry *cr_entry;
803 int cred_record_count;
804 int i;
805
806 vrh->lookup_request = NULL;
807 cred_record_count = 0;
808
809 if (0 == rd_count)
810 {
811 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
812 "No credentials found\n");
813 send_lookup_response (vrh);
814 return;
815 }
816
817 for (i=0; i < rd_count; i++)
818 {
819 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
820 continue;
821 cred_record_count++;
822 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
823 rd[i].data_size);
824 if (NULL == crd)
825 {
826 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
827 "Invalid credential found\n");
828 continue;
829 }
830 cr_entry = GNUNET_new (struct CredentialRecordEntry);
831 cr_entry->credential = crd;
832 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
833 vrh->cred_chain_tail,
834 cr_entry);
835 vrh->cred_chain_size++;
836
837 if (0 != memcmp (&crd->issuer_key,
838 &vrh->issuer_key,
839 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
840 continue;
841 if (0 != strcmp (crd->issuer_attribute, vrh->issuer_attribute))
842 continue;
843 //Found match prematurely
844 send_lookup_response (vrh);
845 return;
846
847 }
848
849 /**
850 * Check for attributes from the issuer and follow the chain
851 * till you get the required subject's attributes
852 */
853 char issuer_attribute_name[strlen (vrh->issuer_attribute)];
854 strcpy (issuer_attribute_name,
855 vrh->issuer_attribute);
856 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
857 ".gnu");
858 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
859 "Looking up %s\n", issuer_attribute_name);
860 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
861 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
862 memcpy (ds_entry->issuer_key,
863 &vrh->issuer_key,
864 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
865 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
866 ds_entry->handle = vrh;
867 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
868 vrh->root_set = ds_entry;
869 vrh->pending_lookups = 1;
870 //Start with backward resolution
871 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
872 issuer_attribute_name,
873 &vrh->issuer_key, //issuer_key,
874 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
875 GNUNET_GNS_LO_DEFAULT,
876 NULL, //shorten_key, always NULL
877 &backward_resolution,
878 ds_entry);
879}
880
881
882/**
883 * Handle Credential verification requests from client
884 *
885 * @param cls the closure
886 * @param client the client
887 * @param message the message
888 */
889static void
890handle_verify (void *cls,
891 const struct VerifyMessage *v_msg)
892{
893 char attrs[GNUNET_CREDENTIAL_MAX_LENGTH*2 + 1];
894 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
895 char subject_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1 + 4];
896 struct VerifyRequestHandle *vrh;
897 struct GNUNET_SERVICE_Client *client = cls;
898 char *attrptr = attrs;
899 const char *utf_in;
900
901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
902 "Received VERIFY message\n");
903
904 utf_in = (const char *) &v_msg[1];
905 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
906
907 GNUNET_memcpy (issuer_attribute, attrs, ntohs (v_msg->issuer_attribute_len));
908 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
909 GNUNET_memcpy (subject_attribute, attrs+strlen(issuer_attribute), ntohs (v_msg->subject_attribute_len));
910 strcpy (subject_attribute+ntohs (v_msg->subject_attribute_len),
911 ".gnu");
912 subject_attribute[ntohs (v_msg->subject_attribute_len)+4] = '\0';
913 vrh = GNUNET_new (struct VerifyRequestHandle);
914 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
915 vrh->client = client;
916 vrh->request_id = v_msg->id;
917 vrh->issuer_key = v_msg->issuer_key;
918 vrh->subject_key = v_msg->subject_key;
919 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
920
921 if (NULL == subject_attribute)
922 {
923 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
924 "No subject attribute provided!\n");
925 send_lookup_response (vrh);
926 return;
927 }
928 if (NULL == issuer_attribute)
929 {
930 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
931 "No issuer attribute provided!\n");
932 send_lookup_response (vrh);
933 return;
934 }
935 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
936 "Looking up %s\n",
937 subject_attribute);
938 /**
939 * First, get attribute from subject
940 */
941 vrh->lookup_request = GNUNET_GNS_lookup (gns,
942 subject_attribute,
943 &v_msg->subject_key, //subject_pkey,
944 GNUNET_GNSRECORD_TYPE_CREDENTIAL,
945 GNUNET_GNS_LO_DEFAULT,
946 NULL, //shorten_key, always NULL
947 &handle_credential_query,
948 vrh);
949}
950
951
952/**
953 * One of our clients disconnected, clean up after it.
954 *
955 * @param cls NULL
956 * @param client the client that disconnected
957 */
958static void
959client_disconnect_cb (void *cls,
960 struct GNUNET_SERVICE_Client *client,
961 void *app_ctx)
962{
963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
964 "Client %p disconnected\n",
965 client);
966}
967
968/**
969 * Add a client to our list of active clients.
970 *
971 * @param cls NULL
972 * @param client client to add
973 * @param mq message queue for @a client
974 * @return this client
975 */
976static void *
977client_connect_cb (void *cls,
978 struct GNUNET_SERVICE_Client *client,
979 struct GNUNET_MQ_Handle *mq)
980{
981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
982 "Client %p connected\n",
983 client);
984 return client;
985}
986
987/**
988 * Process Credential requests.
989 *
990 * @param cls closure
991 * @param server the initialized server
992 * @param c configuration to use
993 */
994static void
995run (void *cls,
996 const struct GNUNET_CONFIGURATION_Handle *c,
997 struct GNUNET_SERVICE_Handle *handle)
998{
999
1000 gns = GNUNET_GNS_connect (c);
1001 if (NULL == gns)
1002 {
1003 fprintf (stderr,
1004 _("Failed to connect to GNS\n"));
1005 }
1006
1007 statistics = GNUNET_STATISTICS_create ("credential", c);
1008 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1009}
1010
1011
1012/**
1013 * Define "main" method using service macro
1014 */
1015GNUNET_SERVICE_MAIN
1016("credential",
1017 GNUNET_SERVICE_OPTION_NONE,
1018 &run,
1019 &client_connect_cb,
1020 &client_disconnect_cb,
1021 NULL,
1022 GNUNET_MQ_hd_var_size (verify,
1023 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1024 struct VerifyMessage,
1025 NULL),
1026 GNUNET_MQ_handler_end());
1027
1028/* end of gnunet-service-credential.c */
diff --git a/src/credential/plugin_gnsrecord_credential.c b/src/credential/plugin_gnsrecord_credential.c
new file mode 100644
index 000000000..5c3c03832
--- /dev/null
+++ b/src/credential/plugin_gnsrecord_credential.c
@@ -0,0 +1,342 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013 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/**
22 * @file credential/plugin_gnsrecord_credential.c
23 * @brief gnsrecord plugin to provide the API for CREDENTIAL records
24 * @author Adnan Husain
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_credential_service.h"
31#include "gnunet_gnsrecord_plugin.h"
32#include "gnunet_signatures.h"
33#include "credential_serialization.h"
34#include "credential_misc.h"
35
36/**
37 * Convert the 'value' of a record to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the record
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46credential_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51
52 const char *cdata;
53
54 switch (type)
55 {
56 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
57 {
58 struct GNUNET_CREDENTIAL_DelegationRecord sets;
59 char *attr_str;
60 char *subject_pkey;
61 char *tmp_str;
62 int i;
63 if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
64 return NULL; /* malformed */
65 memcpy (&sets,
66 data,
67 sizeof (sets));
68 cdata = data;
69 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
70 if (GNUNET_OK != GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll (sets.data_size),
71 &cdata[sizeof (sets)],
72 ntohl (sets.set_count),
73 set))
74 return NULL;
75
76 for (i=0;i<ntohl(sets.set_count);i++)
77 {
78 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key);
79 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
80 "%d len attr\n", set[i].subject_attribute_len);
81 if (0 == set[i].subject_attribute_len)
82 {
83 if (0 == i)
84 {
85 GNUNET_asprintf (&attr_str,
86 "%s",
87 subject_pkey);
88 } else {
89 GNUNET_asprintf (&tmp_str,
90 "%s,%s",
91 attr_str,
92 subject_pkey);
93 GNUNET_free (attr_str);
94 attr_str = tmp_str;
95 }
96 } else {
97 if (0 == i)
98 {
99 GNUNET_asprintf (&attr_str,
100 "%s %s",
101 subject_pkey,
102 set[i].subject_attribute);
103 } else {
104 GNUNET_asprintf (&tmp_str,
105 "%s,%s %s",
106 attr_str,
107 subject_pkey,
108 set[i].subject_attribute);
109 GNUNET_free (attr_str);
110 attr_str = tmp_str;
111 }
112 }
113 GNUNET_free (subject_pkey);
114 }
115 return attr_str;
116 }
117 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
118 {
119 struct GNUNET_CREDENTIAL_Credential *cred;
120 char *cred_str;
121
122 cred = GNUNET_CREDENTIAL_credential_deserialize (data,
123 data_size);
124 cred_str = GNUNET_CREDENTIAL_credential_to_string (cred);
125 GNUNET_free (cred);
126 return cred_str;
127 }
128 default:
129 return NULL;
130 }
131}
132
133
134/**
135 * Convert human-readable version of a 'value' of a record to the binary
136 * representation.
137 *
138 * @param cls closure, unused
139 * @param type type of the record
140 * @param s human-readable string
141 * @param data set to value in binary encoding (will be allocated)
142 * @param data_size set to number of bytes in @a data
143 * @return #GNUNET_OK on success
144 */
145static int
146credential_string_to_value (void *cls,
147 uint32_t type,
148 const char *s,
149 void **data,
150 size_t *data_size)
151{
152 if (NULL == s)
153 return GNUNET_SYSERR;
154 switch (type)
155 {
156 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
157 {
158 struct GNUNET_CREDENTIAL_DelegationRecord *sets;
159 char attr_str[253 + 1];
160 char subject_pkey[52 + 1];
161 char *token;
162 char *tmp_str;
163 int matches = 0;
164 int entries;
165 size_t tmp_data_size;
166 int i;
167
168 tmp_str = GNUNET_strdup (s);
169 token = strtok (tmp_str, ",");
170 entries = 0;
171 tmp_data_size = 0;
172 *data_size = sizeof (struct GNUNET_CREDENTIAL_DelegationRecord);
173 while (NULL != token)
174 {
175 matches = SSCANF (token,
176 "%s %s",
177 subject_pkey,
178 attr_str);
179 if (0 == matches)
180 {
181 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
182 _("Unable to parse ATTR record string `%s'\n"),
183 s);
184 GNUNET_free (tmp_str);
185 return GNUNET_SYSERR;
186 }
187 if (1 == matches) {
188 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet);
189 } else if (2 == matches) {
190 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
191 }
192 entries++;
193 token = strtok (NULL, ",");
194 }
195 GNUNET_free (tmp_str);
196 tmp_str = GNUNET_strdup (s);
197 token = strtok (tmp_str, ",");
198 struct GNUNET_CREDENTIAL_DelegationSet set[entries];
199 for (i=0;i<entries;i++)
200 {
201 matches = SSCANF (token,
202 "%s %s",
203 subject_pkey,
204 attr_str);
205 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
206 strlen (subject_pkey),
207 &set[i].subject_key);
208 if (2 == matches) {
209 set[i].subject_attribute_len = strlen (attr_str) + 1;
210 set[i].subject_attribute = GNUNET_strdup (attr_str);
211 }
212 token = strtok (NULL , ",");
213 }
214 tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
215 set);
216
217 if (-1 == tmp_data_size)
218 return GNUNET_SYSERR;
219 *data_size += tmp_data_size;
220 *data = sets = GNUNET_malloc (*data_size);
221 GNUNET_CREDENTIAL_delegation_set_serialize (entries,
222 set,
223 tmp_data_size,
224 (char*)&sets[1]);
225 for (i=0;i<entries;i++)
226 {
227 if (0 != set[i].subject_attribute_len)
228 GNUNET_free ((char*)set[i].subject_attribute);
229 }
230 sets->set_count = htonl (entries);
231 sets->data_size = GNUNET_htonll (tmp_data_size);
232
233 GNUNET_free (tmp_str);
234 return GNUNET_OK;
235 }
236 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
237 {
238 struct GNUNET_CREDENTIAL_Credential *cred;
239 cred = GNUNET_CREDENTIAL_credential_from_string (s);
240
241 *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
242 (char**)data);
243 return GNUNET_OK;
244 }
245 default:
246 return GNUNET_SYSERR;
247 }
248}
249
250
251/**
252 * Mapping of record type numbers to human-readable
253 * record type names.
254 */
255static struct {
256 const char *name;
257 uint32_t number;
258} name_map[] = {
259 { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
260 { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
261 { NULL, UINT32_MAX }
262};
263
264
265/**
266 * Convert a type name (i.e. "AAAA") to the corresponding number.
267 *
268 * @param cls closure, unused
269 * @param gns_typename name to convert
270 * @return corresponding number, UINT32_MAX on error
271 */
272static uint32_t
273credential_typename_to_number (void *cls,
274 const char *gns_typename)
275{
276 unsigned int i;
277
278 i=0;
279 while ( (name_map[i].name != NULL) &&
280 (0 != strcasecmp (gns_typename, name_map[i].name)) )
281 i++;
282 return name_map[i].number;
283}
284
285
286/**
287 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
288 *
289 * @param cls closure, unused
290 * @param type number of a type to convert
291 * @return corresponding typestring, NULL on error
292 */
293static const char *
294credential_number_to_typename (void *cls,
295 uint32_t type)
296{
297 unsigned int i;
298
299 i=0;
300 while ( (name_map[i].name != NULL) &&
301 (type != name_map[i].number) )
302 i++;
303 return name_map[i].name;
304}
305
306
307/**
308 * Entry point for the plugin.
309 *
310 * @param cls NULL
311 * @return the exported block API
312 */
313void *
314libgnunet_plugin_gnsrecord_credential_init (void *cls)
315{
316 struct GNUNET_GNSRECORD_PluginFunctions *api;
317
318 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
319 api->value_to_string = &credential_value_to_string;
320 api->string_to_value = &credential_string_to_value;
321 api->typename_to_number = &credential_typename_to_number;
322 api->number_to_typename = &credential_number_to_typename;
323 return api;
324}
325
326
327/**
328 * Exit point from the plugin.
329 *
330 * @param cls the return value from #libgnunet_plugin_block_test_init
331 * @return NULL
332 */
333void *
334libgnunet_plugin_gnsrecord_credential_done (void *cls)
335{
336 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
337
338 GNUNET_free (api);
339 return NULL;
340}
341
342/* end of plugin_gnsrecord_credential.c */
diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c
new file mode 100644
index 000000000..651de0075
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,821 @@
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_API_NS_CREDENTIAL_ISSUE "/credential/issue"
41
42#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
43
44#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
45
46#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
47
48#define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
49
50#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
51
52#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
53
54#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
55
56#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
57
58/**
59 * @brief struct returned by the initialization function of the plugin
60 */
61struct Plugin
62{
63 const struct GNUNET_CONFIGURATION_Handle *cfg;
64};
65
66const struct GNUNET_CONFIGURATION_Handle *cfg;
67
68struct RequestHandle
69{
70 /**
71 * Handle to Credential service.
72 */
73 struct GNUNET_CREDENTIAL_Handle *credential;
74
75 /**
76 * Handle to lookup request
77 */
78 struct GNUNET_CREDENTIAL_Request *verify_request;
79
80 /**
81 * Handle to issue request
82 */
83 struct GNUNET_CREDENTIAL_Request *issue_request;
84
85 /**
86 * Handle to identity
87 */
88 struct GNUNET_IDENTITY_Handle *identity;
89
90 /**
91 * Handle to identity operation
92 */
93 struct GNUNET_IDENTITY_Operation *id_op;
94
95 /**
96 * Handle to rest request
97 */
98 struct GNUNET_REST_RequestHandle *rest_handle;
99
100 /**
101 * ID of a task associated with the resolution process.
102 */
103 struct GNUNET_SCHEDULER_Task * timeout_task;
104
105 /**
106 * The root of the received JSON or NULL
107 */
108 json_t *json_root;
109
110 /**
111 * The plugin result processor
112 */
113 GNUNET_REST_ResultProcessor proc;
114
115 /**
116 * The closure of the result processor
117 */
118 void *proc_cls;
119
120 /**
121 * The issuer attribute to verify
122 */
123 char *issuer_attr;
124
125 /**
126 * The subject attribute
127 */
128 char *subject_attr;
129
130 /**
131 * The public key of the issuer
132 */
133 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
134
135 /**
136 * The public key of the subject
137 */
138 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
139
140 /**
141 * HTTP response code
142 */
143 int response_code;
144
145 /**
146 * Timeout
147 */
148 struct GNUNET_TIME_Relative timeout;
149
150};
151
152
153/**
154 * Cleanup lookup handle.
155 *
156 * @param handle Handle to clean up
157 */
158static void
159cleanup_handle (struct RequestHandle *handle)
160{
161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
162 "Cleaning up\n");
163 if (NULL != handle->json_root)
164 json_decref (handle->json_root);
165
166 if (NULL != handle->issuer_attr)
167 GNUNET_free (handle->issuer_attr);
168 if (NULL != handle->subject_attr)
169 GNUNET_free (handle->subject_attr);
170 if (NULL != handle->verify_request)
171 GNUNET_CREDENTIAL_verify_cancel (handle->verify_request);
172 if (NULL != handle->credential)
173 GNUNET_CREDENTIAL_disconnect (handle->credential);
174 if (NULL != handle->id_op)
175 GNUNET_IDENTITY_cancel (handle->id_op);
176 if (NULL != handle->identity)
177 GNUNET_IDENTITY_disconnect (handle->identity);
178 if (NULL != handle->timeout_task)
179 {
180 GNUNET_SCHEDULER_cancel (handle->timeout_task);
181 }
182 GNUNET_free (handle);
183}
184
185
186/**
187 * Task run on shutdown. Cleans up everything.
188 *
189 * @param cls unused
190 * @param tc scheduler context
191 */
192static void
193do_error (void *cls)
194{
195 struct RequestHandle *handle = cls;
196 struct MHD_Response *resp;
197
198 resp = GNUNET_REST_create_response (NULL);
199 handle->proc (handle->proc_cls, resp, handle->response_code);
200 cleanup_handle (handle);
201}
202
203/**
204 * Attribute delegation to JSON
205 * @param attr the attribute
206 * @return JSON, NULL if failed
207 */
208static json_t*
209attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
210{
211 char *subject;
212 char *issuer;
213 json_t *attr_obj;
214
215 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
216 if (NULL == issuer)
217 {
218 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
219 "Issuer in delegation malformed\n");
220 return NULL;
221 }
222 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
223 if (NULL == subject)
224 {
225 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
226 "Subject in credential malformed\n");
227 GNUNET_free (issuer);
228 return NULL;
229 }
230 attr_obj = json_object ();
231
232 json_object_set_new (attr_obj, "issuer", json_string (issuer));
233 json_object_set_new (attr_obj, "issuer_attribute",
234 json_string (delegation_chain_entry->issuer_attribute));
235
236 json_object_set_new (attr_obj, "subject", json_string (subject));
237 if (0 < delegation_chain_entry->subject_attribute_len)
238 {
239 json_object_set_new (attr_obj, "subject_attribute",
240 json_string (delegation_chain_entry->subject_attribute));
241 }
242 GNUNET_free (issuer);
243 GNUNET_free (subject);
244 return attr_obj;
245}
246
247/**
248 * Credential to JSON
249 * @param cred the credential
250 * @return the resulting json, NULL if failed
251 */
252static json_t*
253credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
254{
255 char *issuer;
256 char *subject;
257 char attribute[cred->issuer_attribute_len + 1];
258 json_t *cred_obj;
259
260 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
261 if (NULL == issuer)
262 {
263 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
264 "Issuer in credential malformed\n");
265 return NULL;
266 }
267 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
268 if (NULL == subject)
269 {
270 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
271 "Subject in credential malformed\n");
272 GNUNET_free (issuer);
273 return NULL;
274 }
275 memcpy (attribute,
276 cred->issuer_attribute,
277 cred->issuer_attribute_len);
278 attribute[cred->issuer_attribute_len] = '\0';
279 cred_obj = json_object ();
280 json_object_set_new (cred_obj, "issuer", json_string (issuer));
281 json_object_set_new (cred_obj, "subject", json_string (subject));
282 json_object_set_new (cred_obj, "attribute", json_string (attribute));
283 GNUNET_free (issuer);
284 GNUNET_free (subject);
285 return cred_obj;
286}
287
288/**
289 * Function called with the result of a Credential lookup.
290 *
291 * @param cls the 'const char *' name that was resolved
292 * @param cd_count number of records returned
293 * @param cd array of @a cd_count records with the results
294 */
295static void
296handle_verify_response (void *cls,
297 unsigned int d_count,
298 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
299 unsigned int c_count,
300 struct GNUNET_CREDENTIAL_Credential *cred)
301{
302
303 struct RequestHandle *handle = cls;
304 struct MHD_Response *resp;
305 struct GNUNET_JSONAPI_Document *json_document;
306 struct GNUNET_JSONAPI_Resource *json_resource;
307 json_t *cred_obj;
308 json_t *attr_obj;
309 json_t *cred_array;
310 json_t *attr_array;
311 char *result;
312 char *issuer;
313 char *id;
314 uint32_t i;
315
316 handle->verify_request = NULL;
317 if (NULL == cred) {
318 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
319 "Verify failed.\n");
320 handle->response_code = MHD_HTTP_NOT_FOUND;
321 GNUNET_SCHEDULER_add_now (&do_error, handle);
322 return;
323 }
324 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
325 if (NULL == issuer)
326 {
327 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
328 "Issuer in delegation malformed\n");
329 return;
330 }
331 GNUNET_asprintf (&id,
332 "%s.%s",
333 issuer,
334 handle->issuer_attr);
335 GNUNET_free (issuer);
336 json_document = GNUNET_JSONAPI_document_new ();
337 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
338 id);
339 GNUNET_free (id);
340 attr_array = json_array ();
341 for (i = 0; i < d_count; i++)
342 {
343 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
344 json_array_append_new (attr_array, attr_obj);
345 }
346 cred_array = json_array ();
347 for (i=0;i<c_count;i++)
348 {
349 cred_obj = credential_to_json (&cred[i]);
350 json_array_append_new (cred_array, cred_obj);
351 }
352 GNUNET_JSONAPI_resource_add_attr (json_resource,
353 GNUNET_REST_JSONAPI_CREDENTIAL,
354 cred_array);
355 GNUNET_JSONAPI_resource_add_attr (json_resource,
356 GNUNET_REST_JSONAPI_DELEGATIONS,
357 attr_array);
358 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
359 GNUNET_JSONAPI_document_serialize (json_document, &result);
360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
361 "Result %s\n",
362 result);
363 json_decref (attr_array);
364 json_decref (cred_array);
365 GNUNET_JSONAPI_document_delete (json_document);
366 resp = GNUNET_REST_create_response (result);
367 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
368 GNUNET_free (result);
369 cleanup_handle (handle);
370}
371
372
373static void
374verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
375 const char* url,
376 void *cls)
377{
378 struct RequestHandle *handle = cls;
379 struct GNUNET_HashCode key;
380 char *tmp;
381 char *entity_attr;
382
383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384 "Connecting...\n");
385 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
386 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
387 &do_error, handle);
388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
389 "Connected\n");
390 if (NULL == handle->credential)
391 {
392 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
393 "Connecting to CREDENTIAL failed\n");
394 GNUNET_SCHEDULER_add_now (&do_error, handle);
395 return;
396 }
397 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
398 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
399 &key);
400 if ( GNUNET_NO ==
401 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
402 &key) )
403 {
404 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
405 "Missing issuer attribute\n");
406 GNUNET_SCHEDULER_add_now (&do_error, handle);
407 return;
408 }
409 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
410 &key);
411 entity_attr = GNUNET_strdup (tmp);
412 tmp = strtok(entity_attr, ".");
413 if (NULL == tmp)
414 {
415 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
416 "Malformed issuer or attribute\n");
417 GNUNET_free (entity_attr);
418 GNUNET_SCHEDULER_add_now (&do_error, handle);
419 return;
420 }
421 if (GNUNET_OK !=
422 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
423 strlen (tmp),
424 &handle->issuer_key))
425 {
426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
427 "Malformed issuer key\n");
428 GNUNET_free (entity_attr);
429 GNUNET_SCHEDULER_add_now (&do_error, handle);
430 return;
431 }
432 tmp = strtok (NULL, "."); //Issuer attribute
433 if (NULL == tmp)
434 {
435 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
436 "Malformed attribute\n");
437 GNUNET_free (entity_attr);
438 GNUNET_SCHEDULER_add_now (&do_error, handle);
439 return;
440 }
441 handle->issuer_attr = GNUNET_strdup (tmp);
442 GNUNET_free (entity_attr);
443
444 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR,
445 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR),
446 &key);
447 if ( GNUNET_NO ==
448 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
449 &key) )
450 {
451 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
452 "Missing subject or attribute\n");
453 GNUNET_free (entity_attr);
454 GNUNET_SCHEDULER_add_now (&do_error, handle);
455 return;
456 }
457 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
458 &key);
459 entity_attr = GNUNET_strdup (tmp);
460 tmp = strtok(entity_attr, ".");
461 if (NULL == tmp)
462 {
463 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
464 "Malformed subject\n");
465 GNUNET_free (entity_attr);
466 GNUNET_SCHEDULER_add_now (&do_error, handle);
467 return;
468 }
469 if (GNUNET_OK !=
470 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
471 strlen (tmp),
472 &handle->subject_key)) {
473 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
474 "Malformed subject key\n");
475 GNUNET_free (entity_attr);
476 GNUNET_SCHEDULER_add_now (&do_error, handle);
477 return;
478 }
479 tmp = strtok (NULL, ".");
480 if (NULL == tmp)
481 {
482 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
483 "Malformed subject attribute\n");
484 GNUNET_free (entity_attr);
485 GNUNET_SCHEDULER_add_now (&do_error, handle);
486 return;
487 }
488 handle->subject_attr = GNUNET_strdup (tmp);
489 GNUNET_free (entity_attr);
490
491 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
492 &handle->issuer_key,
493 handle->issuer_attr,
494 &handle->subject_key,
495 handle->subject_attr,
496 &handle_verify_response,
497 handle);
498
499}
500
501void
502send_cred_response (struct RequestHandle *handle,
503 struct GNUNET_CREDENTIAL_Credential *cred)
504{
505 struct MHD_Response *resp;
506 struct GNUNET_JSONAPI_Document *json_document;
507 struct GNUNET_JSONAPI_Resource *json_resource;
508 json_t *cred_obj;
509 char *result;
510 char *issuer;
511 char *subject;
512 char *signature;
513 char *id;
514
515 GNUNET_assert (NULL != cred);
516 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
517 if (NULL == issuer)
518 {
519 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
520 "Subject malformed\n");
521 return;
522 }
523 GNUNET_asprintf (&id,
524 "%s.%s",
525 issuer,
526 (char*)&cred[1]);
527 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
528 if (NULL == subject)
529 {
530 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
531 "Subject malformed\n");
532 return;
533 }
534 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
535 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
536 &signature);
537 json_document = GNUNET_JSONAPI_document_new ();
538 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
539 id);
540 GNUNET_free (id);
541 cred_obj = json_object();
542 json_object_set_new (cred_obj, "issuer", json_string (issuer));
543 json_object_set_new (cred_obj, "subject", json_string (subject));
544 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
545 json_object_set_new (cred_obj, "signature", json_string (signature));
546 GNUNET_JSONAPI_resource_add_attr (json_resource,
547 GNUNET_REST_JSONAPI_CREDENTIAL,
548 cred_obj);
549 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
550 GNUNET_JSONAPI_document_serialize (json_document, &result);
551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
552 "Result %s\n",
553 result);
554 json_decref (cred_obj);
555 GNUNET_JSONAPI_document_delete (json_document);
556 resp = GNUNET_REST_create_response (result);
557 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
558 GNUNET_free (result);
559 GNUNET_free (signature);
560 GNUNET_free (issuer);
561 GNUNET_free (subject);
562 cleanup_handle (handle);
563}
564
565void
566get_cred_issuer_cb (void *cls,
567 struct GNUNET_IDENTITY_Ego *ego,
568 void **ctx,
569 const char *name)
570{
571 struct RequestHandle *handle = cls;
572 struct GNUNET_TIME_Absolute etime_abs;
573 struct GNUNET_TIME_Relative etime_rel;
574 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
575 struct GNUNET_HashCode key;
576 struct GNUNET_CREDENTIAL_Credential *cred;
577 char* expiration_str;
578 char* tmp;
579
580 handle->id_op = NULL;
581
582 if (NULL == name)
583 {
584 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
585 "Issuer not configured!\n");
586 GNUNET_SCHEDULER_add_now (&do_error, handle);
587 return;
588 }
589
590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
591 "Connecting to credential service...\n");
592 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
594 "Connected\n");
595 if (NULL == handle->credential)
596 {
597 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
598 "Connecting to CREDENTIAL failed\n");
599 GNUNET_SCHEDULER_add_now (&do_error, handle);
600 return;
601 }
602 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
603 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
604 &key);
605 if ( GNUNET_NO ==
606 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
607 &key) )
608 {
609 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
610 "Missing expiration\n");
611 GNUNET_SCHEDULER_add_now (&do_error, handle);
612 return;
613 }
614 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
615 &key);
616 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
617 &etime_rel))
618 {
619 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
620 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
621 &etime_abs))
622 {
623 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
624 "Malformed expiration: %s\n", expiration_str);
625 GNUNET_SCHEDULER_add_now (&do_error, handle);
626 return;
627 }
628 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
629 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
630 &key);
631 if ( GNUNET_NO ==
632 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
633 &key) )
634 {
635 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
636 "Missing issuer attribute\n");
637 GNUNET_SCHEDULER_add_now (&do_error, handle);
638 return;
639 }
640 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
641 (handle->rest_handle->url_param_map,
642 &key));
643 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
644 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
645 &key);
646 if ( GNUNET_NO ==
647 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
648 &key) )
649 {
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
651 "Missing subject\n");
652 GNUNET_SCHEDULER_add_now (&do_error, handle);
653 return;
654 }
655 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
656 &key);
657 if (NULL == tmp)
658 {
659 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
660 "Malformed subject\n");
661 GNUNET_SCHEDULER_add_now (&do_error, handle);
662 return;
663 }
664 if (GNUNET_OK !=
665 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
666 strlen (tmp),
667 &handle->subject_key)) {
668 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
669 "Malformed subject key\n");
670 GNUNET_SCHEDULER_add_now (&do_error, handle);
671 return;
672 }
673 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
674 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
675 &handle->subject_key,
676 handle->issuer_attr,
677 &etime_abs);
678 if (NULL == cred)
679 {
680 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
681 "Failed to create credential\n");
682 GNUNET_SCHEDULER_add_now (&do_error, handle);
683 return;
684 }
685 send_cred_response (handle, cred);
686}
687
688
689static void
690issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
691 const char* url,
692 void *cls)
693{
694 struct RequestHandle *handle = cls;
695
696 handle->identity = GNUNET_IDENTITY_connect (cfg,
697 NULL,
698 NULL);
699 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
700 "credential-issuer",
701 &get_cred_issuer_cb,
702 handle);
703 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
704 &do_error,
705 handle);
706}
707
708/**
709 * Handle rest request
710 *
711 * @param handle the lookup handle
712 */
713static void
714options_cont (struct GNUNET_REST_RequestHandle *con_handle,
715 const char* url,
716 void *cls)
717{
718 struct MHD_Response *resp;
719 struct RequestHandle *handle = cls;
720
721 //For GNS, independent of path return all options
722 resp = GNUNET_REST_create_response (NULL);
723 MHD_add_response_header (resp,
724 "Access-Control-Allow-Methods",
725 MHD_HTTP_METHOD_GET);
726 handle->proc (handle->proc_cls,
727 resp,
728 MHD_HTTP_OK);
729 cleanup_handle (handle);
730}
731
732
733/**
734 * Function processing the REST call
735 *
736 * @param method HTTP method
737 * @param url URL of the HTTP request
738 * @param data body of the HTTP request (optional)
739 * @param data_size length of the body
740 * @param proc callback function for the result
741 * @param proc_cls closure for callback function
742 * @return GNUNET_OK if request accepted
743 */
744static void
745rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
746 GNUNET_REST_ResultProcessor proc,
747 void *proc_cls)
748{
749 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
750 struct GNUNET_REST_RequestHandlerError err;
751
752 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
753 handle->proc_cls = proc_cls;
754 handle->proc = proc;
755 handle->rest_handle = conndata_handle;
756
757 static const struct GNUNET_REST_RequestHandler handlers[] = {
758 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
759 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
760 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
761 GNUNET_REST_HANDLER_END
762 };
763
764 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
765 handlers,
766 &err,
767 handle))
768 {
769 handle->response_code = err.error_code;
770 GNUNET_SCHEDULER_add_now (&do_error, handle);
771 }
772}
773
774
775/**
776 * Entry point for the plugin.
777 *
778 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
779 * @return NULL on error, otherwise the plugin context
780 */
781void *
782libgnunet_plugin_rest_credential_init (void *cls)
783{
784 static struct Plugin plugin;
785 cfg = cls;
786 struct GNUNET_REST_Plugin *api;
787
788 if (NULL != plugin.cfg)
789 return NULL; /* can only initialize once! */
790 memset (&plugin, 0, sizeof (struct Plugin));
791 plugin.cfg = cfg;
792 api = GNUNET_new (struct GNUNET_REST_Plugin);
793 api->cls = &plugin;
794 api->name = GNUNET_REST_API_NS_CREDENTIAL;
795 api->process_request = &rest_credential_process_request;
796 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
797 _("GNS REST API initialized\n"));
798 return api;
799}
800
801
802/**
803 * Exit point from the plugin.
804 *
805 * @param cls the plugin context (as returned by "init")
806 * @return always NULL
807 */
808void *
809libgnunet_plugin_rest_credential_done (void *cls)
810{
811 struct GNUNET_REST_Plugin *api = cls;
812 struct Plugin *plugin = api->cls;
813
814 plugin->cfg = NULL;
815 GNUNET_free (api);
816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
817 "GNS REST plugin is finished\n");
818 return NULL;
819}
820
821/* end of plugin_rest_gns.c */
diff --git a/src/credential/test_credential_defaults.conf b/src/credential/test_credential_defaults.conf
new file mode 100644
index 000000000..d157ddd43
--- /dev/null
+++ b/src/credential/test_credential_defaults.conf
@@ -0,0 +1,24 @@
1@INLINE@ ../../contrib/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-credential-testing/
5
6[namestore-sqlite]
7FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
8
9[namecache-sqlite]
10FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
11
12[identity]
13# Directory where we store information about our egos
14EGODIR = $GNUNET_TEST_HOME/identity/egos/
15
16[dhtcache]
17DATABASE = heap
18
19[transport]
20PLUGINS = tcp
21
22[transport-tcp]
23BINDTO = 127.0.0.1
24
diff --git a/src/credential/test_credential_issue.sh b/src/credential/test_credential_issue.sh
new file mode 100755
index 000000000..158d91c5b
--- /dev/null
+++ b/src/credential/test_credential_issue.sh
@@ -0,0 +1,44 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C testissuer -c test_credential_lookup.conf
28gnunet-identity -C testsubject -c test_credential_lookup.conf
29SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
30ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
31#TODO1 Get credential and store it with subject (3)
32CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
33STATUS=$?
34
35if test $? != 0
36then
37 echo "Error issuing..."
38 exit 1
39fi
40#Try import
41$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
42RES=$?
43gnunet-arm -e -c test_credential_lookup.conf
44exit $RES
diff --git a/src/credential/test_credential_lookup.conf b/src/credential/test_credential_lookup.conf
new file mode 100644
index 000000000..7aa193abd
--- /dev/null
+++ b/src/credential/test_credential_lookup.conf
@@ -0,0 +1,28 @@
1@INLINE@ test_credential_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-credential-peer-1/
5
6[dht]
7AUTOSTART = YES
8
9[transport]
10PLUGINS =
11
12[credential]
13AUTOSTART = YES
14#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
15
16[rest]
17#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
18
19[gns]
20#PREFIX = valgrind --leak-check=full --track-origins=yes
21AUTOSTART = YES
22AUTO_IMPORT_PKEY = YES
23MAX_PARALLEL_BACKGROUND_QUERIES = 10
24DEFAULT_LOOKUP_TIMEOUT = 15 s
25RECORD_PUT_INTERVAL = 1 h
26ZONE_PUBLISH_TIME_WINDOW = 1 h
27DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
28
diff --git a/src/credential/test_credential_verify.sh b/src/credential/test_credential_verify.sh
new file mode 100755
index 000000000..6d69e337b
--- /dev/null
+++ b/src/credential/test_credential_verify.sh
@@ -0,0 +1,78 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60#TODO2 Add -z swich like in gnunet-gns
61RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
62
63
64#TODO cleanup properly
65gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
66gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
67gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
68gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
69gnunet-arm -e -c test_credential_lookup.conf
70
71if [ "$RES_CRED" != "Failed." ]
72then
73 echo -e "${RES_CRED}"
74 exit 0
75else
76 echo "FAIL: Failed to verify credential $RES_CRED."
77 exit 1
78fi
diff --git a/src/credential/test_credential_verify_and.sh b/src/credential/test_credential_verify_and.sh
new file mode 100755
index 000000000..833d36f95
--- /dev/null
+++ b/src/credential/test_credential_verify_and.sh
@@ -0,0 +1,81 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR,$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
52
53# (5) GNUnet issues Alice the credential "developer"
54CRED1=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
55# (5) GNUnet issues Alice the credential "user"
56CRED2=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
57
58
59# Alice stores the credential under "mygnunetcreds"
60gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED1" -e 5m -c test_credential_lookup.conf
61gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m -c test_credential_lookup.conf
62
63#TODO2 Add -z swich like in gnunet-gns
64RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
65
66
67#TODO cleanup properly
68gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
69gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
70gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
71gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
72gnunet-arm -e -c test_credential_lookup.conf
73
74if [ "$RES_CRED" != "Failed." ]
75then
76 echo -e "${RES_CRED}"
77 exit 0
78else
79 echo "FAIL: Failed to verify credential $RES_CRED."
80 exit 1
81fi
diff --git a/src/credential/test_credential_verify_rest.sh b/src/credential/test_credential_verify_rest.sh
new file mode 100755
index 000000000..092737df7
--- /dev/null
+++ b/src/credential/test_credential_verify_rest.sh
@@ -0,0 +1,84 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60#TODO2 Add -z swich like in gnunet-gns
61RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
62
63gnunet-arm -i rest -c test_credential_lookup.conf
64
65sleep 5
66
67echo "localhost:7776/credential?attribute=$SERVICE_KEY.$USER_ATTR&credential=$ALICE_KEY.$TEST_CREDENTIAL"
68curl -v "localhost:7776/credential?attribute=$SERVICE_KEY.$USER_ATTR&credential=$ALICE_KEY.$TEST_CREDENTIAL"
69
70#TODO cleanup properly
71gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
72gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
73gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
74gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
75gnunet-arm -e -c test_credential_lookup.conf
76
77if [ "$RES_CRED" != "Failed." ]
78then
79 echo -e "${RES_CRED}"
80 exit 0
81else
82 echo "FAIL: Failed to verify credential $RES_CRED."
83 exit 1
84fi
diff --git a/src/credential/test_credential_verify_simple.sh b/src/credential/test_credential_verify_simple.sh
new file mode 100755
index 000000000..c4fd8c7a3
--- /dev/null
+++ b/src/credential/test_credential_verify_simple.sh
@@ -0,0 +1,50 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (3) Isser.user -> Subject
19
20
21which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
22gnunet-arm -s -c test_credential_lookup.conf
23gnunet-identity -C testissuer -c test_credential_lookup.conf
24gnunet-identity -C testsubject -c test_credential_lookup.conf
25
26TEST_ATTR="user"
27SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
28ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
29CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
30
31TEST_CREDENTIAL="t1"
32gnunet-namestore -p -z testsubject -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
33
34#TODO2 Add -z swich like in gnunet-gns
35#RES_CRED=`$DO_TIMEOUT gnunet-credential --verify --issuer=$ISSUER_KEY --attribute="$TEST_ATTR" --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
36RES_CRED=`gnunet-credential --verify --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
37
38#TODO cleanup properly
39gnunet-namestore -z testsubject -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
40gnunet-identity -D testsubject -c test_credential_lookup.conf
41gnunet-arm -e -c test_credential_lookup.conf
42echo $RES_CRED
43#TODO3 proper test
44if [ "$RES_CRED" == "Successful." ]
45then
46 exit 0
47else
48 echo "FAIL: Failed to verify credential."
49 exit 1
50fi