aboutsummaryrefslogtreecommitdiff
path: root/src/credential
diff options
context:
space:
mode:
Diffstat (limited to 'src/credential')
-rw-r--r--src/credential/Makefile.am112
-rw-r--r--src/credential/credential.conf.in5
-rw-r--r--src/credential/credential.h221
-rw-r--r--src/credential/credential_api.c511
-rw-r--r--src/credential/credential_misc.c168
-rw-r--r--src/credential/credential_misc.h35
-rw-r--r--src/credential/credential_serialization.c460
-rw-r--r--src/credential/credential_serialization.h159
-rw-r--r--src/credential/gnunet-credential.c588
-rw-r--r--src/credential/gnunet-service-credential.c1160
-rw-r--r--src/credential/plugin_gnsrecord_credential.c353
-rw-r--r--src/credential/plugin_rest_credential.c1146
-rwxr-xr-xsrc/credential/test_credential_collect.sh47
-rwxr-xr-xsrc/credential/test_credential_collect_rest.sh90
-rw-r--r--src/credential/test_credential_defaults.conf24
-rwxr-xr-xsrc/credential/test_credential_issue.sh44
-rwxr-xr-xsrc/credential/test_credential_issue_rest.sh53
-rw-r--r--src/credential/test_credential_lookup.conf28
-rwxr-xr-xsrc/credential/test_credential_verify.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_and.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_rest.sh87
-rwxr-xr-xsrc/credential/test_credential_verify_simple.sh50
22 files changed, 5503 insertions, 0 deletions
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
new file mode 100644
index 000000000..ca11c5e4f
--- /dev/null
+++ b/src/credential/Makefile.am
@@ -0,0 +1,112 @@
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/namestore/libgnunetnamestore.la \
73 $(top_builddir)/src/statistics/libgnunetstatistics.la \
74 $(GN_LIBINTL)
75
76
77libgnunetcredential_la_SOURCES = \
78 credential_api.c \
79 credential_serialization.c \
80 credential_misc.c
81libgnunetcredential_la_LIBADD = \
82 $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
83libgnunetcredential_la_LDFLAGS = \
84 $(GN_LIB_LDFLAGS)
85
86
87libgnunet_plugin_rest_credential_la_SOURCES = \
88 plugin_rest_credential.c
89libgnunet_plugin_rest_credential_la_LIBADD = \
90 libgnunetcredential.la \
91 $(top_builddir)/src/rest/libgnunetrest.la \
92 $(top_builddir)/src/identity/libgnunetidentity.la \
93 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
94 $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
95 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
96 $(LTLIBINTL) -ljansson -lmicrohttpd
97libgnunet_plugin_rest_credential_la_LDFLAGS = \
98 $(GN_PLUGIN_LDFLAGS)
99
100
101check_SCRIPTS = \
102 test_credential_issue.sh \
103 test_credential_verify_simple.sh \
104 test_credential_verify.sh \
105 test_credential_verify_and.sh
106
107if ENABLE_TEST_RUN
108if HAVE_SQLITE
109 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
110 TESTS = $(check_SCRIPTS)
111endif
112endif
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..66a4636fc
--- /dev/null
+++ b/src/credential/credential.h
@@ -0,0 +1,221 @@
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 Martin Schanzenbach
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 collect credentials.
34 */
35struct CollectMessage
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_EcdsaPrivateKey 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 * Unique identifier for this request (for key collisions).
59 */
60 uint32_t id GNUNET_PACKED;
61
62 /* Followed by the zero-terminated attribute */
63
64};
65
66
67/**
68 * Message from client to Credential service to verify attributes.
69 */
70struct VerifyMessage
71{
72 /**
73 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
74 */
75 struct GNUNET_MessageHeader header;
76
77 /**
78 * Subject public key
79 */
80 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
81
82 /**
83 * Trust anchor
84 */
85 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
86
87 /**
88 * Number of credentials
89 */
90 uint32_t c_count;
91
92 /**
93 * Length of the issuer attribute
94 */
95 uint16_t issuer_attribute_len;
96
97 /**
98 * Unique identifier for this request (for key collisions).
99 */
100 uint32_t id GNUNET_PACKED;
101
102 /* Followed by the zero-terminated attribute and credentials to look up */
103
104};
105
106
107/**
108 * Message from CREDENTIAL service to client: new results.
109 */
110struct DelegationChainResultMessage
111{
112 /**
113 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT
114 */
115 struct GNUNET_MessageHeader header;
116
117 /**
118 * Unique identifier for this request (for key collisions).
119 */
120 uint32_t id GNUNET_PACKED;
121
122 /**
123 * Indicates if credential has been found at all
124 */
125 uint32_t cred_found GNUNET_PACKED;
126
127 /**
128 * The number of delegations in the response
129 */
130 uint32_t d_count GNUNET_PACKED;
131
132 /**
133 * The number of credentials in the response
134 */
135 uint32_t c_count GNUNET_PACKED;
136
137 /* followed by ad_count GNUNET_CREDENTIAL_RecordData structs*/
138
139};
140
141struct DelegationRecordData
142{
143 /**
144 * Subject key
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
147
148 /**
149 * Subject attributes
150 */
151 uint32_t subject_attribute_len GNUNET_PACKED;
152};
153
154
155struct ChainEntry
156{
157 /**
158 * Issuer key
159 */
160 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
161
162 /**
163 * Subject key
164 */
165 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
166
167 /**
168 * Issuer attributes
169 */
170 uint32_t issuer_attribute_len GNUNET_PACKED;
171
172 /**
173 * Subject attributes
174 */
175 uint32_t subject_attribute_len GNUNET_PACKED;
176};
177
178
179struct CredentialEntry
180{
181
182 /**
183 * The signature for this credential by the issuer
184 */
185 struct GNUNET_CRYPTO_EcdsaSignature signature;
186
187 /**
188 * Signature meta
189 */
190 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
191
192 /**
193 * Public key of the issuer
194 */
195 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
196
197 /**
198 * Public key of the subject this credential was issued to
199 */
200 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
201
202 /**
203 * Expiration time of this credential
204 */
205 uint64_t expiration GNUNET_PACKED;
206
207 /**
208 * Issuer attribute length
209 */
210 uint32_t issuer_attribute_len;
211
212 /**
213 * Followed by the attribute string
214 */
215};
216
217
218GNUNET_NETWORK_STRUCT_END
219
220#endif
221
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
new file mode 100644
index 000000000..677cb9ad4
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,511 @@
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 Martin Schanzenbach
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_CredentialResultProcessor 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 *request_head;
104
105 /**
106 * Tail of linked list of active verify requests.
107 */
108 struct GNUNET_CREDENTIAL_Request *request_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 * Check validity of message received from the CREDENTIAL service
190 *
191 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
192 * @param vr_msg the incoming message
193 */
194static int
195check_result (void *cls,
196 const struct DelegationChainResultMessage *vr_msg)
197{
198 //TODO
199 return GNUNET_OK;
200}
201
202
203/**
204 * Handler for messages received from the CREDENTIAL service
205 *
206 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
207 * @param vr_msg the incoming message
208 */
209static void
210handle_result (void *cls,
211 const struct DelegationChainResultMessage *vr_msg)
212{
213 struct GNUNET_CREDENTIAL_Handle *handle = cls;
214 uint32_t r_id = ntohl (vr_msg->id);
215 struct GNUNET_CREDENTIAL_Request *vr;
216 size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg);
217 uint32_t d_count = ntohl (vr_msg->d_count);
218 uint32_t c_count = ntohl (vr_msg->c_count);
219 struct GNUNET_CREDENTIAL_Delegation d_chain[d_count];
220 struct GNUNET_CREDENTIAL_Credential creds[c_count];
221 GNUNET_CREDENTIAL_CredentialResultProcessor proc;
222 void *proc_cls;
223
224 LOG (GNUNET_ERROR_TYPE_DEBUG,
225 "Received verify reply from CREDENTIAL service\n");
226 for (vr = handle->request_head; NULL != vr; vr = vr->next)
227 if (vr->r_id == r_id)
228 break;
229 if (NULL == vr)
230 return;
231 proc = vr->verify_proc;
232 proc_cls = vr->proc_cls;
233 GNUNET_CONTAINER_DLL_remove (handle->request_head,
234 handle->request_tail,
235 vr);
236 GNUNET_MQ_discard (vr->env);
237 GNUNET_free (vr);
238 GNUNET_assert (GNUNET_OK ==
239 GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen,
240 (const char*) &vr_msg[1],
241 d_count,
242 d_chain,
243 c_count,
244 creds));
245 if (GNUNET_NO == ntohl (vr_msg->cred_found))
246 {
247 proc (proc_cls,
248 0,
249 NULL,
250 0,
251 NULL); // TODO
252 } else {
253 proc (proc_cls,
254 d_count,
255 d_chain,
256 c_count,
257 creds);
258 }
259}
260
261
262/**
263 * Reconnect to CREDENTIAL service.
264 *
265 * @param handle the handle to the CREDENTIAL service
266 */
267static void
268reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
269{
270 struct GNUNET_MQ_MessageHandler handlers[] = {
271 GNUNET_MQ_hd_var_size (result,
272 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
273 struct DelegationChainResultMessage,
274 handle),
275 GNUNET_MQ_hd_var_size (result,
276 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT,
277 struct DelegationChainResultMessage,
278 handle),
279 GNUNET_MQ_handler_end ()
280 };
281 struct GNUNET_CREDENTIAL_Request *vr;
282
283 GNUNET_assert (NULL == handle->mq);
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Trying to connect to CREDENTIAL\n");
286 handle->mq = GNUNET_CLIENT_connect (handle->cfg,
287 "credential",
288 handlers,
289 &mq_error_handler,
290 handle);
291 if (NULL == handle->mq)
292 return;
293 for (vr = handle->request_head; NULL != vr; vr = vr->next)
294 GNUNET_MQ_send_copy (handle->mq,
295 vr->env);
296}
297
298
299/**
300 * Initialize the connection with the CREDENTIAL service.
301 *
302 * @param cfg configuration to use
303 * @return handle to the CREDENTIAL service, or NULL on error
304 */
305struct GNUNET_CREDENTIAL_Handle *
306GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
307{
308 struct GNUNET_CREDENTIAL_Handle *handle;
309
310 handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
311 handle->cfg = cfg;
312 reconnect (handle);
313 if (NULL == handle->mq)
314 {
315 GNUNET_free (handle);
316 return NULL;
317 }
318 return handle;
319}
320
321
322/**
323 * Shutdown connection with the CREDENTIAL service.
324 *
325 * @param handle handle of the CREDENTIAL connection to stop
326 */
327void
328GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle)
329{
330 if (NULL != handle->mq)
331 {
332 GNUNET_MQ_destroy (handle->mq);
333 handle->mq = NULL;
334 }
335 if (NULL != handle->reconnect_task)
336 {
337 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
338 handle->reconnect_task = NULL;
339 }
340 GNUNET_assert (NULL == handle->request_head);
341 GNUNET_free (handle);
342}
343
344
345/**
346 * Cancel pending verify request
347 *
348 * @param lr the verify request to cancel
349 */
350void
351GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *lr)
352{
353 struct GNUNET_CREDENTIAL_Handle *handle = lr->credential_handle;
354
355 GNUNET_CONTAINER_DLL_remove (handle->request_head,
356 handle->request_tail,
357 lr);
358 GNUNET_MQ_discard (lr->env);
359 GNUNET_free (lr);
360}
361
362
363/**
364 * Performs attribute collection.
365 * Collects all credentials of subject to fulfill the
366 * attribute, if possible
367 *
368 * @param handle handle to the Credential service
369 * @param issuer_key the issuer public key
370 * @param issuer_attribute the issuer attribute
371 * @param subject_key the subject public key
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_collect (struct GNUNET_CREDENTIAL_Handle *handle,
378 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
379 const char *issuer_attribute,
380 const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
381 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
382 void *proc_cls)
383{
384 /* IPC to shorten credential names, return shorten_handle */
385 struct CollectMessage *c_msg;
386 struct GNUNET_CREDENTIAL_Request *vr;
387 size_t nlen;
388
389 if (NULL == issuer_attribute)
390 {
391 GNUNET_break (0);
392 return NULL;
393 }
394
395 //DEBUG LOG
396 LOG (GNUNET_ERROR_TYPE_DEBUG,
397 "Trying to collect `%s' in CREDENTIAL\n",
398 issuer_attribute);
399 nlen = strlen (issuer_attribute) + 1;
400 if (nlen >= GNUNET_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 (c_msg,
411 nlen,
412 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT);
413 c_msg->id = htonl (vr->r_id);
414 c_msg->subject_key = *subject_key;
415 c_msg->issuer_key = *issuer_key;
416 c_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
417 GNUNET_memcpy (&c_msg[1],
418 issuer_attribute,
419 strlen (issuer_attribute));
420 GNUNET_CONTAINER_DLL_insert (handle->request_head,
421 handle->request_tail,
422 vr);
423 if (NULL != handle->mq)
424 GNUNET_MQ_send_copy (handle->mq,
425 vr->env);
426 return vr;
427}
428/**
429 * Performs attribute verification.
430 * Checks if there is a delegation chain from
431 * attribute ``issuer_attribute'' issued by the issuer
432 * with public key ``issuer_key'' maps to the attribute
433 * ``subject_attribute'' claimed by the subject with key
434 * ``subject_key''
435 *
436 * @param handle handle to the Credential service
437 * @param issuer_key the issuer public key
438 * @param issuer_attribute the issuer attribute
439 * @param subject_key the subject public key
440 * @param credential_count number of credentials provided
441 * @param credentials subject credentials
442 * @param proc function to call on result
443 * @param proc_cls closure for processor
444 * @return handle to the queued request
445 */
446struct GNUNET_CREDENTIAL_Request*
447GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
448 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
449 const char *issuer_attribute,
450 const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
451 uint32_t credential_count,
452 const struct GNUNET_CREDENTIAL_Credential *credentials,
453 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
454 void *proc_cls)
455{
456 /* IPC to shorten credential names, return shorten_handle */
457 struct VerifyMessage *v_msg;
458 struct GNUNET_CREDENTIAL_Request *vr;
459 size_t nlen;
460 size_t clen;
461
462 if (NULL == issuer_attribute || NULL == credentials)
463 {
464 GNUNET_break (0);
465 return NULL;
466 }
467
468 clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
469 credentials);
470
471 //DEBUG LOG
472 LOG (GNUNET_ERROR_TYPE_DEBUG,
473 "Trying to verify `%s' in CREDENTIAL\n",
474 issuer_attribute);
475 nlen = strlen (issuer_attribute) + 1 + clen;
476 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
477 {
478 GNUNET_break (0);
479 return NULL;
480 }
481 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
482 vr->credential_handle = handle;
483 vr->verify_proc = proc;
484 vr->proc_cls = proc_cls;
485 vr->r_id = handle->r_id_gen++;
486 vr->env = GNUNET_MQ_msg_extra (v_msg,
487 nlen,
488 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
489 v_msg->id = htonl (vr->r_id);
490 v_msg->subject_key = *subject_key;
491 v_msg->c_count = htonl(credential_count);
492 v_msg->issuer_key = *issuer_key;
493 v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
494 GNUNET_memcpy (&v_msg[1],
495 issuer_attribute,
496 strlen (issuer_attribute));
497 GNUNET_CREDENTIAL_credentials_serialize (credential_count,
498 credentials,
499 clen,
500 ((char*)&v_msg[1])
501 + strlen (issuer_attribute) + 1);
502 GNUNET_CONTAINER_DLL_insert (handle->request_head,
503 handle->request_tail,
504 vr);
505 if (NULL != handle->mq)
506 GNUNET_MQ_send_copy (handle->mq,
507 vr->env);
508 return vr;
509}
510
511/* 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..c94c33919
--- /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_misc.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_len = strlen ((char*)&cred[1]);
109 cred->issuer_attribute = (char*)&cred[1];
110 return cred;
111}
112
113/**
114 * Issue an attribute to a subject
115 *
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..1d23bb08c
--- /dev/null
+++ b/src/credential/credential_serialization.c
@@ -0,0 +1,460 @@
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
38 *
39 * @param ds_count number of delegation chain entries
40 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
41 * @return the required size to serialize
42 */
43size_t
44GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
45 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
46{
47 unsigned int i;
48 size_t ret;
49
50 ret = sizeof (struct DelegationRecordData) * (ds_count);
51
52 for (i=0; i<ds_count;i++)
53 {
54 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
55 ret += dsr[i].subject_attribute_len;
56 }
57 return ret;
58}
59
60/**
61 * Serizalize the given delegation chain entries and credential
62 *
63 * @param d_count number of delegation chain entries
64 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
65 * @param dest_size size of the destination
66 * @param dest where to store the result
67 * @return the size of the data, -1 on failure
68 */
69ssize_t
70GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
71 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
72 size_t dest_size,
73 char *dest)
74{
75 struct DelegationRecordData rec;
76 unsigned int i;
77 size_t off;
78
79 off = 0;
80 for (i=0;i<d_count;i++)
81 {
82 rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
83 rec.subject_key = dsr[i].subject_key;
84 if (off + sizeof (rec) > dest_size)
85 return -1;
86 GNUNET_memcpy (&dest[off],
87 &rec,
88 sizeof (rec));
89 off += sizeof (rec);
90 if (0 == dsr[i].subject_attribute_len)
91 continue;
92 if (off + dsr[i].subject_attribute_len > dest_size)
93 return -1;
94 GNUNET_memcpy (&dest[off],
95 dsr[i].subject_attribute,
96 dsr[i].subject_attribute_len);
97 off += dsr[i].subject_attribute_len;
98 }
99 return off;
100}
101
102
103/**
104 * Deserialize the given destination
105 *
106 * @param len size of the serialized delegation chain and cred
107 * @param src the serialized data
108 * @param d_count the number of delegation chain entries
109 * @param dsr where to put the delegation chain entries
110 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
111 */
112int
113GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
114 const char *src,
115 unsigned int d_count,
116 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
117{
118 struct DelegationRecordData rec;
119 unsigned int i;
120 size_t off;
121
122 off = 0;
123 for (i=0;i<d_count;i++)
124 {
125 if (off + sizeof (rec) > len)
126 return GNUNET_SYSERR;
127 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
128 dsr[i].subject_key = rec.subject_key;
129 off += sizeof (rec);
130 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
131 if (off + dsr[i].subject_attribute_len > len)
132 return GNUNET_SYSERR;
133 dsr[i].subject_attribute = (char*)&src[off];
134 off += dsr[i].subject_attribute_len;
135 }
136 return GNUNET_OK;
137}
138
139
140/**
141 * Calculate how many bytes we will need to serialize
142 * the credentials
143 *
144 * @param c_count number of credential entries
145 * @param cd a #GNUNET_CREDENTIAL_Credential
146 * @return the required size to serialize
147 */
148size_t
149GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
150 const struct GNUNET_CREDENTIAL_Credential *cd)
151{
152 unsigned int i;
153 size_t ret;
154
155 ret = sizeof (struct CredentialEntry) * (c_count);
156
157 for (i=0; i<c_count;i++)
158 {
159 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
160 ret += cd[i].issuer_attribute_len;
161 }
162 return ret;
163}
164/**
165 * Serizalize the given credentials
166 *
167 * @param c_count number of credential entries
168 * @param cd a #GNUNET_CREDENTIAL_Credential
169 * @param dest_size size of the destination
170 * @param dest where to store the result
171 * @return the size of the data, -1 on failure
172 */
173ssize_t
174GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
175 const struct GNUNET_CREDENTIAL_Credential *cd,
176 size_t dest_size,
177 char *dest)
178{
179 struct CredentialEntry c_rec;
180 unsigned int i;
181 size_t off;
182
183 off = 0;
184 for (i=0;i<c_count;i++)
185 {
186 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
187 c_rec.issuer_key = cd[i].issuer_key;
188 c_rec.subject_key = cd[i].subject_key;
189 c_rec.signature = cd[i].signature;
190 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
191 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
192 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
193 if (off + sizeof (c_rec) > dest_size)
194 return -1;
195 GNUNET_memcpy (&dest[off],
196 &c_rec,
197 sizeof (c_rec));
198 off += sizeof (c_rec);
199 if (off + cd[i].issuer_attribute_len > dest_size)
200 return -1;
201 GNUNET_memcpy (&dest[off],
202 cd[i].issuer_attribute,
203 cd[i].issuer_attribute_len);
204 off += cd[i].issuer_attribute_len;
205 }
206
207 return off;
208}
209
210
211
212/**
213 * Deserialize the given destination
214 *
215 * @param len size of the serialized creds
216 * @param src the serialized data
217 * @param c_count the number of credential entries
218 * @param cd where to put the credential data
219 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
220 */
221int
222GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
223 const char *src,
224 unsigned int c_count,
225 struct GNUNET_CREDENTIAL_Credential *cd)
226{
227 struct CredentialEntry c_rec;
228 unsigned int i;
229 size_t off;
230
231 off = 0;
232 for (i=0;i<c_count;i++)
233 {
234 if (off + sizeof (c_rec) > len)
235 return GNUNET_SYSERR;
236 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
237 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
238 cd[i].issuer_key = c_rec.issuer_key;
239 cd[i].subject_key = c_rec.subject_key;
240 cd[i].signature = c_rec.signature;
241 cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
242 off += sizeof (c_rec);
243 if (off + cd[i].issuer_attribute_len > len)
244 return GNUNET_SYSERR;
245 cd[i].issuer_attribute = &src[off];
246 off += cd[i].issuer_attribute_len;
247 }
248 return GNUNET_OK;
249}
250
251
252
253/**
254 * Calculate how many bytes we will need to serialize
255 * the given delegation chain and credential
256 *
257 * @param d_count number of delegation chain entries
258 * @param dd array of #GNUNET_CREDENTIAL_Delegation
259 * @param c_count number of credential entries
260 * @param cd a #GNUNET_CREDENTIAL_Credential
261 * @return the required size to serialize
262 */
263size_t
264GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
265 const struct GNUNET_CREDENTIAL_Delegation *dd,
266 unsigned int c_count,
267 const struct GNUNET_CREDENTIAL_Credential *cd)
268{
269 unsigned int i;
270 size_t ret;
271
272 ret = sizeof (struct ChainEntry) * (d_count);
273
274 for (i=0; i<d_count;i++)
275 {
276 GNUNET_assert ((ret +
277 dd[i].issuer_attribute_len +
278 dd[i].subject_attribute_len) >= ret);
279 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
280 }
281 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
282 return ret;
283}
284
285/**
286 * Serizalize the given delegation chain entries and credential
287 *
288 * @param d_count number of delegation chain entries
289 * @param dd array of #GNUNET_CREDENTIAL_Delegation
290 * @param c_count number of credential entries
291 * @param cd a #GNUNET_CREDENTIAL_Credential
292 * @param dest_size size of the destination
293 * @param dest where to store the result
294 * @return the size of the data, -1 on failure
295 */
296ssize_t
297GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
298 const struct GNUNET_CREDENTIAL_Delegation *dd,
299 unsigned int c_count,
300 const struct GNUNET_CREDENTIAL_Credential *cd,
301 size_t dest_size,
302 char *dest)
303{
304 struct ChainEntry rec;
305 unsigned int i;
306 size_t off;
307
308 off = 0;
309 for (i=0;i<d_count;i++)
310 {
311 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
312 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
313 rec.issuer_key = dd[i].issuer_key;
314 rec.subject_key = dd[i].subject_key;
315 if (off + sizeof (rec) > dest_size)
316 return -1;
317 GNUNET_memcpy (&dest[off],
318 &rec,
319 sizeof (rec));
320 off += sizeof (rec);
321 if (off + dd[i].issuer_attribute_len > dest_size)
322 return -1;
323 GNUNET_memcpy (&dest[off],
324 dd[i].issuer_attribute,
325 dd[i].issuer_attribute_len);
326 off += dd[i].issuer_attribute_len;
327 if (0 == dd[i].subject_attribute_len)
328 continue;
329 if (off + dd[i].subject_attribute_len > dest_size)
330 return -1;
331 GNUNET_memcpy (&dest[off],
332 dd[i].subject_attribute,
333 dd[i].subject_attribute_len);
334 off += dd[i].subject_attribute_len;
335 }
336 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
337 cd,
338 dest_size-off,
339 &dest[off]);
340}
341
342
343/**
344 * Deserialize the given destination
345 *
346 * @param len size of the serialized delegation chain and cred
347 * @param src the serialized data
348 * @param d_count the number of delegation chain entries
349 * @param dd where to put the delegation chain entries
350 * @param c_count the number of credential entries
351 * @param cd where to put the credential data
352 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
353 */
354int
355GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
356 const char *src,
357 unsigned int d_count,
358 struct GNUNET_CREDENTIAL_Delegation *dd,
359 unsigned int c_count,
360 struct GNUNET_CREDENTIAL_Credential *cd)
361{
362 struct ChainEntry rec;
363 unsigned int i;
364 size_t off;
365
366 off = 0;
367 for (i=0;i<d_count;i++)
368 {
369 if (off + sizeof (rec) > len)
370 return GNUNET_SYSERR;
371 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
372 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
373 dd[i].issuer_key = rec.issuer_key;
374 dd[i].subject_key = rec.subject_key;
375 off += sizeof (rec);
376 if (off + dd[i].issuer_attribute_len > len)
377 return GNUNET_SYSERR;
378 dd[i].issuer_attribute = &src[off];
379 off += dd[i].issuer_attribute_len;
380 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
381 if (off + dd[i].subject_attribute_len > len)
382 return GNUNET_SYSERR;
383 dd[i].subject_attribute = &src[off];
384 off += dd[i].subject_attribute_len;
385 }
386 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
387 &src[off],
388 c_count,
389 cd);
390}
391int
392GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
393 char **data)
394{
395 size_t size;
396 struct CredentialEntry *cdata;
397
398 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
399 *data = GNUNET_malloc (size);
400 cdata = (struct CredentialEntry*)*data;
401 cdata->subject_key = cred->subject_key;
402 cdata->issuer_key = cred->issuer_key;
403 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
404 cdata->signature = cred->signature;
405 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
406 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
407 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
408 GNUNET_memcpy (&cdata[1],
409 cred->issuer_attribute,
410 strlen (cred->issuer_attribute));
411
412 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
413 &cdata->purpose,
414 &cdata->signature,
415 &cdata->issuer_key))
416 {
417 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
418 "Invalid credential\n");
419 //return NULL;
420 }
421 return size;
422}
423
424struct GNUNET_CREDENTIAL_Credential*
425GNUNET_CREDENTIAL_credential_deserialize (const char* data,
426 size_t data_size)
427{
428 struct GNUNET_CREDENTIAL_Credential *cred;
429 struct CredentialEntry *cdata;
430 char *issuer_attribute;
431
432 if (data_size < sizeof (struct CredentialEntry))
433 return NULL;
434 cdata = (struct CredentialEntry*)data;
435 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
436 &cdata->purpose,
437 &cdata->signature,
438 &cdata->issuer_key))
439 {
440 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
441 "Invalid credential\n");
442 //return NULL;
443 }
444 issuer_attribute = (char*)&cdata[1];
445
446 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
447
448 cred->issuer_key = cdata->issuer_key;
449 cred->subject_key = cdata->subject_key;
450 GNUNET_memcpy (&cred[1],
451 issuer_attribute,
452 ntohl (cdata->issuer_attribute_len));
453 cred->signature = cdata->signature;
454 cred->issuer_attribute = (char*)&cred[1];
455 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
456 return cred;
457}
458
459
460/* 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..b870d47dc
--- /dev/null
+++ b/src/credential/credential_serialization.h
@@ -0,0 +1,159 @@
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 size_t
134 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
135 const struct GNUNET_CREDENTIAL_Credential *cd);
136
137ssize_t
138GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
139 const struct GNUNET_CREDENTIAL_Credential *cd,
140 size_t dest_size,
141 char *dest);
142
143
144int
145GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
146 const char *src,
147 unsigned int c_count,
148 struct GNUNET_CREDENTIAL_Credential *cd);
149
150
151int
152GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
153 char **data);
154
155struct GNUNET_CREDENTIAL_Credential*
156GNUNET_CREDENTIAL_credential_deserialize (const char* data,
157 size_t data_size);
158#endif
159/* 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..03f959b95
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,588 @@
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 Martin Schanzenbach
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 * Handle to collect request
59 */
60static struct GNUNET_CREDENTIAL_Request *collect_request;
61
62/**
63 * Task scheduled to handle timeout.
64 */
65static struct GNUNET_SCHEDULER_Task *tt;
66
67/**
68 * Subject pubkey string
69 */
70static char *subject_key;
71
72/**
73 * Subject credential string
74 */
75static char *subject_credential;
76
77/**
78 * Credential TTL
79 */
80static char *expiration;
81
82/**
83 * Subject key
84 */
85struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
86
87/**
88 * Issuer key
89 */
90struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
91
92
93/**
94 * Issuer pubkey string
95 */
96static char *issuer_key;
97
98/**
99 * ego
100 */
101static char *ego_name;
102
103/**
104 * Issuer attribute
105 */
106static char *issuer_attr;
107
108/**
109 * Verify mode
110 */
111static int verify;
112
113/**
114 * Issue mode
115 */
116static int create_cred;
117
118/**
119 * Collect mode
120 */
121static int collect;
122
123/**
124 * Task run on shutdown. Cleans up everything.
125 *
126 * @param cls unused
127 */
128static void
129do_shutdown (void *cls)
130{
131 if (NULL != verify_request)
132 {
133 GNUNET_CREDENTIAL_request_cancel (verify_request);
134 verify_request = NULL;
135 }
136 if (NULL != credential)
137 {
138 GNUNET_CREDENTIAL_disconnect (credential);
139 credential = NULL;
140 }
141 if (NULL != tt)
142 {
143 GNUNET_SCHEDULER_cancel (tt);
144 tt = NULL;
145 }
146}
147
148
149/**
150 * Task run on timeout. Triggers shutdown.
151 *
152 * @param cls unused
153 */
154static void
155do_timeout (void *cls)
156{
157 tt = NULL;
158 GNUNET_SCHEDULER_shutdown ();
159}
160
161static void
162handle_collect_result (void *cls,
163 unsigned int d_count,
164 struct GNUNET_CREDENTIAL_Delegation *dc,
165 unsigned int c_count,
166 struct GNUNET_CREDENTIAL_Credential *cred)
167{
168 int i;
169 char* line;
170
171 verify_request = NULL;
172 if (NULL != cred)
173 {
174 for (i=0;i<c_count;i++)
175 {
176 line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
177 printf ("%s\n",
178 line);
179 GNUNET_free (line);
180 }
181 }
182
183
184 GNUNET_SCHEDULER_shutdown ();
185}
186
187
188static void
189handle_verify_result (void *cls,
190 unsigned int d_count,
191 struct GNUNET_CREDENTIAL_Delegation *dc,
192 unsigned int c_count,
193 struct GNUNET_CREDENTIAL_Credential *cred)
194{
195 int i;
196 char* iss_key;
197 char* sub_key;
198
199 verify_request = NULL;
200 if (NULL == cred)
201 printf ("Failed.\n");
202 else
203 {
204 printf("Delegation Chain:\n");
205 for (i=0;i<d_count;i++)
206 {
207 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
208 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
209 if (0 != dc[i].subject_attribute_len)
210 {
211 printf ("(%d) %s.%s <- %s.%s\n", i,
212 iss_key, dc[i].issuer_attribute,
213 sub_key, dc[i].subject_attribute);
214 } else {
215 printf ("(%d) %s.%s <- %s\n", i,
216 iss_key, dc[i].issuer_attribute,
217 sub_key);
218 }
219 GNUNET_free (iss_key);
220 GNUNET_free (sub_key);
221 }
222 printf("\nCredentials:\n");
223 for (i=0;i<c_count;i++)
224 {
225 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
226 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
227 printf ("%s.%s <- %s\n",
228 iss_key, cred[i].issuer_attribute,
229 sub_key);
230 GNUNET_free (iss_key);
231 GNUNET_free (sub_key);
232
233 }
234 printf ("Successful.\n");
235 }
236
237
238 GNUNET_SCHEDULER_shutdown ();
239}
240
241/**
242 * Callback invoked from identity service with ego information.
243 * An @a ego of NULL means the ego was not found.
244 *
245 * @param cls closure with the configuration
246 * @param ego an ego known to identity service, or NULL
247 */
248static void
249identity_cb (void *cls,
250 const struct GNUNET_IDENTITY_Ego *ego)
251{
252 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
253 struct GNUNET_CREDENTIAL_Credential *crd;
254 struct GNUNET_TIME_Absolute etime_abs;
255 struct GNUNET_TIME_Relative etime_rel;
256 char *res;
257
258 el = NULL;
259 if (NULL == ego)
260 {
261 if (NULL != ego_name)
262 {
263 fprintf (stderr,
264 _("Ego `%s' not known to identity service\n"),
265 ego_name);
266 }
267 GNUNET_SCHEDULER_shutdown ();
268 return;
269 }
270
271 if (GNUNET_YES == collect)
272 {
273
274 if (GNUNET_OK !=
275 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
276 strlen (issuer_key),
277 &issuer_pkey))
278 {
279 fprintf (stderr,
280 _("Issuer public key `%s' is not well-formed\n"),
281 issuer_key);
282 GNUNET_SCHEDULER_shutdown ();
283 }
284 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
285
286 collect_request = GNUNET_CREDENTIAL_collect(credential,
287 &issuer_pkey,
288 issuer_attr, //TODO argument
289 privkey,
290 &handle_collect_result,
291 NULL);
292 return;
293 }
294
295 //Else issue
296
297 if (NULL == expiration)
298 {
299 fprintf (stderr,
300 "Please specify a TTL\n");
301 GNUNET_SCHEDULER_shutdown ();
302 return;
303 } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
304 &etime_rel))
305 {
306 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
307 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
308 &etime_abs))
309 {
310 fprintf (stderr,
311 "%s is not a valid ttl!\n",
312 expiration);
313 GNUNET_SCHEDULER_shutdown ();
314 return;
315 }
316
317
318 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
319 GNUNET_free_non_null (ego_name);
320 ego_name = NULL;
321 crd = GNUNET_CREDENTIAL_credential_issue (privkey,
322 &subject_pkey,
323 issuer_attr,
324 &etime_abs);
325
326 res = GNUNET_CREDENTIAL_credential_to_string (crd);
327 GNUNET_free (crd);
328 printf ("%s\n", res);
329 GNUNET_SCHEDULER_shutdown ();
330}
331
332
333
334
335/**
336 * Main function that will be run.
337 *
338 * @param cls closure
339 * @param args remaining command-line arguments
340 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
341 * @param c configuration
342 */
343static void
344run (void *cls,
345 char *const *args,
346 const char *cfgfile,
347 const struct GNUNET_CONFIGURATION_Handle *c)
348{
349
350 cfg = c;
351
352
353 tt = GNUNET_SCHEDULER_add_delayed (timeout,
354 &do_timeout, NULL);
355 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
356
357 if (GNUNET_YES == collect) {
358 if (NULL == issuer_key)
359 {
360 fprintf (stderr,
361 _("Issuer public key not well-formed\n"));
362 GNUNET_SCHEDULER_shutdown ();
363 return;
364
365 }
366
367 credential = GNUNET_CREDENTIAL_connect (cfg);
368
369 if (NULL == credential)
370 {
371 fprintf (stderr,
372 _("Failed to connect to CREDENTIAL\n"));
373 GNUNET_SCHEDULER_shutdown ();
374 }
375 if (NULL == issuer_attr)
376 {
377 fprintf (stderr,
378 _("You must provide issuer the attribute\n"));
379 GNUNET_SCHEDULER_shutdown ();
380 }
381
382 if (NULL == ego_name)
383 {
384 fprintf (stderr,
385 _("ego required\n"));
386 GNUNET_SCHEDULER_shutdown ();
387 return;
388
389 }
390 el = GNUNET_IDENTITY_ego_lookup (cfg,
391 ego_name,
392 &identity_cb,
393 (void *) cfg);
394 return;
395
396 }
397
398 if (NULL == subject_key)
399 {
400 fprintf (stderr,
401 _("Subject public key needed\n"));
402 GNUNET_SCHEDULER_shutdown ();
403 return;
404
405 }
406 if (GNUNET_OK !=
407 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
408 strlen (subject_key),
409 &subject_pkey))
410 {
411 fprintf (stderr,
412 _("Subject public key `%s' is not well-formed\n"),
413 subject_key);
414 GNUNET_SCHEDULER_shutdown ();
415 return;
416 }
417 if (GNUNET_YES == verify) {
418 if (NULL == issuer_key)
419 {
420 fprintf (stderr,
421 _("Issuer public key not well-formed\n"));
422 GNUNET_SCHEDULER_shutdown ();
423 return;
424
425 }
426 if (GNUNET_OK !=
427 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
428 strlen (issuer_key),
429 &issuer_pkey))
430 {
431 fprintf (stderr,
432 _("Issuer public key `%s' is not well-formed\n"),
433 issuer_key);
434 GNUNET_SCHEDULER_shutdown ();
435 }
436 credential = GNUNET_CREDENTIAL_connect (cfg);
437
438 if (NULL == credential)
439 {
440 fprintf (stderr,
441 _("Failed to connect to CREDENTIAL\n"));
442 GNUNET_SCHEDULER_shutdown ();
443 }
444 if (NULL == issuer_attr || NULL == subject_credential)
445 {
446 fprintf (stderr,
447 _("You must provide issuer and subject attributes\n"));
448 GNUNET_SCHEDULER_shutdown ();
449 }
450
451 //Subject credentials are comma separated
452 char *tmp = GNUNET_strdup (subject_credential);
453 char *tok = strtok (tmp, ",");
454 if (NULL == tok)
455 {
456 fprintf (stderr,
457 "Invalid subject credentials\n");
458 GNUNET_free (tmp);
459 GNUNET_SCHEDULER_shutdown ();
460 }
461 int count = 1;
462 int i;
463 while (NULL != (tok = strtok(NULL, ",")))
464 count++;
465 struct GNUNET_CREDENTIAL_Credential credentials[count];
466 struct GNUNET_CREDENTIAL_Credential *cred;
467 GNUNET_free (tmp);
468 tmp = GNUNET_strdup (subject_credential);
469 tok = strtok (tmp, ",");
470 for (i=0;i<count;i++)
471 {
472 cred = GNUNET_CREDENTIAL_credential_from_string (tok);
473 GNUNET_memcpy (&credentials[i],
474 cred,
475 sizeof (struct GNUNET_CREDENTIAL_Credential));
476 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
477 tok = strtok(NULL, ",");
478 GNUNET_free (cred);
479 }
480
481 verify_request = GNUNET_CREDENTIAL_verify(credential,
482 &issuer_pkey,
483 issuer_attr, //TODO argument
484 &subject_pkey,
485 count,
486 credentials,
487 &handle_verify_result,
488 NULL);
489 for (i=0;i<count;i++)
490 {
491 GNUNET_free ((char*)credentials[i].issuer_attribute);
492 }
493 } else if (GNUNET_YES == create_cred) {
494 if (NULL == ego_name)
495 {
496 fprintf (stderr,
497 _("Issuer ego required\n"));
498 GNUNET_SCHEDULER_shutdown ();
499 return;
500
501 }
502 el = GNUNET_IDENTITY_ego_lookup (cfg,
503 ego_name,
504 &identity_cb,
505 (void *) cfg);
506 return;
507 } else {
508 fprintf (stderr,
509 _("Please specify name to lookup, subject key and issuer key!\n"));
510 GNUNET_SCHEDULER_shutdown ();
511 }
512 return;
513}
514
515
516/**
517 * The main function for gnunet-gns.
518 *
519 * @param argc number of arguments from the command line
520 * @param argv command line arguments
521 * @return 0 ok, 1 on error
522 */
523int
524main (int argc, char *const *argv)
525{
526 struct GNUNET_GETOPT_CommandLineOption options[] = {
527 GNUNET_GETOPT_option_flag ('I',
528 "issue",
529 gettext_noop ("create credential"),
530 &create_cred),
531 GNUNET_GETOPT_option_flag ('V',
532 "verify",
533 gettext_noop ("verify credential against attribute"),
534 &verify),
535 GNUNET_GETOPT_option_string ('s',
536 "subject",
537 "PKEY",
538 gettext_noop ("The public key of the subject to lookup the credential for"),
539 &subject_key),
540 GNUNET_GETOPT_option_string ('b',
541 "credential",
542 "CRED",
543 gettext_noop ("The name of the credential presented by the subject"),
544 &subject_credential),
545 GNUNET_GETOPT_option_string ('i',
546 "issuer",
547 "PKEY",
548 gettext_noop ("The public key of the authority to verify the credential against"),
549 &issuer_key),
550 GNUNET_GETOPT_option_string ('e',
551 "ego",
552 "EGO",
553 gettext_noop ("The ego to use"),
554 &ego_name),
555 GNUNET_GETOPT_option_string ('a',
556 "attribute",
557 "ATTR",
558 gettext_noop ("The issuer attribute to verify against or to issue"),
559 &issuer_attr),
560 GNUNET_GETOPT_option_string ('T',
561 "ttl",
562 "EXP",
563 gettext_noop ("The time to live for the credential"),
564 &expiration),
565 GNUNET_GETOPT_option_flag ('g',
566 "collect",
567 gettext_noop ("collect credentials"),
568 &collect),
569 GNUNET_GETOPT_OPTION_END
570 };
571 int ret;
572
573 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
574 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
575 return 2;
576
577 GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
578 ret =
579 (GNUNET_OK ==
580 GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
581 _("GNUnet credential resolver tool"),
582 options,
583 &run, NULL)) ? 0 : 1;
584 GNUNET_free ((void*) argv);
585 return ret;
586}
587
588/* 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..be88839e9
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1160 @@
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 credential/gnunet-service-credential.c
22 * @brief GNUnet Credential Service (main service)
23 * @author Martin Schanzenbach
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#include <gnunet_dnsparser_lib.h>
35#include <gnunet_identity_service.h>
36#include <gnunet_gnsrecord_lib.h>
37#include <gnunet_namestore_service.h>
38#include <gnunet_gns_service.h>
39
40
41#define GNUNET_CREDENTIAL_MAX_LENGTH 255
42
43struct VerifyRequestHandle;
44
45struct DelegationSetQueueEntry;
46
47
48struct DelegationChainEntry
49{
50 /**
51 * DLL
52 */
53 struct DelegationChainEntry *next;
54
55 /**
56 * DLL
57 */
58 struct DelegationChainEntry *prev;
59
60 /**
61 * The issuer
62 */
63 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
64
65 /**
66 * The subject
67 */
68 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
69
70 /**
71 * The issued attribute
72 */
73 char *issuer_attribute;
74
75 /**
76 * The delegated attribute
77 */
78 char *subject_attribute;
79};
80
81/**
82 * DLL for record
83 */
84struct CredentialRecordEntry
85{
86 /**
87 * DLL
88 */
89 struct CredentialRecordEntry *next;
90
91 /**
92 * DLL
93 */
94 struct CredentialRecordEntry *prev;
95
96 /**
97 * Number of references in delegation chains
98 */
99 uint32_t refcount;
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 * Credential iterator
316 */
317 struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
318
319 /**
320 * Collect task
321 */
322 struct GNUNET_SCHEDULER_Task *collect_next_task;
323
324};
325
326
327/**
328 * Head of the DLL.
329 */
330static struct VerifyRequestHandle *vrh_head;
331
332/**
333 * Tail of the DLL.
334 */
335static struct VerifyRequestHandle *vrh_tail;
336
337/**
338 * Handle to the statistics service
339 */
340static struct GNUNET_STATISTICS_Handle *statistics;
341
342/**
343 * Handle to GNS service.
344 */
345static struct GNUNET_GNS_Handle *gns;
346
347
348/**
349 * Handle to namestore service
350 */
351static struct GNUNET_NAMESTORE_Handle *namestore;
352
353static void
354cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
355{
356 struct DelegationQueueEntry *dq_entry;
357 struct DelegationSetQueueEntry *child;
358
359 if (NULL == ds_entry)
360 return;
361
362 for (dq_entry = ds_entry->queue_entries_head;
363 NULL != dq_entry;
364 dq_entry = ds_entry->queue_entries_head)
365 {
366 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
367 ds_entry->queue_entries_tail,
368 dq_entry);
369 for (child = dq_entry->set_entries_head;
370 NULL != child;
371 child = dq_entry->set_entries_head)
372 {
373 GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
374 dq_entry->set_entries_tail,
375 child);
376 cleanup_delegation_set (child);
377 }
378 GNUNET_free (dq_entry);
379 }
380 GNUNET_free_non_null (ds_entry->issuer_key);
381 GNUNET_free_non_null (ds_entry->lookup_attribute);
382 GNUNET_free_non_null (ds_entry->issuer_attribute);
383 GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation);
384 GNUNET_free_non_null (ds_entry->attr_trailer);
385 if (NULL != ds_entry->lookup_request)
386 {
387 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
388 ds_entry->lookup_request = NULL;
389 }
390 if (NULL != ds_entry->delegation_chain_entry)
391 {
392 GNUNET_free_non_null (ds_entry->delegation_chain_entry->subject_attribute);
393 GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute);
394 GNUNET_free (ds_entry->delegation_chain_entry);
395 }
396 GNUNET_free (ds_entry);
397}
398
399static void
400cleanup_handle (struct VerifyRequestHandle *vrh)
401{
402 struct CredentialRecordEntry *cr_entry;
403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
404 "Cleaning up...\n");
405 if (NULL != vrh->lookup_request)
406 {
407 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
408 vrh->lookup_request = NULL;
409 }
410 cleanup_delegation_set (vrh->root_set);
411 GNUNET_free_non_null (vrh->issuer_attribute);
412 for (cr_entry = vrh->cred_chain_head;
413 NULL != vrh->cred_chain_head;
414 cr_entry = vrh->cred_chain_head)
415 {
416 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
417 vrh->cred_chain_tail,
418 cr_entry);
419 GNUNET_free_non_null (cr_entry->credential);
420 GNUNET_free (cr_entry);
421 }
422 GNUNET_free (vrh);
423}
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 != namestore)
448 {
449 GNUNET_NAMESTORE_disconnect (namestore);
450 namestore = NULL;
451 }
452 if (NULL != statistics)
453 {
454 GNUNET_STATISTICS_destroy (statistics,
455 GNUNET_NO);
456 statistics = NULL;
457 }
458
459}
460
461
462
463static void
464send_lookup_response (struct VerifyRequestHandle *vrh)
465{
466 struct GNUNET_MQ_Envelope *env;
467 struct DelegationChainResultMessage *rmsg;
468 struct DelegationChainEntry *dce;
469 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
470 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
471 struct CredentialRecordEntry *cd;
472 struct CredentialRecordEntry *tmp;
473 size_t size;
474
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Sending response\n");
477 dce = vrh->delegation_chain_head;
478 for (uint32_t i=0;i<vrh->delegation_chain_size;i++)
479 {
480 dd[i].issuer_key = dce->issuer_key;
481 dd[i].subject_key = dce->subject_key;
482 dd[i].issuer_attribute = dce->issuer_attribute;
483 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
484 dd[i].subject_attribute_len = 0;
485 dd[i].subject_attribute = NULL;
486 if (NULL != dce->subject_attribute)
487 {
488 dd[i].subject_attribute = dce->subject_attribute;
489 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
490 }
491 dce = dce->next;
492 }
493
494 /**
495 * Remove all credentials not needed
496 */
497 for (cd = vrh->cred_chain_head; NULL != cd;)
498 {
499 if (cd->refcount > 0)
500 {
501 cd = cd->next;
502 continue;
503 }
504 tmp = cd;
505 cd = cd->next;
506 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
507 vrh->cred_chain_tail,
508 tmp);
509 GNUNET_free (tmp->credential);
510 GNUNET_free (tmp);
511 vrh->cred_chain_size--;
512 }
513
514 /**
515 * Get serialized record data
516 * Append at the end of rmsg
517 */
518 cd = vrh->cred_chain_head;
519 for (uint32_t i=0;i<vrh->cred_chain_size;i++)
520 {
521 cred[i].issuer_key = cd->credential->issuer_key;
522 cred[i].subject_key = cd->credential->subject_key;
523 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
524 cred[i].issuer_attribute = cd->credential->issuer_attribute;
525 cred[i].expiration = cd->credential->expiration;
526 cred[i].signature = cd->credential->signature;
527 cd = cd->next;
528 }
529 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
530 dd,
531 vrh->cred_chain_size,
532 cred);
533 env = GNUNET_MQ_msg_extra (rmsg,
534 size,
535 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
536 //Assign id so that client can find associated request
537 rmsg->id = vrh->request_id;
538 rmsg->d_count = htonl (vrh->delegation_chain_size);
539 rmsg->c_count = htonl (vrh->cred_chain_size);
540
541 if (0 < vrh->cred_chain_size)
542 rmsg->cred_found = htonl (GNUNET_YES);
543 else
544 rmsg->cred_found = htonl (GNUNET_NO);
545
546 GNUNET_assert (-1 !=
547 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
548 dd,
549 vrh->cred_chain_size,
550 cred,
551 size,
552 (char*)&rmsg[1]));
553
554 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
555 env);
556 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
557 cleanup_handle(vrh);
558
559 GNUNET_STATISTICS_update (statistics,
560 "Completed verifications", 1,
561 GNUNET_NO);
562}
563
564
565static void
566backward_resolution (void* cls,
567 uint32_t rd_count,
568 const struct GNUNET_GNSRECORD_Data *rd)
569{
570
571 struct VerifyRequestHandle *vrh;
572 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
573 struct CredentialRecordEntry *cred_pointer;
574 struct DelegationSetQueueEntry *current_set;
575 struct DelegationSetQueueEntry *ds_entry;
576 struct DelegationSetQueueEntry *tmp_set;
577 struct DelegationQueueEntry *dq_entry;
578 char *expanded_attr;
579 char *lookup_attribute;
580
581
582 current_set = cls;
583 current_set->lookup_request = NULL;
584 vrh = current_set->handle;
585 vrh->pending_lookups--;
586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
587 "Got %d attrs\n", rd_count);
588
589 // Each OR
590 for (uint32_t i=0; i < rd_count; i++)
591 {
592 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
593 continue;
594
595 sets = rd[i].data;
596 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
598 "Found new attribute delegation with %d sets. Creating new Job...\n",
599 ntohl (sets->set_count));
600
601 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
602 (const char*)&sets[1],
603 ntohl(sets->set_count),
604 set))
605 {
606 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
607 "Failed to deserialize!\n");
608 continue;
609 }
610 dq_entry = GNUNET_new (struct DelegationQueueEntry);
611 dq_entry->required_solutions = ntohl(sets->set_count);
612 dq_entry->parent_set = current_set;
613 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
614 current_set->queue_entries_tail,
615 dq_entry);
616 // Each AND
617 for (uint32_t j=0; j<ntohl(sets->set_count); j++)
618 {
619 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
620 if (NULL != current_set->attr_trailer)
621 {
622 if (0 == set[j].subject_attribute_len)
623 {
624 GNUNET_asprintf (&expanded_attr,
625 "%s",
626 current_set->attr_trailer);
627
628 } else {
629 GNUNET_asprintf (&expanded_attr,
630 "%s.%s",
631 set[j].subject_attribute,
632 current_set->attr_trailer);
633 }
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Expanded to %s\n", expanded_attr);
636 ds_entry->unresolved_attribute_delegation = expanded_attr;
637 } else {
638 if (0 != set[j].subject_attribute_len)
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
641 "Not Expanding %s\n", set[j].subject_attribute);
642 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
643 }
644 }
645
646 //Add a credential chain entry
647 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
648 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
649 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
650 GNUNET_memcpy (ds_entry->issuer_key,
651 &set[j].subject_key,
652 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
653 if (0 < set[j].subject_attribute_len)
654 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
655 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
656 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
657
658 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
659 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
660 dq_entry->set_entries_tail,
661 ds_entry);
662
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
664 "Checking for cred match\n");
665 /**
666 * Check if this delegation already matches one of our credentials
667 */
668 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
669 cred_pointer = cred_pointer->next)
670 {
671 if(0 != memcmp (&set->subject_key,
672 &cred_pointer->credential->issuer_key,
673 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
674 continue;
675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
676 "Checking if %s matches %s\n",
677 ds_entry->unresolved_attribute_delegation,
678 cred_pointer->credential->issuer_attribute);
679
680 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
681 cred_pointer->credential->issuer_attribute))
682 continue;
683
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
685 "Found issuer\n");
686 cred_pointer->refcount++;
687 //Backtrack
688 for (tmp_set = ds_entry;
689 NULL != tmp_set->parent_queue_entry;
690 tmp_set = tmp_set->parent_queue_entry->parent_set)
691 {
692 tmp_set->parent_queue_entry->required_solutions--;
693 if (NULL != tmp_set->delegation_chain_entry)
694 {
695 vrh->delegation_chain_size++;
696 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
697 vrh->delegation_chain_tail,
698 tmp_set->delegation_chain_entry);
699 }
700 if (0 < tmp_set->parent_queue_entry->required_solutions)
701 break;
702 }
703
704 if (NULL == tmp_set->parent_queue_entry)
705 {
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 "All solutions found\n");
708 //Found match
709 send_lookup_response (vrh);
710 return;
711 }
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "Not all solutions found yet.\n");
714 continue;
715
716 }
717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718 "Building new lookup request from %s\n",
719 ds_entry->unresolved_attribute_delegation);
720 //Continue with backward resolution
721 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
722 strcpy (issuer_attribute_name,
723 ds_entry->unresolved_attribute_delegation);
724 char *next_attr = strtok (issuer_attribute_name, ".");
725 GNUNET_asprintf (&lookup_attribute,
726 "%s.gnu",
727 next_attr);
728 GNUNET_asprintf (&ds_entry->lookup_attribute,
729 "%s",
730 next_attr);
731 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
732 {
733 ds_entry->attr_trailer = NULL;
734 } else {
735 next_attr += strlen (next_attr) + 1;
736 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
737 }
738
739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
740 "Looking up %s\n", ds_entry->lookup_attribute);
741 if (NULL != ds_entry->attr_trailer)
742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
743 "%s still to go...\n", ds_entry->attr_trailer);
744
745 vrh->pending_lookups++;
746 ds_entry->handle = vrh;
747 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
748 lookup_attribute,
749 ds_entry->issuer_key, //issuer_key,
750 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
751 GNUNET_GNS_LO_DEFAULT,
752 &backward_resolution,
753 ds_entry);
754 GNUNET_free (lookup_attribute);
755 }
756 }
757
758 if(0 == vrh->pending_lookups)
759 {
760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
761 "We are all out of attributes...\n");
762 send_lookup_response (vrh);
763 return;
764
765 }
766}
767
768
769/**
770 * Result from GNS lookup.
771 *
772 * @param cls the closure (our client lookup handle)
773 */
774static void
775delegation_chain_resolution_start (void* cls)
776{
777 struct VerifyRequestHandle *vrh = cls;
778 struct DelegationSetQueueEntry *ds_entry;
779 struct CredentialRecordEntry *cr_entry;
780 vrh->lookup_request = NULL;
781
782 if (0 == vrh->cred_chain_size)
783 {
784 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
785 "No credentials found\n");
786 send_lookup_response (vrh);
787 return;
788 }
789
790 for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
791 {
792 if (0 != memcmp (&cr_entry->credential->issuer_key,
793 &vrh->issuer_key,
794 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
795 continue;
796 if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
797 continue;
798 cr_entry->refcount++;
799 //Found match prematurely
800 send_lookup_response (vrh);
801 return;
802
803 }
804
805 /**
806 * Check for attributes from the issuer and follow the chain
807 * till you get the required subject's attributes
808 */
809 char issuer_attribute_name[strlen (vrh->issuer_attribute)];
810 strcpy (issuer_attribute_name,
811 vrh->issuer_attribute);
812 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
813 ".gnu");
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815 "Looking up %s\n", issuer_attribute_name);
816 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
817 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
818 memcpy (ds_entry->issuer_key,
819 &vrh->issuer_key,
820 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
821 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
822 ds_entry->handle = vrh;
823 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
824 vrh->root_set = ds_entry;
825 vrh->pending_lookups = 1;
826 //Start with backward resolution
827 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
828 issuer_attribute_name,
829 &vrh->issuer_key, //issuer_key,
830 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
831 GNUNET_GNS_LO_DEFAULT,
832 &backward_resolution,
833 ds_entry);
834}
835
836static int
837check_verify (void *cls,
838 const struct VerifyMessage *v_msg)
839{
840 size_t msg_size;
841 const char* attr;
842
843 msg_size = ntohs (v_msg->header.size);
844 if (msg_size < sizeof (struct VerifyMessage))
845 {
846 GNUNET_break (0);
847 return GNUNET_SYSERR;
848 }
849 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
850 {
851 GNUNET_break (0);
852 return GNUNET_SYSERR;
853 }
854 attr = (const char *) &v_msg[1];
855
856 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
857 {
858 GNUNET_break (0);
859 return GNUNET_SYSERR;
860 }
861 return GNUNET_OK;
862}
863
864static void
865handle_verify (void *cls,
866 const struct VerifyMessage *v_msg)
867{
868 struct VerifyRequestHandle *vrh;
869 struct GNUNET_SERVICE_Client *client = cls;
870 struct CredentialRecordEntry *cr_entry;
871 uint32_t credentials_count;
872 uint32_t credential_data_size;
873 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
874 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
875 char *attrptr = attr;
876 char *credential_data;
877 const char *utf_in;
878
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
880 "Received VERIFY message\n");
881 utf_in = (const char *) &v_msg[1];
882 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
883 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
884 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
885 vrh = GNUNET_new (struct VerifyRequestHandle);
886 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
887 vrh->client = client;
888 vrh->request_id = v_msg->id;
889 vrh->issuer_key = v_msg->issuer_key;
890 vrh->subject_key = v_msg->subject_key;
891 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
892 if (NULL == issuer_attribute)
893 {
894 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
895 "No issuer attribute provided!\n");
896 send_lookup_response (vrh);
897 return;
898 }
899 /**
900 * First, collect credentials
901 * TODO: cleanup!
902 */
903 credentials_count = ntohl(v_msg->c_count);
904 credential_data_size = ntohs (v_msg->header.size)
905 - sizeof (struct VerifyMessage)
906 - ntohs (v_msg->issuer_attribute_len)
907 - 1;
908 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
909 credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
910 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
911 credential_data,
912 credentials_count,
913 credentials))
914 {
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
916 "Cannot deserialize credentials!\n");
917 send_lookup_response (vrh);
918 return;
919 }
920
921 for (uint32_t i=0;i<credentials_count;i++) {
922 cr_entry = GNUNET_new (struct CredentialRecordEntry);
923 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
924 credentials[i].issuer_attribute_len);
925 GNUNET_memcpy (cr_entry->credential,
926 &credentials[i],
927 sizeof (struct GNUNET_CREDENTIAL_Credential));
928 GNUNET_memcpy (&cr_entry->credential[1],
929 credentials[i].issuer_attribute,
930 credentials[i].issuer_attribute_len);
931 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
932 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
933 vrh->cred_chain_tail,
934 cr_entry);
935 vrh->cred_chain_size++;
936 }
937
938 delegation_chain_resolution_start (vrh);
939
940}
941
942static void
943handle_cred_collection_error_cb (void *cls)
944{
945 struct VerifyRequestHandle *vrh = cls;
946 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
947 "Got disconnected from namestore database.\n");
948 vrh->cred_collection_iter = NULL;
949 send_lookup_response (vrh);
950}
951
952static void
953collect_next (void *cls)
954{
955 struct VerifyRequestHandle *vrh = cls;
956 vrh->collect_next_task = NULL;
957 GNUNET_assert (NULL != vrh->cred_collection_iter);
958 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
959}
960
961static void
962handle_cred_collection_cb (void *cls,
963 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
964 const char *label,
965 unsigned int rd_count,
966 const struct GNUNET_GNSRECORD_Data *rd)
967{
968 struct VerifyRequestHandle *vrh = cls;
969 struct GNUNET_CREDENTIAL_Credential *crd;
970 struct CredentialRecordEntry *cr_entry;
971 int cred_record_count;
972
973 cred_record_count = 0;
974 for (uint32_t i=0; i < rd_count; i++)
975 {
976 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
977 continue;
978 cred_record_count++;
979 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
980 rd[i].data_size);
981 if (NULL == crd)
982 {
983 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
984 "Invalid credential found\n");
985 continue;
986 }
987 cr_entry = GNUNET_new (struct CredentialRecordEntry);
988 cr_entry->credential = crd;
989 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
990 vrh->cred_chain_tail,
991 cr_entry);
992 vrh->cred_chain_size++;
993 }
994 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
995 vrh);
996}
997
998static void
999handle_cred_collection_finished_cb (void *cls)
1000{
1001 struct VerifyRequestHandle *vrh = cls;
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 "Done collecting credentials.\n");
1004 vrh->cred_collection_iter = NULL;
1005 delegation_chain_resolution_start (vrh);
1006}
1007
1008static void
1009handle_collect (void *cls,
1010 const struct CollectMessage *c_msg)
1011{
1012 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1013 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1014 struct VerifyRequestHandle *vrh;
1015 struct GNUNET_SERVICE_Client *client = cls;
1016 char *attrptr = attr;
1017 const char *utf_in;
1018
1019 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1020 "Received COLLECT message\n");
1021
1022 utf_in = (const char *) &c_msg[1];
1023 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1024
1025 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1026 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1027 vrh = GNUNET_new (struct VerifyRequestHandle);
1028 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1029 vrh->client = client;
1030 vrh->request_id = c_msg->id;
1031 vrh->issuer_key = c_msg->issuer_key;
1032 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1033 &vrh->subject_key);
1034 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1035
1036 if (NULL == issuer_attribute)
1037 {
1038 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1039 "No issuer attribute provided!\n");
1040 send_lookup_response (vrh);
1041 return;
1042 }
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1044 "Getting credentials for subject\n");
1045 /**
1046 * First, get attribute from subject
1047 */
1048 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
1049 &c_msg->subject_key,
1050 &handle_cred_collection_error_cb,
1051 vrh,
1052 &handle_cred_collection_cb,
1053 vrh,
1054 &handle_cred_collection_finished_cb,
1055 vrh);
1056}
1057
1058
1059static int
1060check_collect (void *cls,
1061 const struct CollectMessage *c_msg)
1062{
1063 size_t msg_size;
1064 const char* attr;
1065
1066 msg_size = ntohs (c_msg->header.size);
1067 if (msg_size < sizeof (struct CollectMessage))
1068 {
1069 GNUNET_break (0);
1070 return GNUNET_SYSERR;
1071 }
1072 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1073 {
1074 GNUNET_break (0);
1075 return GNUNET_SYSERR;
1076 }
1077 attr = (const char *) &c_msg[1];
1078
1079 if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
1080 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1081 {
1082 GNUNET_break (0);
1083 return GNUNET_SYSERR;
1084 }
1085 return GNUNET_OK;
1086}
1087
1088static void
1089client_disconnect_cb (void *cls,
1090 struct GNUNET_SERVICE_Client *client,
1091 void *app_ctx)
1092{
1093 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1094 "Client %p disconnected\n",
1095 client);
1096}
1097
1098static void *
1099client_connect_cb (void *cls,
1100 struct GNUNET_SERVICE_Client *client,
1101 struct GNUNET_MQ_Handle *mq)
1102{
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104 "Client %p connected\n",
1105 client);
1106 return client;
1107}
1108
1109/**
1110 * Process Credential requests.
1111 *
1112 * @param cls closure
1113 * @param c configuration to use
1114 * @param handle service handle
1115 */
1116static void
1117run (void *cls,
1118 const struct GNUNET_CONFIGURATION_Handle *c,
1119 struct GNUNET_SERVICE_Handle *handle)
1120{
1121
1122 gns = GNUNET_GNS_connect (c);
1123 if (NULL == gns)
1124 {
1125 fprintf (stderr,
1126 _("Failed to connect to GNS\n"));
1127 }
1128 namestore = GNUNET_NAMESTORE_connect (c);
1129 if (NULL == namestore)
1130 {
1131 fprintf (stderr,
1132 _("Failed to connect to namestore\n"));
1133 }
1134
1135 statistics = GNUNET_STATISTICS_create ("credential", c);
1136 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1137}
1138
1139
1140/**
1141 * Define "main" method using service macro
1142 */
1143GNUNET_SERVICE_MAIN
1144("credential",
1145 GNUNET_SERVICE_OPTION_NONE,
1146 &run,
1147 &client_connect_cb,
1148 &client_disconnect_cb,
1149 NULL,
1150 GNUNET_MQ_hd_var_size (verify,
1151 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1152 struct VerifyMessage,
1153 NULL),
1154 GNUNET_MQ_hd_var_size (collect,
1155 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1156 struct CollectMessage,
1157 NULL),
1158 GNUNET_MQ_handler_end());
1159
1160/* 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..342790b7a
--- /dev/null
+++ b/src/credential/plugin_gnsrecord_credential.c
@@ -0,0 +1,353 @@
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 Martin Schanzenbach
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_DEBUG,
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 case GNUNET_GNSRECORD_TYPE_POLICY:
129 {
130 return GNUNET_strndup (data,data_size);
131 }
132 default:
133 return NULL;
134 }
135}
136
137
138/**
139 * Convert human-readable version of a 'value' of a record to the binary
140 * representation.
141 *
142 * @param cls closure, unused
143 * @param type type of the record
144 * @param s human-readable string
145 * @param data set to value in binary encoding (will be allocated)
146 * @param data_size set to number of bytes in @a data
147 * @return #GNUNET_OK on success
148 */
149static int
150credential_string_to_value (void *cls,
151 uint32_t type,
152 const char *s,
153 void **data,
154 size_t *data_size)
155{
156 if (NULL == s)
157 return GNUNET_SYSERR;
158 switch (type)
159 {
160 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
161 {
162 struct GNUNET_CREDENTIAL_DelegationRecord *sets;
163 char attr_str[253 + 1];
164 char subject_pkey[52 + 1];
165 char *token;
166 char *tmp_str;
167 int matches = 0;
168 int entries;
169 size_t tmp_data_size;
170 int i;
171
172 tmp_str = GNUNET_strdup (s);
173 token = strtok (tmp_str, ",");
174 entries = 0;
175 tmp_data_size = 0;
176 *data_size = sizeof (struct GNUNET_CREDENTIAL_DelegationRecord);
177 while (NULL != token)
178 {
179 matches = SSCANF (token,
180 "%s %s",
181 subject_pkey,
182 attr_str);
183 if (0 == matches)
184 {
185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186 _("Unable to parse ATTR record string `%s'\n"),
187 s);
188 GNUNET_free (tmp_str);
189 return GNUNET_SYSERR;
190 }
191 if (1 == matches) {
192 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet);
193 } else if (2 == matches) {
194 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
195 }
196 entries++;
197 token = strtok (NULL, ",");
198 }
199 GNUNET_free (tmp_str);
200 tmp_str = GNUNET_strdup (s);
201 token = strtok (tmp_str, ",");
202 struct GNUNET_CREDENTIAL_DelegationSet set[entries];
203 for (i=0;i<entries;i++)
204 {
205 matches = SSCANF (token,
206 "%s %s",
207 subject_pkey,
208 attr_str);
209 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
210 strlen (subject_pkey),
211 &set[i].subject_key);
212 if (2 == matches) {
213 set[i].subject_attribute_len = strlen (attr_str) + 1;
214 set[i].subject_attribute = GNUNET_strdup (attr_str);
215 }
216 token = strtok (NULL , ",");
217 }
218 tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
219 set);
220
221 if (-1 == tmp_data_size)
222 return GNUNET_SYSERR;
223 *data_size += tmp_data_size;
224 *data = sets = GNUNET_malloc (*data_size);
225 GNUNET_CREDENTIAL_delegation_set_serialize (entries,
226 set,
227 tmp_data_size,
228 (char*)&sets[1]);
229 for (i=0;i<entries;i++)
230 {
231 if (0 != set[i].subject_attribute_len)
232 GNUNET_free ((char*)set[i].subject_attribute);
233 }
234 sets->set_count = htonl (entries);
235 sets->data_size = GNUNET_htonll (tmp_data_size);
236
237 GNUNET_free (tmp_str);
238 return GNUNET_OK;
239 }
240 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
241 {
242 struct GNUNET_CREDENTIAL_Credential *cred;
243 cred = GNUNET_CREDENTIAL_credential_from_string (s);
244
245 *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
246 (char**)data);
247 return GNUNET_OK;
248 }
249 case GNUNET_GNSRECORD_TYPE_POLICY:
250 {
251 *data_size = strlen (s);
252 *data = GNUNET_strdup (s);
253 return GNUNET_OK;
254 }
255 default:
256 return GNUNET_SYSERR;
257 }
258}
259
260
261/**
262 * Mapping of record type numbers to human-readable
263 * record type names.
264 */
265static struct {
266 const char *name;
267 uint32_t number;
268} name_map[] = {
269 { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
270 { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
271 { "POLICY", GNUNET_GNSRECORD_TYPE_POLICY },
272 { NULL, UINT32_MAX }
273};
274
275
276/**
277 * Convert a type name (i.e. "AAAA") to the corresponding number.
278 *
279 * @param cls closure, unused
280 * @param gns_typename name to convert
281 * @return corresponding number, UINT32_MAX on error
282 */
283static uint32_t
284credential_typename_to_number (void *cls,
285 const char *gns_typename)
286{
287 unsigned int i;
288
289 i=0;
290 while ( (name_map[i].name != NULL) &&
291 (0 != strcasecmp (gns_typename, name_map[i].name)) )
292 i++;
293 return name_map[i].number;
294}
295
296
297/**
298 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
299 *
300 * @param cls closure, unused
301 * @param type number of a type to convert
302 * @return corresponding typestring, NULL on error
303 */
304static const char *
305credential_number_to_typename (void *cls,
306 uint32_t type)
307{
308 unsigned int i;
309
310 i=0;
311 while ( (name_map[i].name != NULL) &&
312 (type != name_map[i].number) )
313 i++;
314 return name_map[i].name;
315}
316
317
318/**
319 * Entry point for the plugin.
320 *
321 * @param cls NULL
322 * @return the exported block API
323 */
324void *
325libgnunet_plugin_gnsrecord_credential_init (void *cls)
326{
327 struct GNUNET_GNSRECORD_PluginFunctions *api;
328
329 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
330 api->value_to_string = &credential_value_to_string;
331 api->string_to_value = &credential_string_to_value;
332 api->typename_to_number = &credential_typename_to_number;
333 api->number_to_typename = &credential_number_to_typename;
334 return api;
335}
336
337
338/**
339 * Exit point from the plugin.
340 *
341 * @param cls the return value from #libgnunet_plugin_block_test_init
342 * @return NULL
343 */
344void *
345libgnunet_plugin_gnsrecord_credential_done (void *cls)
346{
347 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
348
349 GNUNET_free (api);
350 return NULL;
351}
352
353/* 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..480658822
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,1146 @@
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 credential/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_API_NS_CREDENTIAL_COLLECT "/credential/collect"
45
46#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
47
48#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
49
50#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
51
52#define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
53
54#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
55
56#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
57
58#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
59
60#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
61
62/**
63 * @brief struct returned by the initialization function of the plugin
64 */
65struct Plugin
66{
67 const struct GNUNET_CONFIGURATION_Handle *cfg;
68};
69
70const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72struct RequestHandle
73{
74 /**
75 * Handle to Credential service.
76 */
77 struct GNUNET_CREDENTIAL_Handle *credential;
78
79 /**
80 * Handle to lookup request
81 */
82 struct GNUNET_CREDENTIAL_Request *verify_request;
83
84 /**
85 * Handle to issue request
86 */
87 struct GNUNET_CREDENTIAL_Request *issue_request;
88
89 /**
90 * Handle to identity
91 */
92 struct GNUNET_IDENTITY_Handle *identity;
93
94 /**
95 * Handle to identity operation
96 */
97 struct GNUNET_IDENTITY_Operation *id_op;
98
99 /**
100 * Handle to ego lookup
101 */
102 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
103
104 /**
105 * Handle to rest request
106 */
107 struct GNUNET_REST_RequestHandle *rest_handle;
108
109 /**
110 * ID of a task associated with the resolution process.
111 */
112 struct GNUNET_SCHEDULER_Task * timeout_task;
113
114 /**
115 * The root of the received JSON or NULL
116 */
117 json_t *json_root;
118
119 /**
120 * The plugin result processor
121 */
122 GNUNET_REST_ResultProcessor proc;
123
124 /**
125 * The closure of the result processor
126 */
127 void *proc_cls;
128
129 /**
130 * The issuer attribute to verify
131 */
132 char *issuer_attr;
133
134 /**
135 * The subject attribute
136 */
137 char *subject_attr;
138
139 /**
140 * The public key of the issuer
141 */
142 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
143
144 /**
145 * The public key of the subject
146 */
147 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
148
149 /**
150 * HTTP response code
151 */
152 int response_code;
153
154 /**
155 * Timeout
156 */
157 struct GNUNET_TIME_Relative timeout;
158
159};
160
161
162/**
163 * Cleanup lookup handle.
164 *
165 * @param handle Handle to clean up
166 */
167static void
168cleanup_handle (struct RequestHandle *handle)
169{
170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
171 "Cleaning up\n");
172 if (NULL != handle->json_root)
173 json_decref (handle->json_root);
174
175 if (NULL != handle->issuer_attr)
176 GNUNET_free (handle->issuer_attr);
177 if (NULL != handle->subject_attr)
178 GNUNET_free (handle->subject_attr);
179 if (NULL != handle->verify_request)
180 GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
181 if (NULL != handle->credential)
182 GNUNET_CREDENTIAL_disconnect (handle->credential);
183 if (NULL != handle->id_op)
184 GNUNET_IDENTITY_cancel (handle->id_op);
185 if (NULL != handle->ego_lookup)
186 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
187 if (NULL != handle->identity)
188 GNUNET_IDENTITY_disconnect (handle->identity);
189 if (NULL != handle->timeout_task)
190 {
191 GNUNET_SCHEDULER_cancel (handle->timeout_task);
192 }
193 GNUNET_free (handle);
194}
195
196
197static void
198do_error (void *cls)
199{
200 struct RequestHandle *handle = cls;
201 struct MHD_Response *resp;
202
203 resp = GNUNET_REST_create_response (NULL);
204 handle->proc (handle->proc_cls, resp, handle->response_code);
205 cleanup_handle (handle);
206}
207
208/**
209 * Attribute delegation to JSON
210 *
211 * @param delegation_chain_entry the DSE
212 * @return JSON, NULL if failed
213 */
214static json_t*
215attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
216{
217 char *subject;
218 char *issuer;
219 json_t *attr_obj;
220
221 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
222 if (NULL == issuer)
223 {
224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 "Issuer in delegation malformed\n");
226 return NULL;
227 }
228 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
229 if (NULL == subject)
230 {
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 "Subject in credential malformed\n");
233 GNUNET_free (issuer);
234 return NULL;
235 }
236 attr_obj = json_object ();
237
238 json_object_set_new (attr_obj, "issuer", json_string (issuer));
239 json_object_set_new (attr_obj, "issuer_attribute",
240 json_string (delegation_chain_entry->issuer_attribute));
241
242 json_object_set_new (attr_obj, "subject", json_string (subject));
243 if (0 < delegation_chain_entry->subject_attribute_len)
244 {
245 json_object_set_new (attr_obj, "subject_attribute",
246 json_string (delegation_chain_entry->subject_attribute));
247 }
248 GNUNET_free (issuer);
249 GNUNET_free (subject);
250 return attr_obj;
251}
252
253/**
254 * JSONAPI resource to Credential
255 *
256 * @param res the JSONAPI resource
257 * @return the resulting credential, NULL if failed
258 */
259static struct GNUNET_CREDENTIAL_Credential*
260json_to_credential (json_t *res)
261{
262 struct GNUNET_CREDENTIAL_Credential *cred;
263 json_t *tmp;
264 const char *attribute;
265 const char *signature;
266 char *sig;
267
268 tmp = json_object_get (res, "attribute");
269 if (0 == json_is_string (tmp))
270 {
271 return NULL;
272 }
273 attribute = json_string_value (tmp);
274 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
275 + strlen (attribute));
276 cred->issuer_attribute = attribute;
277 cred->issuer_attribute_len = strlen (attribute);
278 tmp = json_object_get (res, "issuer");
279 if (0 == json_is_string (tmp))
280 {
281 GNUNET_free (cred);
282 return NULL;
283 }
284
285 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
286 strlen (json_string_value(tmp)),
287 &cred->issuer_key);
288 tmp = json_object_get (res, "subject");
289 if (0 == json_is_string (tmp))
290 {
291 GNUNET_free (cred);
292 return NULL;
293 }
294 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
295 strlen (json_string_value(tmp)),
296 &cred->subject_key);
297
298 tmp = json_object_get (res, "signature");
299 if (0 == json_is_string (tmp))
300 {
301 GNUNET_free (cred);
302 return NULL;
303 }
304 signature = json_string_value (tmp);
305 GNUNET_STRINGS_base64_decode (signature,
306 strlen (signature),
307 (char**)&sig);
308 GNUNET_memcpy (&cred->signature,
309 sig,
310 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
311 GNUNET_free (sig);
312
313 tmp = json_object_get (res, "expiration");
314 if (0 == json_is_integer (tmp))
315 {
316 GNUNET_free (cred);
317 return NULL;
318 }
319 cred->expiration.abs_value_us = json_integer_value (tmp);
320 return cred;
321}
322
323
324/**
325 * Credential to JSON
326 *
327 * @param cred the credential
328 * @return the resulting json, NULL if failed
329 */
330static json_t*
331credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
332{
333 char *issuer;
334 char *subject;
335 char *signature;
336 char attribute[cred->issuer_attribute_len + 1];
337 json_t *cred_obj;
338
339 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
340 if (NULL == issuer)
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
343 "Issuer in credential malformed\n");
344 return NULL;
345 }
346 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
347 if (NULL == subject)
348 {
349 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
350 "Subject in credential malformed\n");
351 GNUNET_free (issuer);
352 return NULL;
353 }
354 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
355 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
356 &signature);
357 memcpy (attribute,
358 cred->issuer_attribute,
359 cred->issuer_attribute_len);
360 attribute[cred->issuer_attribute_len] = '\0';
361 cred_obj = json_object ();
362 json_object_set_new (cred_obj, "issuer", json_string (issuer));
363 json_object_set_new (cred_obj, "subject", json_string (subject));
364 json_object_set_new (cred_obj, "attribute", json_string (attribute));
365 json_object_set_new (cred_obj, "signature", json_string (signature));
366 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
367 GNUNET_free (issuer);
368 GNUNET_free (subject);
369 GNUNET_free (signature);
370 return cred_obj;
371}
372
373static void
374handle_collect_response (void *cls,
375 unsigned int d_count,
376 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
377 unsigned int c_count,
378 struct GNUNET_CREDENTIAL_Credential *cred)
379{
380 struct RequestHandle *handle = cls;
381 struct MHD_Response *resp;
382 struct GNUNET_JSONAPI_Document *json_document;
383 struct GNUNET_JSONAPI_Resource *json_resource;
384 json_t *cred_obj;
385 json_t *cred_array;
386 char *result;
387 char *issuer;
388 char *id;
389 uint32_t i;
390
391 handle->verify_request = NULL;
392 if (NULL == cred) {
393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
394 "Verify failed.\n");
395 handle->response_code = MHD_HTTP_NOT_FOUND;
396 GNUNET_SCHEDULER_add_now (&do_error, handle);
397 return;
398 }
399 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
400 if (NULL == issuer)
401 {
402 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403 "Issuer in delegation malformed\n");
404 return;
405 }
406 GNUNET_asprintf (&id,
407 "%s.%s",
408 issuer,
409 handle->issuer_attr);
410 GNUNET_free (issuer);
411 json_document = GNUNET_JSONAPI_document_new ();
412 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
413 id);
414 GNUNET_free (id);
415 cred_array = json_array ();
416 for (i=0;i<c_count;i++)
417 {
418 cred_obj = credential_to_json (&cred[i]);
419 json_array_append_new (cred_array, cred_obj);
420 }
421 GNUNET_JSONAPI_resource_add_attr (json_resource,
422 GNUNET_REST_JSONAPI_CREDENTIAL,
423 cred_array);
424 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
425 GNUNET_JSONAPI_document_serialize (json_document, &result);
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
427 "Result %s\n",
428 result);
429 json_decref (cred_array);
430 GNUNET_JSONAPI_document_delete (json_document);
431 resp = GNUNET_REST_create_response (result);
432 GNUNET_free(result);
433 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
434 cleanup_handle (handle);
435}
436
437static void
438subject_ego_lookup (void *cls,
439 const struct GNUNET_IDENTITY_Ego *ego)
440{
441 struct RequestHandle *handle = cls;
442 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
443 handle->ego_lookup = NULL;
444
445 if (NULL == ego)
446 {
447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
448 "Subject not found\n");
449 GNUNET_SCHEDULER_add_now (&do_error, handle);
450 return;
451 }
452 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
453 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
454 &handle->issuer_key,
455 handle->issuer_attr,
456 sub_key,
457 &handle_collect_response,
458 handle);
459}
460
461
462
463static void
464handle_verify_response (void *cls,
465 unsigned int d_count,
466 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
467 unsigned int c_count,
468 struct GNUNET_CREDENTIAL_Credential *cred)
469{
470
471 struct RequestHandle *handle = cls;
472 struct MHD_Response *resp;
473 struct GNUNET_JSONAPI_Document *json_document;
474 struct GNUNET_JSONAPI_Resource *json_resource;
475 json_t *cred_obj;
476 json_t *attr_obj;
477 json_t *cred_array;
478 json_t *attr_array;
479 char *result;
480 char *issuer;
481 char *id;
482 uint32_t i;
483
484 handle->verify_request = NULL;
485 if (NULL == cred) {
486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
487 "Verify failed.\n");
488 handle->response_code = MHD_HTTP_NOT_FOUND;
489 GNUNET_SCHEDULER_add_now (&do_error, handle);
490 return;
491 }
492 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
493 if (NULL == issuer)
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
496 "Issuer in delegation malformed\n");
497 return;
498 }
499 GNUNET_asprintf (&id,
500 "%s.%s",
501 issuer,
502 handle->issuer_attr);
503 GNUNET_free (issuer);
504 json_document = GNUNET_JSONAPI_document_new ();
505 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
506 id);
507 GNUNET_free (id);
508 attr_array = json_array ();
509 for (i = 0; i < d_count; i++)
510 {
511 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
512 json_array_append_new (attr_array, attr_obj);
513 }
514 cred_array = json_array ();
515 for (i=0;i<c_count;i++)
516 {
517 cred_obj = credential_to_json (&cred[i]);
518 json_array_append_new (cred_array, cred_obj);
519 }
520 GNUNET_JSONAPI_resource_add_attr (json_resource,
521 GNUNET_REST_JSONAPI_CREDENTIAL,
522 cred_array);
523 GNUNET_JSONAPI_resource_add_attr (json_resource,
524 GNUNET_REST_JSONAPI_DELEGATIONS,
525 attr_array);
526 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
527 GNUNET_JSONAPI_document_serialize (json_document, &result);
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Result %s\n",
530 result);
531 json_decref (attr_array);
532 json_decref (cred_array);
533 GNUNET_JSONAPI_document_delete (json_document);
534 resp = GNUNET_REST_create_response (result);
535 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
536 GNUNET_free (result);
537 cleanup_handle (handle);
538}
539
540static void
541collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
542 const char* url,
543 void *cls)
544{
545 struct RequestHandle *handle = cls;
546 struct GNUNET_HashCode key;
547 char *tmp;
548 char *entity_attr;
549
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
551 "Connecting...\n");
552 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
553 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
554 &do_error, handle);
555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
556 "Connected\n");
557 if (NULL == handle->credential)
558 {
559 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560 "Connecting to CREDENTIAL failed\n");
561 GNUNET_SCHEDULER_add_now (&do_error, handle);
562 return;
563 }
564 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
565 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
566 &key);
567 if ( GNUNET_NO ==
568 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
569 &key) )
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 "Missing issuer attribute\n");
573 GNUNET_SCHEDULER_add_now (&do_error, handle);
574 return;
575 }
576 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
577 &key);
578 entity_attr = GNUNET_strdup (tmp);
579 tmp = strtok(entity_attr, ".");
580 if (NULL == tmp)
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
583 "Malformed issuer or attribute\n");
584 GNUNET_free (entity_attr);
585 GNUNET_SCHEDULER_add_now (&do_error, handle);
586 return;
587 }
588 if (GNUNET_OK !=
589 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
590 strlen (tmp),
591 &handle->issuer_key))
592 {
593 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
594 "Malformed issuer key\n");
595 GNUNET_free (entity_attr);
596 GNUNET_SCHEDULER_add_now (&do_error, handle);
597 return;
598 }
599 tmp = strtok (NULL, "."); //Issuer attribute
600 if (NULL == tmp)
601 {
602 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603 "Malformed attribute\n");
604 GNUNET_free (entity_attr);
605 GNUNET_SCHEDULER_add_now (&do_error, handle);
606 return;
607 }
608 handle->issuer_attr = GNUNET_strdup (tmp);
609 GNUNET_free (entity_attr);
610
611 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
612 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
613 &key);
614 if ( GNUNET_NO ==
615 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
616 &key) )
617 {
618 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619 "Missing subject\n");
620 GNUNET_free (entity_attr);
621 GNUNET_SCHEDULER_add_now (&do_error, handle);
622 return;
623 }
624 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
625 &key);
626 if (NULL == tmp)
627 {
628 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
629 "Malformed subject\n");
630 GNUNET_free (entity_attr);
631 GNUNET_SCHEDULER_add_now (&do_error, handle);
632 return;
633 }
634 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
635 tmp,
636 &subject_ego_lookup,
637 handle);
638}
639
640
641
642static void
643verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
644 const char* url,
645 void *cls)
646{
647 struct RequestHandle *handle = cls;
648 struct GNUNET_HashCode key;
649 struct GNUNET_JSONAPI_Document *json_obj;
650 struct GNUNET_JSONAPI_Resource *res;
651 struct GNUNET_CREDENTIAL_Credential *cred;
652 char *tmp;
653 char *entity_attr;
654 int i;
655 uint32_t credential_count;
656 uint32_t resource_count;
657 json_t *cred_json;
658 json_t *data_js;
659 json_error_t err;
660
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "Connecting...\n");
663 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
664 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
665 &do_error, handle);
666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
667 "Connected\n");
668 if (NULL == handle->credential)
669 {
670 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
671 "Connecting to CREDENTIAL failed\n");
672 GNUNET_SCHEDULER_add_now (&do_error, handle);
673 return;
674 }
675 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
676 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
677 &key);
678 if ( GNUNET_NO ==
679 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
680 &key) )
681 {
682 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
683 "Missing issuer attribute\n");
684 GNUNET_SCHEDULER_add_now (&do_error, handle);
685 return;
686 }
687 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
688 &key);
689 entity_attr = GNUNET_strdup (tmp);
690 tmp = strtok(entity_attr, ".");
691 if (NULL == tmp)
692 {
693 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
694 "Malformed issuer or attribute\n");
695 GNUNET_free (entity_attr);
696 GNUNET_SCHEDULER_add_now (&do_error, handle);
697 return;
698 }
699 if (GNUNET_OK !=
700 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
701 strlen (tmp),
702 &handle->issuer_key))
703 {
704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
705 "Malformed issuer key\n");
706 GNUNET_free (entity_attr);
707 GNUNET_SCHEDULER_add_now (&do_error, handle);
708 return;
709 }
710 tmp = strtok (NULL, "."); //Issuer attribute
711 if (NULL == tmp)
712 {
713 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
714 "Malformed attribute\n");
715 GNUNET_free (entity_attr);
716 GNUNET_SCHEDULER_add_now (&do_error, handle);
717 return;
718 }
719 handle->issuer_attr = GNUNET_strdup (tmp);
720 GNUNET_free (entity_attr);
721
722 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
723 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
724 &key);
725 if ( GNUNET_NO ==
726 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
727 &key) )
728 {
729 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
730 "Missing subject key\n");
731 GNUNET_free (entity_attr);
732 GNUNET_SCHEDULER_add_now (&do_error, handle);
733 return;
734 }
735 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
736 &key);
737 if (NULL == tmp)
738 {
739 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
740 "Malformed subject\n");
741 GNUNET_free (entity_attr);
742 GNUNET_SCHEDULER_add_now (&do_error, handle);
743 return;
744 }
745 if (GNUNET_OK !=
746 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
747 strlen (tmp),
748 &handle->subject_key)) {
749 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
750 "Malformed subject key\n");
751 GNUNET_free (entity_attr);
752 GNUNET_SCHEDULER_add_now (&do_error, handle);
753 return;
754 }
755
756 if (0 >= handle->rest_handle->data_size)
757 {
758 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
759 "Missing credentials\n");
760 GNUNET_SCHEDULER_add_now (&do_error, handle);
761 return;
762 }
763
764 struct GNUNET_JSON_Specification docspec[] = {
765 GNUNET_JSON_spec_jsonapi_document (&json_obj),
766 GNUNET_JSON_spec_end()
767 };
768 char term_data[handle->rest_handle->data_size+1];
769 term_data[handle->rest_handle->data_size] = '\0';
770 credential_count = 0;
771 GNUNET_memcpy (term_data,
772 handle->rest_handle->data,
773 handle->rest_handle->data_size);
774 data_js = json_loads (term_data,
775 JSON_DECODE_ANY,
776 &err);
777 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
778 NULL, NULL));
779 json_decref (data_js);
780 if (NULL == json_obj)
781 {
782 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
783 "Unable to parse JSONAPI Object from %s\n",
784 term_data);
785 GNUNET_SCHEDULER_add_now (&do_error, handle);
786 return;
787 }
788
789 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
790 GNUNET_assert (1 == resource_count);
791 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
792 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
793 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
794 {
795 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
796 "Resource not a credential!\n");
797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
798 "Unable to parse JSONAPI Object from %s\n",
799 term_data);
800 GNUNET_JSONAPI_document_delete (json_obj);
801 GNUNET_SCHEDULER_add_now (&do_error, handle);
802 return;
803 }
804 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
805 GNUNET_REST_JSONAPI_CREDENTIAL);
806
807 GNUNET_assert (json_is_array (cred_json));
808
809 credential_count = json_array_size(cred_json);
810
811 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
812 for (i=0;i<credential_count;i++)
813 {
814 cred = json_to_credential (json_array_get (cred_json, i));
815 if (NULL == cred)
816 {
817 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
818 "Unable to parse credential!\n");
819 continue;
820 }
821 GNUNET_memcpy (&credentials[i],
822 cred,
823 sizeof (struct GNUNET_CREDENTIAL_Credential));
824 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
825 GNUNET_free (cred);
826 }
827 GNUNET_JSONAPI_document_delete(json_obj);
828 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
829 &handle->issuer_key,
830 handle->issuer_attr,
831 &handle->subject_key,
832 credential_count,
833 credentials,
834 &handle_verify_response,
835 handle);
836 for (i=0;i<credential_count;i++)
837 GNUNET_free ((char*)credentials[i].issuer_attribute);
838
839}
840
841void
842send_cred_response (struct RequestHandle *handle,
843 struct GNUNET_CREDENTIAL_Credential *cred)
844{
845 struct MHD_Response *resp;
846 struct GNUNET_JSONAPI_Document *json_document;
847 struct GNUNET_JSONAPI_Resource *json_resource;
848 json_t *cred_obj;
849 char *result;
850 char *issuer;
851 char *subject;
852 char *signature;
853 char *id;
854
855 GNUNET_assert (NULL != cred);
856 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
857 if (NULL == issuer)
858 {
859 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
860 "Subject malformed\n");
861 return;
862 }
863 GNUNET_asprintf (&id,
864 "%s.%s",
865 issuer,
866 (char*)&cred[1]);
867 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
868 if (NULL == subject)
869 {
870 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
871 "Subject malformed\n");
872 return;
873 }
874 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
875 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
876 &signature);
877 json_document = GNUNET_JSONAPI_document_new ();
878 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
879 id);
880 GNUNET_free (id);
881 cred_obj = json_object();
882 json_object_set_new (cred_obj, "issuer", json_string (issuer));
883 json_object_set_new (cred_obj, "subject", json_string (subject));
884 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
885 json_object_set_new (cred_obj, "signature", json_string (signature));
886 GNUNET_JSONAPI_resource_add_attr (json_resource,
887 GNUNET_REST_JSONAPI_CREDENTIAL,
888 cred_obj);
889 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
890 GNUNET_JSONAPI_document_serialize (json_document, &result);
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
892 "Result %s\n",
893 result);
894 json_decref (cred_obj);
895 GNUNET_JSONAPI_document_delete (json_document);
896 resp = GNUNET_REST_create_response (result);
897 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
898 GNUNET_free (result);
899 GNUNET_free (signature);
900 GNUNET_free (issuer);
901 GNUNET_free (subject);
902 cleanup_handle (handle);
903}
904
905void
906get_cred_issuer_cb (void *cls,
907 struct GNUNET_IDENTITY_Ego *ego,
908 void **ctx,
909 const char *name)
910{
911 struct RequestHandle *handle = cls;
912 struct GNUNET_TIME_Absolute etime_abs;
913 struct GNUNET_TIME_Relative etime_rel;
914 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
915 struct GNUNET_HashCode key;
916 struct GNUNET_CREDENTIAL_Credential *cred;
917 char* expiration_str;
918 char* tmp;
919
920 handle->id_op = NULL;
921
922 if (NULL == name)
923 {
924 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
925 "Issuer not configured!\n");
926 GNUNET_SCHEDULER_add_now (&do_error, handle);
927 return;
928 }
929
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 "Connecting to credential service...\n");
932 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
934 "Connected\n");
935 if (NULL == handle->credential)
936 {
937 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
938 "Connecting to CREDENTIAL failed\n");
939 GNUNET_SCHEDULER_add_now (&do_error, handle);
940 return;
941 }
942 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
943 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
944 &key);
945 if ( GNUNET_NO ==
946 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
947 &key) )
948 {
949 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
950 "Missing expiration\n");
951 GNUNET_SCHEDULER_add_now (&do_error, handle);
952 return;
953 }
954 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
955 &key);
956 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
957 &etime_rel))
958 {
959 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
960 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
961 &etime_abs))
962 {
963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
964 "Malformed expiration: %s\n", expiration_str);
965 GNUNET_SCHEDULER_add_now (&do_error, handle);
966 return;
967 }
968 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
969 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
970 &key);
971 if ( GNUNET_NO ==
972 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
973 &key) )
974 {
975 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
976 "Missing issuer attribute\n");
977 GNUNET_SCHEDULER_add_now (&do_error, handle);
978 return;
979 }
980 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
981 (handle->rest_handle->url_param_map,
982 &key));
983 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
984 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
985 &key);
986 if ( GNUNET_NO ==
987 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
988 &key) )
989 {
990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
991 "Missing subject\n");
992 GNUNET_SCHEDULER_add_now (&do_error, handle);
993 return;
994 }
995 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
996 &key);
997 if (NULL == tmp)
998 {
999 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1000 "Malformed subject\n");
1001 GNUNET_SCHEDULER_add_now (&do_error, handle);
1002 return;
1003 }
1004 if (GNUNET_OK !=
1005 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1006 strlen (tmp),
1007 &handle->subject_key)) {
1008 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1009 "Malformed subject key\n");
1010 GNUNET_SCHEDULER_add_now (&do_error, handle);
1011 return;
1012 }
1013 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1014 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1015 &handle->subject_key,
1016 handle->issuer_attr,
1017 &etime_abs);
1018 if (NULL == cred)
1019 {
1020 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1021 "Failed to create credential\n");
1022 GNUNET_SCHEDULER_add_now (&do_error, handle);
1023 return;
1024 }
1025 send_cred_response (handle, cred);
1026}
1027
1028
1029static void
1030issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1031 const char* url,
1032 void *cls)
1033{
1034 struct RequestHandle *handle = cls;
1035
1036 handle->identity = GNUNET_IDENTITY_connect (cfg,
1037 NULL,
1038 NULL);
1039 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1040 "credential-issuer",
1041 &get_cred_issuer_cb,
1042 handle);
1043 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1044 &do_error,
1045 handle);
1046}
1047
1048static void
1049options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1050 const char* url,
1051 void *cls)
1052{
1053 struct MHD_Response *resp;
1054 struct RequestHandle *handle = cls;
1055
1056 //For GNS, independent of path return all options
1057 resp = GNUNET_REST_create_response (NULL);
1058 MHD_add_response_header (resp,
1059 "Access-Control-Allow-Methods",
1060 MHD_HTTP_METHOD_GET);
1061 handle->proc (handle->proc_cls,
1062 resp,
1063 MHD_HTTP_OK);
1064 cleanup_handle (handle);
1065}
1066
1067
1068static void
1069rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1070 GNUNET_REST_ResultProcessor proc,
1071 void *proc_cls)
1072{
1073 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1074 struct GNUNET_REST_RequestHandlerError err;
1075
1076 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1077 handle->proc_cls = proc_cls;
1078 handle->proc = proc;
1079 handle->rest_handle = conndata_handle;
1080
1081 static const struct GNUNET_REST_RequestHandler handlers[] = {
1082 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1083 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1084 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1085 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1086 GNUNET_REST_HANDLER_END
1087 };
1088
1089 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1090 handlers,
1091 &err,
1092 handle))
1093 {
1094 handle->response_code = err.error_code;
1095 GNUNET_SCHEDULER_add_now (&do_error, handle);
1096 }
1097}
1098
1099
1100/**
1101 * Entry point for the plugin.
1102 *
1103 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1104 * @return NULL on error, otherwise the plugin context
1105 */
1106void *
1107libgnunet_plugin_rest_credential_init (void *cls)
1108{
1109 static struct Plugin plugin;
1110 cfg = cls;
1111 struct GNUNET_REST_Plugin *api;
1112
1113 if (NULL != plugin.cfg)
1114 return NULL; /* can only initialize once! */
1115 memset (&plugin, 0, sizeof (struct Plugin));
1116 plugin.cfg = cfg;
1117 api = GNUNET_new (struct GNUNET_REST_Plugin);
1118 api->cls = &plugin;
1119 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1120 api->process_request = &rest_credential_process_request;
1121 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1122 _("GNS REST API initialized\n"));
1123 return api;
1124}
1125
1126
1127/**
1128 * Exit point from the plugin.
1129 *
1130 * @param cls the plugin context (as returned by "init")
1131 * @return always NULL
1132 */
1133void *
1134libgnunet_plugin_rest_credential_done (void *cls)
1135{
1136 struct GNUNET_REST_Plugin *api = cls;
1137 struct Plugin *plugin = api->cls;
1138
1139 plugin->cfg = NULL;
1140 GNUNET_free (api);
1141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1142 "GNS REST plugin is finished\n");
1143 return NULL;
1144}
1145
1146/* end of plugin_rest_gns.c */
diff --git a/src/credential/test_credential_collect.sh b/src/credential/test_credential_collect.sh
new file mode 100755
index 000000000..6c713063f
--- /dev/null
+++ b/src/credential/test_credential_collect.sh
@@ -0,0 +1,47 @@
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"
26TEST_ATTR2="test2"
27gnunet-arm -s -c test_credential_lookup.conf
28gnunet-identity -C testissuer -c test_credential_lookup.conf
29gnunet-identity -C testsubject -c test_credential_lookup.conf
30SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
31ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
32#TODO1 Get credential and store it with subject (3)
33CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
34$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
35CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c test_credential_lookup.conf`
36$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
37CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste -d, -s`
38echo $CREDS
39RES=$?
40gnunet-arm -e -c test_credential_lookup.conf
41
42if test $? != 0
43then
44 echo "Error collecting..."
45 exit 1
46fi
47
diff --git a/src/credential/test_credential_collect_rest.sh b/src/credential/test_credential_collect_rest.sh
new file mode 100755
index 000000000..0b31f85bc
--- /dev/null
+++ b/src/credential/test_credential_collect_rest.sh
@@ -0,0 +1,90 @@
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# (5) GNUnet issues Alice the credential "developer"
61CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
62
63# Alice stores the credential under "mygnunetcreds"
64gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
65
66#TODO2 Add -z swich like in gnunet-gns
67#RES_CRED=`gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY -c test_credential_lookup.conf`
68
69gnunet-arm -i rest -c test_credential_lookup.conf
70
71sleep 5
72
73curl -v "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"
74
75#TODO cleanup properly
76gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
77gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
78gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
79gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
80echo "Stopping arm..."
81gnunet-arm -e -c test_credential_lookup.conf
82echo "Done"
83if [ "$RES_CRED" != "Failed." ]
84then
85 echo -e "${RES_CRED}"
86 exit 0
87else
88 echo "FAIL: Failed to verify credential $RES_CRED."
89 exit 1
90fi
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_issue_rest.sh b/src/credential/test_credential_issue_rest.sh
new file mode 100755
index 000000000..15cd55083
--- /dev/null
+++ b/src/credential/test_credential_issue_rest.sh
@@ -0,0 +1,53 @@
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-arm -i gns
28gnunet-arm -i credential
29gnunet-arm -i identity
30gnunet-arm -i rest -c test_credential_lookup.conf
31
32gnunet-arm -I -c test_credential_lookup.conf
33gnunet-identity -C testissuer -c test_credential_lookup.conf
34gnunet-identity -C testsubject -c test_credential_lookup.conf
35gnunet-identity -s credential-issuer -e testissuer
36SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
37ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
38#TODO1 Get credential and store it with subject (3)
39sleep 5
40curl "localhost:7776/credential/issue?subject_key=$SUBJECT_KEY&attribute=$TEST_ATTR&expiration=1d"
41#CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
42STATUS=$?
43
44if test $? != 0
45then
46 echo "Error issuing..."
47 exit 1
48fi
49#Try import
50#$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
51RES=$?
52gnunet-arm -e -c test_credential_lookup.conf
53exit $RES
diff --git a/src/credential/test_credential_lookup.conf b/src/credential/test_credential_lookup.conf
new file mode 100644
index 000000000..3684063b1
--- /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
14PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
15
16[rest]
17PREFIX = 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..d042bcfe6
--- /dev/null
+++ b/src/credential/test_credential_verify.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" -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
60CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
61
62echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf
63#TODO2 Add -z swich like in gnunet-gns
64gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -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_and.sh b/src/credential/test_credential_verify_and.sh
new file mode 100755
index 000000000..9d5c1962e
--- /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# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED1" -e 5m -c test_credential_lookup.conf
59gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m -c test_credential_lookup.conf
60
61CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
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="$CREDS" -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..6133ea25e
--- /dev/null
+++ b/src/credential/test_credential_verify_rest.sh
@@ -0,0 +1,87 @@
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
61#RES_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
67CREDS=`curl "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"`
68
69echo $CREDS
70
71curl -v "localhost:7776/credential/verify?attribute=$SERVICE_KEY.$USER_ATTR&subject_key=$ALICE_KEY" --data "$CREDS"
72
73#TODO cleanup properly
74gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
75gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
76gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
77gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
78gnunet-arm -e -c test_credential_lookup.conf
79
80if [ "$RES_CRED" != "Failed." ]
81then
82 echo -e "${RES_CRED}"
83 exit 0
84else
85 echo "FAIL: Failed to verify credential $RES_CRED."
86 exit 1
87fi
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