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.c513
-rw-r--r--src/credential/credential_misc.c169
-rw-r--r--src/credential/credential_misc.h35
-rw-r--r--src/credential/credential_serialization.c463
-rw-r--r--src/credential/credential_serialization.h159
-rw-r--r--src/credential/gnunet-credential.c587
-rw-r--r--src/credential/gnunet-service-credential.c1240
-rw-r--r--src/credential/plugin_gnsrecord_credential.c342
-rw-r--r--src/credential/plugin_rest_credential.c1179
-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, 5610 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..f16249c1b
--- /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 Adnan Husain
24 */
25#ifndef CREDENTIAL_H
26#define CREDENTIAL_H
27
28#include "gnunet_credential_service.h"
29
30GNUNET_NETWORK_STRUCT_BEGIN
31
32/**
33 * Message from client to Credential service to 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..f90bf9630
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,513 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file credential/credential_api.c
22 * @brief library to access the CREDENTIAL service
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_constants.h"
28#include "gnunet_arm_service.h"
29#include "gnunet_hello_lib.h"
30#include "gnunet_protocols.h"
31#include "gnunet_signatures.h"
32#include "credential.h"
33#include "credential_serialization.h"
34#include "gnunet_credential_service.h"
35#include "gnunet_identity_service.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
39
40/**
41 * Handle to a verify request
42 */
43struct GNUNET_CREDENTIAL_Request
44{
45
46 /**
47 * DLL
48 */
49 struct GNUNET_CREDENTIAL_Request *next;
50
51 /**
52 * DLL
53 */
54 struct GNUNET_CREDENTIAL_Request *prev;
55
56 /**
57 * handle to credential service
58 */
59 struct GNUNET_CREDENTIAL_Handle *credential_handle;
60
61 /**
62 * processor to call on verify result
63 */
64 GNUNET_CREDENTIAL_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 loookup_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 loookup_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_verify_cancel (struct GNUNET_CREDENTIAL_Request *vr)
352{
353 struct GNUNET_CREDENTIAL_Handle *handle = vr->credential_handle;
354
355 GNUNET_CONTAINER_DLL_remove (handle->request_head,
356 handle->request_tail,
357 vr);
358 GNUNET_MQ_discard (vr->env);
359 GNUNET_free (vr);
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 credential_count number of credentials provided
373 * @param credentials subject credentials
374 * @param proc function to call on result
375 * @param proc_cls closure for processor
376 * @return handle to the queued request
377 */
378struct GNUNET_CREDENTIAL_Request*
379GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
380 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
381 const char *issuer_attribute,
382 const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
383 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
384 void *proc_cls)
385{
386 /* IPC to shorten credential names, return shorten_handle */
387 struct CollectMessage *c_msg;
388 struct GNUNET_CREDENTIAL_Request *vr;
389 size_t nlen;
390
391 if (NULL == issuer_attribute)
392 {
393 GNUNET_break (0);
394 return NULL;
395 }
396
397 //DEBUG LOG
398 LOG (GNUNET_ERROR_TYPE_DEBUG,
399 "Trying to collect `%s' in CREDENTIAL\n",
400 issuer_attribute);
401 nlen = strlen (issuer_attribute) + 1;
402 if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*vr))
403 {
404 GNUNET_break (0);
405 return NULL;
406 }
407 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
408 vr->credential_handle = handle;
409 vr->verify_proc = proc;
410 vr->proc_cls = proc_cls;
411 vr->r_id = handle->r_id_gen++;
412 vr->env = GNUNET_MQ_msg_extra (c_msg,
413 nlen,
414 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT);
415 c_msg->id = htonl (vr->r_id);
416 c_msg->subject_key = *subject_key;
417 c_msg->issuer_key = *issuer_key;
418 c_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
419 GNUNET_memcpy (&c_msg[1],
420 issuer_attribute,
421 strlen (issuer_attribute));
422 GNUNET_CONTAINER_DLL_insert (handle->request_head,
423 handle->request_tail,
424 vr);
425 if (NULL != handle->mq)
426 GNUNET_MQ_send_copy (handle->mq,
427 vr->env);
428 return vr;
429}
430/**
431 * Performs attribute verification.
432 * Checks if there is a delegation chain from
433 * attribute ``issuer_attribute'' issued by the issuer
434 * with public key ``issuer_key'' maps to the attribute
435 * ``subject_attribute'' claimed by the subject with key
436 * ``subject_key''
437 *
438 * @param handle handle to the Credential service
439 * @param issuer_key the issuer public key
440 * @param issuer_attribute the issuer attribute
441 * @param subject_key the subject public key
442 * @param credential_count number of credentials provided
443 * @param credentials subject credentials
444 * @param proc function to call on result
445 * @param proc_cls closure for processor
446 * @return handle to the queued request
447 */
448struct GNUNET_CREDENTIAL_Request*
449GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
450 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
451 const char *issuer_attribute,
452 const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
453 uint32_t credential_count,
454 const struct GNUNET_CREDENTIAL_Credential *credentials,
455 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
456 void *proc_cls)
457{
458 /* IPC to shorten credential names, return shorten_handle */
459 struct VerifyMessage *v_msg;
460 struct GNUNET_CREDENTIAL_Request *vr;
461 size_t nlen;
462 size_t clen;
463
464 if (NULL == issuer_attribute || NULL == credentials)
465 {
466 GNUNET_break (0);
467 return NULL;
468 }
469
470 clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
471 credentials);
472
473 //DEBUG LOG
474 LOG (GNUNET_ERROR_TYPE_DEBUG,
475 "Trying to verify `%s' in CREDENTIAL\n",
476 issuer_attribute);
477 nlen = strlen (issuer_attribute) + 1 + clen;
478 if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*vr))
479 {
480 GNUNET_break (0);
481 return NULL;
482 }
483 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
484 vr->credential_handle = handle;
485 vr->verify_proc = proc;
486 vr->proc_cls = proc_cls;
487 vr->r_id = handle->r_id_gen++;
488 vr->env = GNUNET_MQ_msg_extra (v_msg,
489 nlen,
490 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
491 v_msg->id = htonl (vr->r_id);
492 v_msg->subject_key = *subject_key;
493 v_msg->c_count = htonl(credential_count);
494 v_msg->issuer_key = *issuer_key;
495 v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
496 GNUNET_memcpy (&v_msg[1],
497 issuer_attribute,
498 strlen (issuer_attribute));
499 GNUNET_CREDENTIAL_credentials_serialize (credential_count,
500 credentials,
501 clen,
502 ((char*)&v_msg[1])
503 + strlen (issuer_attribute) + 1);
504 GNUNET_CONTAINER_DLL_insert (handle->request_head,
505 handle->request_tail,
506 vr);
507 if (NULL != handle->mq)
508 GNUNET_MQ_send_copy (handle->mq,
509 vr->env);
510 return vr;
511}
512
513/* 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..7849e81e6
--- /dev/null
+++ b/src/credential/credential_misc.c
@@ -0,0 +1,169 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_mic.c
24 * @brief Misc API for credentials
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34#include <inttypes.h>
35
36char*
37GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred)
38{
39 char *cred_str;
40 char *subject_pkey;
41 char *issuer_pkey;
42 char *signature;
43
44
45 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
46 issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
47 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
48 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
49 &signature);
50 GNUNET_asprintf (&cred_str,
51 "%s.%s -> %s | %s | %"SCNu64,
52 issuer_pkey,
53 cred->issuer_attribute,
54 subject_pkey,
55 signature,
56 cred->expiration.abs_value_us);
57 GNUNET_free (subject_pkey);
58 GNUNET_free (issuer_pkey);
59 GNUNET_free (signature);
60 return cred_str;
61}
62
63struct GNUNET_CREDENTIAL_Credential*
64GNUNET_CREDENTIAL_credential_from_string (const char* s)
65{
66 struct GNUNET_CREDENTIAL_Credential *cred;
67 size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
68 if (enclen % 5 > 0)
69 enclen += 5 - enclen % 5;
70 enclen /= 5; /* 260/5 = 52 */
71 char subject_pkey[enclen + 1];
72 char issuer_pkey[enclen + 1];
73 char name[253 + 1];
74 char signature[256]; //TODO max payload size
75
76 struct GNUNET_CRYPTO_EcdsaSignature *sig;
77 struct GNUNET_TIME_Absolute etime_abs;
78
79 if (5 != SSCANF (s,
80 "%52s.%253s -> %52s | %s | %"SCNu64,
81 issuer_pkey,
82 name,
83 subject_pkey,
84 signature,
85 &etime_abs.abs_value_us))
86 {
87 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
88 _("Unable to parse CRED record string `%s'\n"),
89 s);
90 return NULL;
91 }
92 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1);
93 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
94 strlen (subject_pkey),
95 &cred->subject_key);
96 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
97 strlen (issuer_pkey),
98 &cred->issuer_key);
99 GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature,
100 strlen (signature),
101 (char**)&sig));
102 cred->signature = *sig;
103 cred->expiration = etime_abs;
104 GNUNET_free (sig);
105 GNUNET_memcpy (&cred[1],
106 name,
107 strlen (name)+1);
108 cred->issuer_attribute_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 handle handle to the Credential service
117 * @param issuer the ego that should be used to issue the attribute
118 * @param subject the subject of the attribute
119 * @param attribute the name of the attribute
120 * @return handle to the queued request
121 */
122struct GNUNET_CREDENTIAL_Credential *
123GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
124 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
125 const char *attribute,
126 struct GNUNET_TIME_Absolute *expiration)
127{
128 struct CredentialEntry *crd;
129 struct GNUNET_CREDENTIAL_Credential *cred;
130 size_t size;
131
132 size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
133 crd = GNUNET_malloc (size);
134 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1);
135 crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
136
137 crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
138 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
139 &crd->issuer_key);
140 crd->subject_key = *subject;
141 crd->expiration = GNUNET_htonll (expiration->abs_value_us);
142 crd->issuer_attribute_len = htonl (strlen (attribute)+1);
143 GNUNET_memcpy ((char*)&crd[1],
144 attribute,
145 strlen (attribute)+1);
146 if (GNUNET_OK !=
147 GNUNET_CRYPTO_ecdsa_sign (issuer,
148 &crd->purpose,
149 &crd->signature))
150 {
151 GNUNET_break (0);
152 GNUNET_free (crd);
153 return NULL;
154 }
155 cred->signature = crd->signature;
156 cred->expiration = *expiration;
157 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
158 &cred->issuer_key);
159
160 cred->subject_key = *subject;
161 GNUNET_memcpy (&cred[1],
162 attribute,
163 strlen (attribute)+1);
164 cred->issuer_attribute = (char*)&cred[1];
165 GNUNET_free (crd);
166 return cred;
167}
168
169
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..1fc72c203
--- /dev/null
+++ b/src/credential/credential_serialization.c
@@ -0,0 +1,463 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_serialization.c
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34
35/**
36 * Calculate how many bytes we will need to serialize
37 * the given delegation chain and credential
38 *
39 * @param d_count number of delegation chain entries
40 * @param dd array of #GNUNET_CREDENTIAL_Delegation
41 * @param cd a #GNUNET_CREDENTIAL_Credential
42 * @return the required size to serialize
43 */
44size_t
45GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
46 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
47{
48 unsigned int i;
49 size_t ret;
50
51 ret = sizeof (struct DelegationRecordData) * (ds_count);
52
53 for (i=0; i<ds_count;i++)
54 {
55 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
56 ret += dsr[i].subject_attribute_len;
57 }
58 return ret;
59}
60
61/**
62 * Serizalize the given delegation chain entries and credential
63 *
64 * @param d_count number of delegation chain entries
65 * @param dd array of #GNUNET_CREDENTIAL_Delegation
66 * @param cd a #GNUNET_CREDENTIAL_Credential
67 * @param dest_size size of the destination
68 * @param dest where to store the result
69 * @return the size of the data, -1 on failure
70 */
71ssize_t
72GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
73 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
74 size_t dest_size,
75 char *dest)
76{
77 struct DelegationRecordData rec;
78 unsigned int i;
79 size_t off;
80
81 off = 0;
82 for (i=0;i<d_count;i++)
83 {
84 rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
85 rec.subject_key = dsr[i].subject_key;
86 if (off + sizeof (rec) > dest_size)
87 return -1;
88 GNUNET_memcpy (&dest[off],
89 &rec,
90 sizeof (rec));
91 off += sizeof (rec);
92 if (0 == dsr[i].subject_attribute_len)
93 continue;
94 if (off + dsr[i].subject_attribute_len > dest_size)
95 return -1;
96 GNUNET_memcpy (&dest[off],
97 dsr[i].subject_attribute,
98 dsr[i].subject_attribute_len);
99 off += dsr[i].subject_attribute_len;
100 }
101 return off;
102}
103
104
105/**
106 * Deserialize the given destination
107 *
108 * @param len size of the serialized delegation chain and cred
109 * @param src the serialized data
110 * @param d_count the number of delegation chain entries
111 * @param dd where to put the delegation chain entries
112 * @param cd where to put the credential data
113 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
114 */
115int
116GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
117 const char *src,
118 unsigned int d_count,
119 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
120{
121 struct DelegationRecordData rec;
122 unsigned int i;
123 size_t off;
124
125 off = 0;
126 for (i=0;i<d_count;i++)
127 {
128 if (off + sizeof (rec) > len)
129 return GNUNET_SYSERR;
130 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
131 dsr[i].subject_key = rec.subject_key;
132 off += sizeof (rec);
133 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
134 if (off + dsr[i].subject_attribute_len > len)
135 return GNUNET_SYSERR;
136 dsr[i].subject_attribute = (char*)&src[off];
137 off += dsr[i].subject_attribute_len;
138 }
139 return GNUNET_OK;
140}
141
142
143/**
144 * Calculate how many bytes we will need to serialize
145 * the credentials
146 *
147 * @param c_count number of credential entries
148 * @param cd a #GNUNET_CREDENTIAL_Credential
149 * @return the required size to serialize
150 */
151size_t
152GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
153 const struct GNUNET_CREDENTIAL_Credential *cd)
154{
155 unsigned int i;
156 size_t ret;
157
158 ret = sizeof (struct CredentialEntry) * (c_count);
159
160 for (i=0; i<c_count;i++)
161 {
162 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
163 ret += cd[i].issuer_attribute_len;
164 }
165 return ret;
166}
167/**
168 * Serizalize the given credentials
169 *
170 * @param c_count number of credential entries
171 * @param cd a #GNUNET_CREDENTIAL_Credential
172 * @param dest_size size of the destination
173 * @param dest where to store the result
174 * @return the size of the data, -1 on failure
175 */
176ssize_t
177GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
178 const struct GNUNET_CREDENTIAL_Credential *cd,
179 size_t dest_size,
180 char *dest)
181{
182 struct CredentialEntry c_rec;
183 unsigned int i;
184 size_t off;
185
186 off = 0;
187 for (i=0;i<c_count;i++)
188 {
189 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
190 c_rec.issuer_key = cd[i].issuer_key;
191 c_rec.subject_key = cd[i].subject_key;
192 c_rec.signature = cd[i].signature;
193 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
194 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
195 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
196 if (off + sizeof (c_rec) > dest_size)
197 return -1;
198 GNUNET_memcpy (&dest[off],
199 &c_rec,
200 sizeof (c_rec));
201 off += sizeof (c_rec);
202 if (off + cd[i].issuer_attribute_len > dest_size)
203 return -1;
204 GNUNET_memcpy (&dest[off],
205 cd[i].issuer_attribute,
206 cd[i].issuer_attribute_len);
207 off += cd[i].issuer_attribute_len;
208 }
209
210 return off;
211}
212
213
214
215/**
216 * Deserialize the given destination
217 *
218 * @param len size of the serialized creds
219 * @param src the serialized data
220 * @param c_count the number of credential entries
221 * @param cd where to put the credential data
222 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
223 */
224int
225GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
226 const char *src,
227 unsigned int c_count,
228 struct GNUNET_CREDENTIAL_Credential *cd)
229{
230 struct CredentialEntry c_rec;
231 unsigned int i;
232 size_t off;
233
234 off = 0;
235 for (i=0;i<c_count;i++)
236 {
237 if (off + sizeof (c_rec) > len)
238 return GNUNET_SYSERR;
239 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
240 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
241 cd[i].issuer_key = c_rec.issuer_key;
242 cd[i].subject_key = c_rec.subject_key;
243 cd[i].signature = c_rec.signature;
244 cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
245 off += sizeof (c_rec);
246 if (off + cd[i].issuer_attribute_len > len)
247 return GNUNET_SYSERR;
248 cd[i].issuer_attribute = &src[off];
249 off += cd[i].issuer_attribute_len;
250 }
251 return GNUNET_OK;
252}
253
254
255
256/**
257 * Calculate how many bytes we will need to serialize
258 * the given delegation chain and credential
259 *
260 * @param d_count number of delegation chain entries
261 * @param dd array of #GNUNET_CREDENTIAL_Delegation
262 * @param c_count number of credential entries
263 * @param cd a #GNUNET_CREDENTIAL_Credential
264 * @return the required size to serialize
265 */
266size_t
267GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
268 const struct GNUNET_CREDENTIAL_Delegation *dd,
269 unsigned int c_count,
270 const struct GNUNET_CREDENTIAL_Credential *cd)
271{
272 unsigned int i;
273 size_t ret;
274
275 ret = sizeof (struct ChainEntry) * (d_count);
276
277 for (i=0; i<d_count;i++)
278 {
279 GNUNET_assert ((ret +
280 dd[i].issuer_attribute_len +
281 dd[i].subject_attribute_len) >= ret);
282 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
283 }
284 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
285 return ret;
286}
287
288/**
289 * Serizalize the given delegation chain entries and credential
290 *
291 * @param d_count number of delegation chain entries
292 * @param dd array of #GNUNET_CREDENTIAL_Delegation
293 * @param c_count number of credential entries
294 * @param cd a #GNUNET_CREDENTIAL_Credential
295 * @param dest_size size of the destination
296 * @param dest where to store the result
297 * @return the size of the data, -1 on failure
298 */
299ssize_t
300GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
301 const struct GNUNET_CREDENTIAL_Delegation *dd,
302 unsigned int c_count,
303 const struct GNUNET_CREDENTIAL_Credential *cd,
304 size_t dest_size,
305 char *dest)
306{
307 struct ChainEntry rec;
308 unsigned int i;
309 size_t off;
310
311 off = 0;
312 for (i=0;i<d_count;i++)
313 {
314 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
315 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
316 rec.issuer_key = dd[i].issuer_key;
317 rec.subject_key = dd[i].subject_key;
318 if (off + sizeof (rec) > dest_size)
319 return -1;
320 GNUNET_memcpy (&dest[off],
321 &rec,
322 sizeof (rec));
323 off += sizeof (rec);
324 if (off + dd[i].issuer_attribute_len > dest_size)
325 return -1;
326 GNUNET_memcpy (&dest[off],
327 dd[i].issuer_attribute,
328 dd[i].issuer_attribute_len);
329 off += dd[i].issuer_attribute_len;
330 if (0 == dd[i].subject_attribute_len)
331 continue;
332 if (off + dd[i].subject_attribute_len > dest_size)
333 return -1;
334 GNUNET_memcpy (&dest[off],
335 dd[i].subject_attribute,
336 dd[i].subject_attribute_len);
337 off += dd[i].subject_attribute_len;
338 }
339 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
340 cd,
341 dest_size-off,
342 &dest[off]);
343}
344
345
346/**
347 * Deserialize the given destination
348 *
349 * @param len size of the serialized delegation chain and cred
350 * @param src the serialized data
351 * @param d_count the number of delegation chain entries
352 * @param dd where to put the delegation chain entries
353 * @param c_count the number of credential entries
354 * @param cd where to put the credential data
355 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
356 */
357int
358GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
359 const char *src,
360 unsigned int d_count,
361 struct GNUNET_CREDENTIAL_Delegation *dd,
362 unsigned int c_count,
363 struct GNUNET_CREDENTIAL_Credential *cd)
364{
365 struct ChainEntry rec;
366 unsigned int i;
367 size_t off;
368
369 off = 0;
370 for (i=0;i<d_count;i++)
371 {
372 if (off + sizeof (rec) > len)
373 return GNUNET_SYSERR;
374 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
375 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
376 dd[i].issuer_key = rec.issuer_key;
377 dd[i].subject_key = rec.subject_key;
378 off += sizeof (rec);
379 if (off + dd[i].issuer_attribute_len > len)
380 return GNUNET_SYSERR;
381 dd[i].issuer_attribute = &src[off];
382 off += dd[i].issuer_attribute_len;
383 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
384 if (off + dd[i].subject_attribute_len > len)
385 return GNUNET_SYSERR;
386 dd[i].subject_attribute = &src[off];
387 off += dd[i].subject_attribute_len;
388 }
389 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
390 &src[off],
391 c_count,
392 cd);
393}
394int
395GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
396 char **data)
397{
398 size_t size;
399 struct CredentialEntry *cdata;
400
401 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
402 *data = GNUNET_malloc (size);
403 cdata = (struct CredentialEntry*)*data;
404 cdata->subject_key = cred->subject_key;
405 cdata->issuer_key = cred->issuer_key;
406 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
407 cdata->signature = cred->signature;
408 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
409 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
410 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
411 GNUNET_memcpy (&cdata[1],
412 cred->issuer_attribute,
413 strlen (cred->issuer_attribute));
414
415 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
416 &cdata->purpose,
417 &cdata->signature,
418 &cdata->issuer_key))
419 {
420 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
421 "Invalid credential\n");
422 //return NULL;
423 }
424 return size;
425}
426
427struct GNUNET_CREDENTIAL_Credential*
428GNUNET_CREDENTIAL_credential_deserialize (const char* data,
429 size_t data_size)
430{
431 struct GNUNET_CREDENTIAL_Credential *cred;
432 struct CredentialEntry *cdata;
433 char *issuer_attribute;
434
435 if (data_size < sizeof (struct CredentialEntry))
436 return NULL;
437 cdata = (struct CredentialEntry*)data;
438 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
439 &cdata->purpose,
440 &cdata->signature,
441 &cdata->issuer_key))
442 {
443 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
444 "Invalid credential\n");
445 //return NULL;
446 }
447 issuer_attribute = (char*)&cdata[1];
448
449 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
450
451 cred->issuer_key = cdata->issuer_key;
452 cred->subject_key = cdata->subject_key;
453 GNUNET_memcpy (&cred[1],
454 issuer_attribute,
455 ntohl (cdata->issuer_attribute_len));
456 cred->signature = cdata->signature;
457 cred->issuer_attribute = (char*)&cred[1];
458 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
459 return cred;
460}
461
462
463/* 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..fb7bdb7f8
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,587 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file gnunet-credential.c
22 * @brief command line tool to access command line Credential service
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include <gnunet_util_lib.h>
27#include <gnunet_credential_service.h>
28#include <gnunet_gnsrecord_lib.h>
29#include "credential_misc.h"
30#include "credential_serialization.h"
31
32/**
33 * Configuration we are using.
34 */
35static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37/**
38 * EgoLookup
39 */
40static struct GNUNET_IDENTITY_EgoLookup *el;
41
42/**
43 * Handle to Credential service.
44 */
45static struct GNUNET_CREDENTIAL_Handle *credential;
46
47/**
48 * Desired timeout for the lookup (default is no timeout).
49 */
50static struct GNUNET_TIME_Relative timeout;
51
52/**
53 * Handle to verify request
54 */
55static struct GNUNET_CREDENTIAL_Request *verify_request;
56
57/**
58 * 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 uint32_t verify;
112
113/**
114 * Issue mode
115 */
116static uint32_t create_cred;
117
118/**
119 * Collect mode
120 */
121static uint32_t 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_verify_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
161/**
162 * Function called with the result of a Credential lookup.
163 *
164 * @param cls the 'const char *' name that was resolved
165 * @param cd_count number of records returned
166 * @param cd array of @a cd_count records with the results
167 */
168static void
169handle_collect_result (void *cls,
170 unsigned int d_count,
171 struct GNUNET_CREDENTIAL_Delegation *dc,
172 unsigned int c_count,
173 struct GNUNET_CREDENTIAL_Credential *cred)
174{
175 int i;
176 char* line;
177
178 verify_request = NULL;
179 if (NULL != cred)
180 {
181 for (i=0;i<c_count;i++)
182 {
183 line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
184 printf ("%s\n",
185 line);
186 GNUNET_free (line);
187 }
188 }
189
190
191 GNUNET_SCHEDULER_shutdown ();
192}
193
194
195/**
196 * Function called with the result of a Credential lookup.
197 *
198 * @param cls the 'const char *' name that was resolved
199 * @param cd_count number of records returned
200 * @param cd array of @a cd_count records with the results
201 */
202static void
203handle_verify_result (void *cls,
204 unsigned int d_count,
205 struct GNUNET_CREDENTIAL_Delegation *dc,
206 unsigned int c_count,
207 struct GNUNET_CREDENTIAL_Credential *cred)
208{
209 int i;
210 char* iss_key;
211 char* sub_key;
212
213 verify_request = NULL;
214 if (NULL == cred)
215 printf ("Failed.\n");
216 else
217 {
218 printf("Delegation Chain:\n");
219 for (i=0;i<d_count;i++)
220 {
221 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
222 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
223 if (0 != dc[i].subject_attribute_len)
224 {
225 printf ("(%d) %s.%s <- %s.%s\n", i,
226 iss_key, dc[i].issuer_attribute,
227 sub_key, dc[i].subject_attribute);
228 } else {
229 printf ("(%d) %s.%s <- %s\n", i,
230 iss_key, dc[i].issuer_attribute,
231 sub_key);
232 }
233 GNUNET_free (iss_key);
234 GNUNET_free (sub_key);
235 }
236 printf("\nCredentials:\n");
237 for (i=0;i<c_count;i++)
238 {
239 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
240 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
241 printf ("%s.%s <- %s\n",
242 iss_key, cred[i].issuer_attribute,
243 sub_key);
244 GNUNET_free (iss_key);
245 GNUNET_free (sub_key);
246
247 }
248 printf ("Successful.\n");
249 }
250
251
252 GNUNET_SCHEDULER_shutdown ();
253}
254
255/**
256 * Callback invoked from identity service with ego information.
257 * An @a ego of NULL means the ego was not found.
258 *
259 * @param cls closure with the configuration
260 * @param ego an ego known to identity service, or NULL
261 */
262static void
263identity_cb (void *cls,
264 const struct GNUNET_IDENTITY_Ego *ego)
265{
266 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
267 struct GNUNET_CREDENTIAL_Credential *crd;
268 struct GNUNET_TIME_Absolute etime_abs;
269 struct GNUNET_TIME_Relative etime_rel;
270 char *res;
271
272 el = NULL;
273 if (NULL == ego)
274 {
275 if (NULL != ego_name)
276 {
277 fprintf (stderr,
278 _("Ego `%s' not known to identity service\n"),
279 ego_name);
280 }
281 GNUNET_SCHEDULER_shutdown ();
282 return;
283 }
284
285 if (GNUNET_YES == collect)
286 {
287
288 if (GNUNET_OK !=
289 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
290 strlen (issuer_key),
291 &issuer_pkey))
292 {
293 fprintf (stderr,
294 _("Issuer public key `%s' is not well-formed\n"),
295 issuer_key);
296 GNUNET_SCHEDULER_shutdown ();
297 }
298 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
299
300 collect_request = GNUNET_CREDENTIAL_collect(credential,
301 &issuer_pkey,
302 issuer_attr, //TODO argument
303 privkey,
304 &handle_collect_result,
305 NULL);
306 return;
307 }
308
309 //Else issue
310
311 if (NULL == expiration)
312 {
313 fprintf (stderr,
314 "Please specify a TTL\n");
315 GNUNET_SCHEDULER_shutdown ();
316 return;
317 } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
318 &etime_rel))
319 {
320 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
321 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
322 &etime_abs))
323 {
324 fprintf (stderr,
325 "%s is not a valid ttl!\n",
326 expiration);
327 GNUNET_SCHEDULER_shutdown ();
328 return;
329 }
330
331
332 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
333 GNUNET_free_non_null (ego_name);
334 ego_name = NULL;
335 crd = GNUNET_CREDENTIAL_credential_issue (privkey,
336 &subject_pkey,
337 issuer_attr,
338 &etime_abs);
339
340 res = GNUNET_CREDENTIAL_credential_to_string (crd);
341 GNUNET_free (crd);
342 printf ("%s\n", res);
343 GNUNET_SCHEDULER_shutdown ();
344}
345
346
347
348
349/**
350 * Main function that will be run.
351 *
352 * @param cls closure
353 * @param args remaining command-line arguments
354 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
355 * @param c configuration
356 */
357static void
358run (void *cls,
359 char *const *args,
360 const char *cfgfile,
361 const struct GNUNET_CONFIGURATION_Handle *c)
362{
363
364 cfg = c;
365
366
367 tt = GNUNET_SCHEDULER_add_delayed (timeout,
368 &do_timeout, NULL);
369 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
370
371 if (GNUNET_YES == collect) {
372 if (NULL == issuer_key)
373 {
374 fprintf (stderr,
375 _("Issuer public key not well-formed\n"));
376 GNUNET_SCHEDULER_shutdown ();
377 return;
378
379 }
380
381 credential = GNUNET_CREDENTIAL_connect (cfg);
382
383 if (NULL == credential)
384 {
385 fprintf (stderr,
386 _("Failed to connect to CREDENTIAL\n"));
387 GNUNET_SCHEDULER_shutdown ();
388 }
389 if (NULL == issuer_attr)
390 {
391 fprintf (stderr,
392 _("You must provide issuer the attribute\n"));
393 GNUNET_SCHEDULER_shutdown ();
394 }
395
396 if (NULL == ego_name)
397 {
398 fprintf (stderr,
399 _("ego required\n"));
400 GNUNET_SCHEDULER_shutdown ();
401 return;
402
403 }
404 el = GNUNET_IDENTITY_ego_lookup (cfg,
405 ego_name,
406 &identity_cb,
407 (void *) cfg);
408 return;
409
410 }
411
412 if (NULL == subject_key)
413 {
414 fprintf (stderr,
415 _("Subject public key needed\n"));
416 GNUNET_SCHEDULER_shutdown ();
417 return;
418
419 }
420 if (GNUNET_OK !=
421 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
422 strlen (subject_key),
423 &subject_pkey))
424 {
425 fprintf (stderr,
426 _("Subject public key `%s' is not well-formed\n"),
427 subject_key);
428 GNUNET_SCHEDULER_shutdown ();
429 return;
430 }
431 if (GNUNET_YES == verify) {
432 if (NULL == issuer_key)
433 {
434 fprintf (stderr,
435 _("Issuer public key not well-formed\n"));
436 GNUNET_SCHEDULER_shutdown ();
437 return;
438
439 }
440 if (GNUNET_OK !=
441 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
442 strlen (issuer_key),
443 &issuer_pkey))
444 {
445 fprintf (stderr,
446 _("Issuer public key `%s' is not well-formed\n"),
447 issuer_key);
448 GNUNET_SCHEDULER_shutdown ();
449 }
450 credential = GNUNET_CREDENTIAL_connect (cfg);
451
452 if (NULL == credential)
453 {
454 fprintf (stderr,
455 _("Failed to connect to CREDENTIAL\n"));
456 GNUNET_SCHEDULER_shutdown ();
457 }
458 if (NULL == issuer_attr || NULL == subject_credential)
459 {
460 fprintf (stderr,
461 _("You must provide issuer and subject attributes\n"));
462 GNUNET_SCHEDULER_shutdown ();
463 }
464
465 //Subject credentials are comma separated
466 char *tmp = GNUNET_strdup (subject_credential);
467 char *tok = strtok (tmp, ",");
468 if (NULL == tok)
469 {
470 fprintf (stderr,
471 "Invalid subject credentials\n");
472 GNUNET_free (tmp);
473 GNUNET_SCHEDULER_shutdown ();
474 }
475 int count = 1;
476 int i;
477 while (NULL != (tok = strtok(NULL, ",")))
478 count++;
479 struct GNUNET_CREDENTIAL_Credential credentials[count];
480 struct GNUNET_CREDENTIAL_Credential *cred;
481 GNUNET_free (tmp);
482 tmp = GNUNET_strdup (subject_credential);
483 tok = strtok (tmp, ",");
484 for (i=0;i<count;i++)
485 {
486 cred = GNUNET_CREDENTIAL_credential_from_string (tok);
487 GNUNET_memcpy (&credentials[i],
488 cred,
489 sizeof (struct GNUNET_CREDENTIAL_Credential));
490 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
491 tok = strtok(NULL, ",");
492 GNUNET_free (cred);
493 }
494
495 verify_request = GNUNET_CREDENTIAL_verify(credential,
496 &issuer_pkey,
497 issuer_attr, //TODO argument
498 &subject_pkey,
499 count,
500 credentials,
501 &handle_verify_result,
502 NULL);
503 for (i=0;i<count;i++)
504 {
505 GNUNET_free ((char*)credentials[i].issuer_attribute);
506 }
507 } else if (GNUNET_YES == create_cred) {
508 if (NULL == ego_name)
509 {
510 fprintf (stderr,
511 _("Issuer ego required\n"));
512 GNUNET_SCHEDULER_shutdown ();
513 return;
514
515 }
516 el = GNUNET_IDENTITY_ego_lookup (cfg,
517 ego_name,
518 &identity_cb,
519 (void *) cfg);
520 return;
521 } else {
522 fprintf (stderr,
523 _("Please specify name to lookup, subject key and issuer key!\n"));
524 GNUNET_SCHEDULER_shutdown ();
525 }
526 return;
527}
528
529
530/**
531 * The main function for gnunet-gns.
532 *
533 * @param argc number of arguments from the command line
534 * @param argv command line arguments
535 * @return 0 ok, 1 on error
536 */
537int
538main (int argc, char *const *argv)
539{
540 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
541 {'I', "issue", NULL,
542 gettext_noop ("create credential"), 0,
543 &GNUNET_GETOPT_set_one, &create_cred},
544 {'V', "verify", NULL,
545 gettext_noop ("verify credential against attribute"), 0,
546 &GNUNET_GETOPT_set_one, &verify},
547 {'s', "subject", "PKEY",
548 gettext_noop ("The public key of the subject to lookup the credential for"), 1,
549 &GNUNET_GETOPT_set_string, &subject_key},
550 {'b', "credential", "CRED",
551 gettext_noop ("The name of the credential presented by the subject"), 1,
552 &GNUNET_GETOPT_set_string, &subject_credential},
553 {'i', "issuer", "PKEY",
554 gettext_noop ("The public key of the authority to verify the credential against"), 1,
555 &GNUNET_GETOPT_set_string, &issuer_key},
556 {'e', "ego", "EGO",
557 gettext_noop ("The ego to use"), 1,
558 &GNUNET_GETOPT_set_string, &ego_name},
559 {'a', "attribute", "ATTR",
560 gettext_noop ("The issuer attribute to verify against or to issue"), 1,
561 &GNUNET_GETOPT_set_string, &issuer_attr},
562 {'T', "ttl", "EXP",
563 gettext_noop ("The time to live for the credential"), 1,
564 &GNUNET_GETOPT_set_string, &expiration},
565 {'g', "collect", NULL,
566 gettext_noop ("collect credentials"), 0,
567 &GNUNET_GETOPT_set_one, &collect},
568 GNUNET_GETOPT_OPTION_END
569 };
570 int ret;
571
572 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
573 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
574 return 2;
575
576 GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
577 ret =
578 (GNUNET_OK ==
579 GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
580 _("GNUnet credential resolver tool"),
581 options,
582 &run, NULL)) ? 0 : 1;
583 GNUNET_free ((void*) argv);
584 return ret;
585}
586
587/* 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..75ed6d5da
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1240 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file gns/gnunet-service-credential.c
22 * @brief GNU Credential Service (main service)
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_credential_service.h"
28#include "gnunet_statistics_service.h"
29#include "credential.h"
30#include "credential_serialization.h"
31#include "gnunet_protocols.h"
32#include "gnunet_signatures.h"
33
34#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 if (NULL != ds_entry->issuer_key)
381 GNUNET_free (ds_entry->issuer_key);
382 if (NULL != ds_entry->lookup_attribute)
383 GNUNET_free (ds_entry->lookup_attribute);
384 if (NULL != ds_entry->issuer_attribute)
385 GNUNET_free (ds_entry->issuer_attribute);
386 if (NULL != ds_entry->unresolved_attribute_delegation)
387 GNUNET_free (ds_entry->unresolved_attribute_delegation);
388 if (NULL != ds_entry->attr_trailer)
389 GNUNET_free (ds_entry->attr_trailer);
390 if (NULL != ds_entry->lookup_request)
391 {
392 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
393 ds_entry->lookup_request = NULL;
394 }
395 if (NULL != ds_entry->delegation_chain_entry)
396 {
397 if (NULL != ds_entry->delegation_chain_entry->subject_attribute)
398 GNUNET_free (ds_entry->delegation_chain_entry->subject_attribute);
399 if (NULL != ds_entry->delegation_chain_entry->issuer_attribute)
400 GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
401 GNUNET_free (ds_entry->delegation_chain_entry);
402 }
403 GNUNET_free (ds_entry);
404}
405
406static void
407cleanup_handle (struct VerifyRequestHandle *vrh)
408{
409 struct CredentialRecordEntry *cr_entry;
410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
411 "Cleaning up...\n");
412 if (NULL != vrh->lookup_request)
413 {
414 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
415 vrh->lookup_request = NULL;
416 }
417 cleanup_delegation_set (vrh->root_set);
418 if (NULL != vrh->issuer_attribute)
419 GNUNET_free (vrh->issuer_attribute);
420 for (cr_entry = vrh->cred_chain_head;
421 NULL != vrh->cred_chain_head;
422 cr_entry = vrh->cred_chain_head)
423 {
424 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
425 vrh->cred_chain_tail,
426 cr_entry);
427 if (NULL != cr_entry->credential);
428 GNUNET_free (cr_entry->credential);
429 GNUNET_free (cr_entry);
430 }
431 GNUNET_free (vrh);
432}
433
434/**
435 * Task run during shutdown.
436 *
437 * @param cls unused
438 * @param tc unused
439 */
440static void
441shutdown_task (void *cls)
442{
443 struct VerifyRequestHandle *vrh;
444
445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
446 "Shutting down!\n");
447
448 while (NULL != (vrh = vrh_head))
449 {
450 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
451 GNUNET_CONTAINER_DLL_remove (vrh_head,
452 vrh_tail,
453 vrh);
454 cleanup_handle (vrh);
455 }
456
457 if (NULL != gns)
458 {
459 GNUNET_GNS_disconnect (gns);
460 gns = NULL;
461 }
462 if (NULL != namestore)
463 {
464 GNUNET_NAMESTORE_disconnect (namestore);
465 namestore = NULL;
466 }
467 if (NULL != statistics)
468 {
469 GNUNET_STATISTICS_destroy (statistics,
470 GNUNET_NO);
471 statistics = NULL;
472 }
473
474}
475
476
477
478/**
479 * Send.
480 *
481 * @param handle the handle to the request
482 */
483static void
484send_lookup_response (struct VerifyRequestHandle *vrh)
485{
486 struct GNUNET_MQ_Envelope *env;
487 struct DelegationChainResultMessage *rmsg;
488 struct DelegationChainEntry *dce;
489 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
490 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
491 struct CredentialRecordEntry *cd;
492 struct CredentialRecordEntry *tmp;
493 size_t size;
494 int i;
495
496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
497 "Sending response\n");
498 dce = vrh->delegation_chain_head;
499 for (i=0;i<vrh->delegation_chain_size;i++)
500 {
501 dd[i].issuer_key = dce->issuer_key;
502 dd[i].subject_key = dce->subject_key;
503 dd[i].issuer_attribute = dce->issuer_attribute;
504 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
505 dd[i].subject_attribute_len = 0;
506 dd[i].subject_attribute = NULL;
507 if (NULL != dce->subject_attribute)
508 {
509 dd[i].subject_attribute = dce->subject_attribute;
510 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
511 }
512 dce = dce->next;
513 }
514
515 /**
516 * Remove all credentials not needed
517 */
518 for (cd = vrh->cred_chain_head; NULL != cd;)
519 {
520 if (cd->refcount > 0)
521 {
522 cd = cd->next;
523 continue;
524 }
525 tmp = cd;
526 cd = cd->next;
527 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
528 vrh->cred_chain_tail,
529 tmp);
530 GNUNET_free (tmp->credential);
531 GNUNET_free (tmp);
532 vrh->cred_chain_size--;
533 }
534
535 /**
536 * Get serialized record data
537 * Append at the end of rmsg
538 */
539 cd = vrh->cred_chain_head;
540 for (i=0;i<vrh->cred_chain_size;i++)
541 {
542 cred[i].issuer_key = cd->credential->issuer_key;
543 cred[i].subject_key = cd->credential->subject_key;
544 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
545 cred[i].issuer_attribute = cd->credential->issuer_attribute;
546 cred[i].expiration = cd->credential->expiration;
547 cred[i].signature = cd->credential->signature;
548 cd = cd->next;
549 }
550 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
551 dd,
552 vrh->cred_chain_size,
553 cred);
554 env = GNUNET_MQ_msg_extra (rmsg,
555 size,
556 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
557 //Assign id so that client can find associated request
558 rmsg->id = vrh->request_id;
559 rmsg->d_count = htonl (vrh->delegation_chain_size);
560 rmsg->c_count = htonl (vrh->cred_chain_size);
561
562 if (0 < vrh->cred_chain_size)
563 rmsg->cred_found = htonl (GNUNET_YES);
564 else
565 rmsg->cred_found = htonl (GNUNET_NO);
566
567 GNUNET_assert (-1 !=
568 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
569 dd,
570 vrh->cred_chain_size,
571 cred,
572 size,
573 (char*)&rmsg[1]));
574
575 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
576 env);
577 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
578 cleanup_handle(vrh);
579
580 GNUNET_STATISTICS_update (statistics,
581 "Completed verifications", 1,
582 GNUNET_NO);
583}
584
585
586static void
587backward_resolution (void* cls,
588 uint32_t rd_count,
589 const struct GNUNET_GNSRECORD_Data *rd)
590{
591
592 struct VerifyRequestHandle *vrh;
593 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
594 struct CredentialRecordEntry *cred_pointer;
595 struct DelegationSetQueueEntry *current_set;
596 struct DelegationSetQueueEntry *ds_entry;
597 struct DelegationSetQueueEntry *tmp_set;
598 struct DelegationQueueEntry *dq_entry;
599 char *expanded_attr;
600 char *lookup_attribute;
601 int i;
602 int j;
603
604
605 current_set = cls;
606 current_set->lookup_request = NULL;
607 vrh = current_set->handle;
608 vrh->pending_lookups--;
609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
610 "Got %d attrs\n", rd_count);
611
612 // Each OR
613 for (i=0; i < rd_count; i++)
614 {
615 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
616 continue;
617
618 sets = rd[i].data;
619 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
621 "Found new attribute delegation with %d sets. Creating new Job...\n",
622 ntohl (sets->set_count));
623
624 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
625 (const char*)&sets[1],
626 ntohl(sets->set_count),
627 set))
628 {
629 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
630 "Failed to deserialize!\n");
631 continue;
632 }
633 dq_entry = GNUNET_new (struct DelegationQueueEntry);
634 dq_entry->required_solutions = ntohl(sets->set_count);
635 dq_entry->parent_set = current_set;
636 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
637 current_set->queue_entries_tail,
638 dq_entry);
639 // Each AND
640 for (j=0; j<ntohl(sets->set_count); j++)
641 {
642 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
643 if (NULL != current_set->attr_trailer)
644 {
645 if (0 == set[j].subject_attribute_len)
646 {
647 GNUNET_asprintf (&expanded_attr,
648 "%s",
649 current_set->attr_trailer);
650
651 } else {
652 GNUNET_asprintf (&expanded_attr,
653 "%s.%s",
654 set[j].subject_attribute,
655 current_set->attr_trailer);
656 }
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658 "Expanded to %s\n", expanded_attr);
659 ds_entry->unresolved_attribute_delegation = expanded_attr;
660 } else {
661 if (0 != set[j].subject_attribute_len)
662 {
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
664 "Not Expanding %s\n", set[j].subject_attribute);
665 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
666 }
667 }
668
669 //Add a credential chain entry
670 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
671 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
672 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
673 GNUNET_memcpy (ds_entry->issuer_key,
674 &set[j].subject_key,
675 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
676 if (0 < set[j].subject_attribute_len)
677 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
678 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
679 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
680
681 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
682 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
683 dq_entry->set_entries_tail,
684 ds_entry);
685
686 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
687 "Checking for cred match\n");
688 /**
689 * Check if this delegation already matches one of our credentials
690 */
691 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
692 cred_pointer = cred_pointer->next)
693 {
694 if(0 != memcmp (&set->subject_key,
695 &cred_pointer->credential->issuer_key,
696 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
697 continue;
698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
699 "Checking if %s matches %s\n",
700 ds_entry->unresolved_attribute_delegation,
701 cred_pointer->credential->issuer_attribute);
702
703 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
704 cred_pointer->credential->issuer_attribute))
705 continue;
706
707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
708 "Found issuer\n");
709 cred_pointer->refcount++;
710 //Backtrack
711 for (tmp_set = ds_entry;
712 NULL != tmp_set->parent_queue_entry;
713 tmp_set = tmp_set->parent_queue_entry->parent_set)
714 {
715 tmp_set->parent_queue_entry->required_solutions--;
716 if (NULL != tmp_set->delegation_chain_entry)
717 {
718 vrh->delegation_chain_size++;
719 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
720 vrh->delegation_chain_tail,
721 tmp_set->delegation_chain_entry);
722 }
723 if (0 < tmp_set->parent_queue_entry->required_solutions)
724 break;
725 }
726
727 if (NULL == tmp_set->parent_queue_entry)
728 {
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "All solutions found\n");
731 //Found match
732 send_lookup_response (vrh);
733 return;
734 }
735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
736 "Not all solutions found yet.\n");
737 continue;
738
739 }
740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
741 "Building new lookup request from %s\n",
742 ds_entry->unresolved_attribute_delegation);
743 //Continue with backward resolution
744 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
745 strcpy (issuer_attribute_name,
746 ds_entry->unresolved_attribute_delegation);
747 char *next_attr = strtok (issuer_attribute_name, ".");
748 GNUNET_asprintf (&lookup_attribute,
749 "%s.gnu",
750 next_attr);
751 GNUNET_asprintf (&ds_entry->lookup_attribute,
752 "%s",
753 next_attr);
754 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
755 {
756 ds_entry->attr_trailer = NULL;
757 } else {
758 next_attr += strlen (next_attr) + 1;
759 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
760 }
761
762 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
763 "Looking up %s\n", ds_entry->lookup_attribute);
764 if (NULL != ds_entry->attr_trailer)
765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
766 "%s still to go...\n", ds_entry->attr_trailer);
767
768 vrh->pending_lookups++;
769 ds_entry->handle = vrh;
770 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
771 lookup_attribute,
772 ds_entry->issuer_key, //issuer_key,
773 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
774 GNUNET_GNS_LO_DEFAULT,
775 NULL, //shorten_key, always NULL
776 &backward_resolution,
777 ds_entry);
778 GNUNET_free (lookup_attribute);
779 }
780 }
781
782 if(0 == vrh->pending_lookups)
783 {
784 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
785 "We are all out of attributes...\n");
786 send_lookup_response (vrh);
787 return;
788
789 }
790}
791
792
793/**
794 * Result from GNS lookup.
795 *
796 * @param cls the closure (our client lookup handle)
797 * @param rd_count the number of records in @a rd
798 * @param rd the record data
799 */
800static void
801delegation_chain_resolution_start (void* cls)
802{
803 struct VerifyRequestHandle *vrh = cls;
804 struct DelegationSetQueueEntry *ds_entry;
805 struct CredentialRecordEntry *cr_entry;
806 vrh->lookup_request = NULL;
807
808 if (0 == vrh->cred_chain_size)
809 {
810 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
811 "No credentials found\n");
812 send_lookup_response (vrh);
813 return;
814 }
815
816 for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
817 {
818 if (0 != memcmp (&cr_entry->credential->issuer_key,
819 &vrh->issuer_key,
820 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
821 continue;
822 if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
823 continue;
824 cr_entry->refcount++;
825 //Found match prematurely
826 send_lookup_response (vrh);
827 return;
828
829 }
830
831 /**
832 * Check for attributes from the issuer and follow the chain
833 * till you get the required subject's attributes
834 */
835 char issuer_attribute_name[strlen (vrh->issuer_attribute)];
836 strcpy (issuer_attribute_name,
837 vrh->issuer_attribute);
838 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
839 ".gnu");
840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
841 "Looking up %s\n", issuer_attribute_name);
842 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
843 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
844 memcpy (ds_entry->issuer_key,
845 &vrh->issuer_key,
846 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
847 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
848 ds_entry->handle = vrh;
849 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
850 vrh->root_set = ds_entry;
851 vrh->pending_lookups = 1;
852 //Start with backward resolution
853 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
854 issuer_attribute_name,
855 &vrh->issuer_key, //issuer_key,
856 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
857 GNUNET_GNS_LO_DEFAULT,
858 NULL, //shorten_key, always NULL
859 &backward_resolution,
860 ds_entry);
861}
862
863/**
864 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
865 *
866 * @param cls client sending the message
867 * @param v_msg message of type `struct VerifyMessage`
868 * @return #GNUNET_OK if @a v_msg is well-formed
869 */
870static int
871check_verify (void *cls,
872 const struct VerifyMessage *v_msg)
873{
874 size_t msg_size;
875 const char* attr;
876
877 msg_size = ntohs (v_msg->header.size);
878 if (msg_size < sizeof (struct VerifyMessage))
879 {
880 GNUNET_break (0);
881 return GNUNET_SYSERR;
882 }
883 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
884 {
885 GNUNET_break (0);
886 return GNUNET_SYSERR;
887 }
888 attr = (const char *) &v_msg[1];
889
890 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
891 {
892 GNUNET_break (0);
893 return GNUNET_SYSERR;
894 }
895 return GNUNET_OK;
896}
897
898/**
899 * Handle Credential verification requests from client
900 *
901 * @param cls the closure
902 * @param client the client
903 * @param message the message
904 */
905static void
906handle_verify (void *cls,
907 const struct VerifyMessage *v_msg)
908{
909 struct VerifyRequestHandle *vrh;
910 struct GNUNET_SERVICE_Client *client = cls;
911 struct CredentialRecordEntry *cr_entry;
912 uint32_t credentials_count;
913 uint32_t credential_data_size;
914 int i;
915 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
916 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
917 char *attrptr = attr;
918 char *credential_data;
919 const char *utf_in;
920
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922 "Received VERIFY message\n");
923 utf_in = (const char *) &v_msg[1];
924 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
925 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
926 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
927 vrh = GNUNET_new (struct VerifyRequestHandle);
928 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
929 vrh->client = client;
930 vrh->request_id = v_msg->id;
931 vrh->issuer_key = v_msg->issuer_key;
932 vrh->subject_key = v_msg->subject_key;
933 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
934 if (NULL == issuer_attribute)
935 {
936 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
937 "No issuer attribute provided!\n");
938 send_lookup_response (vrh);
939 return;
940 }
941 /**
942 * First, collect credentials
943 * TODO: cleanup!
944 */
945 credentials_count = ntohl(v_msg->c_count);
946 credential_data_size = ntohs (v_msg->header.size)
947 - sizeof (struct VerifyMessage)
948 - ntohs (v_msg->issuer_attribute_len)
949 - 1;
950 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
951 credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
952 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
953 credential_data,
954 credentials_count,
955 credentials))
956 {
957 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
958 "Cannot deserialize credentials!\n");
959 send_lookup_response (vrh);
960 return;
961 }
962
963 for (i=0;i<credentials_count;i++) {
964 cr_entry = GNUNET_new (struct CredentialRecordEntry);
965 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
966 strlen (credentials[i].issuer_attribute) + 1);
967 GNUNET_memcpy (cr_entry->credential,
968 &credentials[i],
969 sizeof (struct GNUNET_CREDENTIAL_Credential));
970 GNUNET_memcpy (&cr_entry->credential[1],
971 credentials[i].issuer_attribute,
972 strlen (credentials[i].issuer_attribute));
973 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
974 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
975 vrh->cred_chain_tail,
976 cr_entry);
977 vrh->cred_chain_size++;
978 }
979
980 delegation_chain_resolution_start (vrh);
981
982}
983
984/**
985 * We encountered an error while collecting
986 */
987static void
988handle_cred_collection_error_cb (void *cls)
989{
990 struct VerifyRequestHandle *vrh = cls;
991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
992 "Got disconnected from namestore database.\n");
993 vrh->cred_collection_iter = NULL;
994 send_lookup_response (vrh);
995}
996
997static void
998collect_next (void *cls)
999{
1000 struct VerifyRequestHandle *vrh = cls;
1001 vrh->collect_next_task = NULL;
1002 GNUNET_assert (NULL != vrh->cred_collection_iter);
1003 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
1004}
1005
1006/**
1007 * Store credential
1008 */
1009static void
1010handle_cred_collection_cb (void *cls,
1011 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
1012 const char *label,
1013 unsigned int rd_count,
1014 const struct GNUNET_GNSRECORD_Data *rd)
1015{
1016 struct VerifyRequestHandle *vrh = cls;
1017 struct GNUNET_CREDENTIAL_Credential *crd;
1018 struct CredentialRecordEntry *cr_entry;
1019 int cred_record_count;
1020 int i;
1021
1022 cred_record_count = 0;
1023 for (i=0; i < rd_count; i++)
1024 {
1025 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
1026 continue;
1027 cred_record_count++;
1028 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
1029 rd[i].data_size);
1030 if (NULL == crd)
1031 {
1032 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1033 "Invalid credential found\n");
1034 continue;
1035 }
1036 cr_entry = GNUNET_new (struct CredentialRecordEntry);
1037 cr_entry->credential = crd;
1038 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
1039 vrh->cred_chain_tail,
1040 cr_entry);
1041 vrh->cred_chain_size++;
1042 }
1043 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
1044 vrh);
1045}
1046
1047/**
1048 * We encountered an error while collecting
1049 */
1050static void
1051handle_cred_collection_finished_cb (void *cls)
1052{
1053 struct VerifyRequestHandle *vrh = cls;
1054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1055 "Done collecting credentials.\n");
1056 vrh->cred_collection_iter = NULL;
1057 delegation_chain_resolution_start (vrh);
1058}
1059
1060/**
1061 * Handle Credential collection requests from client
1062 *
1063 * @param cls the closure
1064 * @param client the client
1065 * @param message the message
1066 */
1067static void
1068handle_collect (void *cls,
1069 const struct CollectMessage *c_msg)
1070{
1071 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1072 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1073 struct VerifyRequestHandle *vrh;
1074 struct GNUNET_SERVICE_Client *client = cls;
1075 char *attrptr = attr;
1076 const char *utf_in;
1077
1078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1079 "Received COLLECT message\n");
1080
1081 utf_in = (const char *) &c_msg[1];
1082 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1083
1084 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1085 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1086 vrh = GNUNET_new (struct VerifyRequestHandle);
1087 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1088 vrh->client = client;
1089 vrh->request_id = c_msg->id;
1090 vrh->issuer_key = c_msg->issuer_key;
1091 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1092 &vrh->subject_key);
1093 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1094
1095 if (NULL == issuer_attribute)
1096 {
1097 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1098 "No issuer attribute provided!\n");
1099 send_lookup_response (vrh);
1100 return;
1101 }
1102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1103 "Getting credentials for subject\n");
1104 /**
1105 * First, get attribute from subject
1106 */
1107 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
1108 &c_msg->subject_key,
1109 &handle_cred_collection_error_cb,
1110 vrh,
1111 &handle_cred_collection_cb,
1112 vrh,
1113 &handle_cred_collection_finished_cb,
1114 vrh);
1115}
1116
1117
1118/**
1119 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT message
1120 *
1121 * @param cls client sending the message
1122 * @param v_msg message of type `struct CollectMessage`
1123 * @return #GNUNET_OK if @a v_msg is well-formed
1124 */
1125static int
1126check_collect (void *cls,
1127 const struct CollectMessage *c_msg)
1128{
1129 size_t msg_size;
1130 const char* attr;
1131
1132 msg_size = ntohs (c_msg->header.size);
1133 if (msg_size < sizeof (struct CollectMessage))
1134 {
1135 GNUNET_break (0);
1136 return GNUNET_SYSERR;
1137 }
1138 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1139 {
1140 GNUNET_break (0);
1141 return GNUNET_SYSERR;
1142 }
1143 attr = (const char *) &c_msg[1];
1144
1145 if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
1146 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1147 {
1148 GNUNET_break (0);
1149 return GNUNET_SYSERR;
1150 }
1151 return GNUNET_OK;
1152}
1153
1154/**
1155 * One of our clients disconnected, clean up after it.
1156 *
1157 * @param cls NULL
1158 * @param client the client that disconnected
1159 */
1160static void
1161client_disconnect_cb (void *cls,
1162 struct GNUNET_SERVICE_Client *client,
1163 void *app_ctx)
1164{
1165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1166 "Client %p disconnected\n",
1167 client);
1168}
1169
1170/**
1171 * Add a client to our list of active clients.
1172 *
1173 * @param cls NULL
1174 * @param client client to add
1175 * @param mq message queue for @a client
1176 * @return this client
1177 */
1178static void *
1179client_connect_cb (void *cls,
1180 struct GNUNET_SERVICE_Client *client,
1181 struct GNUNET_MQ_Handle *mq)
1182{
1183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1184 "Client %p connected\n",
1185 client);
1186 return client;
1187}
1188
1189/**
1190 * Process Credential requests.
1191 *
1192 * @param cls closure
1193 * @param server the initialized server
1194 * @param c configuration to use
1195 */
1196static void
1197run (void *cls,
1198 const struct GNUNET_CONFIGURATION_Handle *c,
1199 struct GNUNET_SERVICE_Handle *handle)
1200{
1201
1202 gns = GNUNET_GNS_connect (c);
1203 if (NULL == gns)
1204 {
1205 fprintf (stderr,
1206 _("Failed to connect to GNS\n"));
1207 }
1208 namestore = GNUNET_NAMESTORE_connect (c);
1209 if (NULL == namestore)
1210 {
1211 fprintf (stderr,
1212 _("Failed to connect to namestore\n"));
1213 }
1214
1215 statistics = GNUNET_STATISTICS_create ("credential", c);
1216 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1217}
1218
1219
1220/**
1221 * Define "main" method using service macro
1222 */
1223GNUNET_SERVICE_MAIN
1224("credential",
1225 GNUNET_SERVICE_OPTION_NONE,
1226 &run,
1227 &client_connect_cb,
1228 &client_disconnect_cb,
1229 NULL,
1230 GNUNET_MQ_hd_var_size (verify,
1231 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1232 struct VerifyMessage,
1233 NULL),
1234 GNUNET_MQ_hd_var_size (collect,
1235 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1236 struct CollectMessage,
1237 NULL),
1238 GNUNET_MQ_handler_end());
1239
1240/* end of gnunet-service-credential.c */
diff --git a/src/credential/plugin_gnsrecord_credential.c b/src/credential/plugin_gnsrecord_credential.c
new file mode 100644
index 000000000..5c3c03832
--- /dev/null
+++ b/src/credential/plugin_gnsrecord_credential.c
@@ -0,0 +1,342 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file credential/plugin_gnsrecord_credential.c
23 * @brief gnsrecord plugin to provide the API for CREDENTIAL records
24 * @author Adnan Husain
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_credential_service.h"
31#include "gnunet_gnsrecord_plugin.h"
32#include "gnunet_signatures.h"
33#include "credential_serialization.h"
34#include "credential_misc.h"
35
36/**
37 * Convert the 'value' of a record to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the record
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46credential_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51
52 const char *cdata;
53
54 switch (type)
55 {
56 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
57 {
58 struct GNUNET_CREDENTIAL_DelegationRecord sets;
59 char *attr_str;
60 char *subject_pkey;
61 char *tmp_str;
62 int i;
63 if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
64 return NULL; /* malformed */
65 memcpy (&sets,
66 data,
67 sizeof (sets));
68 cdata = data;
69 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
70 if (GNUNET_OK != GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll (sets.data_size),
71 &cdata[sizeof (sets)],
72 ntohl (sets.set_count),
73 set))
74 return NULL;
75
76 for (i=0;i<ntohl(sets.set_count);i++)
77 {
78 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key);
79 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
80 "%d len attr\n", set[i].subject_attribute_len);
81 if (0 == set[i].subject_attribute_len)
82 {
83 if (0 == i)
84 {
85 GNUNET_asprintf (&attr_str,
86 "%s",
87 subject_pkey);
88 } else {
89 GNUNET_asprintf (&tmp_str,
90 "%s,%s",
91 attr_str,
92 subject_pkey);
93 GNUNET_free (attr_str);
94 attr_str = tmp_str;
95 }
96 } else {
97 if (0 == i)
98 {
99 GNUNET_asprintf (&attr_str,
100 "%s %s",
101 subject_pkey,
102 set[i].subject_attribute);
103 } else {
104 GNUNET_asprintf (&tmp_str,
105 "%s,%s %s",
106 attr_str,
107 subject_pkey,
108 set[i].subject_attribute);
109 GNUNET_free (attr_str);
110 attr_str = tmp_str;
111 }
112 }
113 GNUNET_free (subject_pkey);
114 }
115 return attr_str;
116 }
117 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
118 {
119 struct GNUNET_CREDENTIAL_Credential *cred;
120 char *cred_str;
121
122 cred = GNUNET_CREDENTIAL_credential_deserialize (data,
123 data_size);
124 cred_str = GNUNET_CREDENTIAL_credential_to_string (cred);
125 GNUNET_free (cred);
126 return cred_str;
127 }
128 default:
129 return NULL;
130 }
131}
132
133
134/**
135 * Convert human-readable version of a 'value' of a record to the binary
136 * representation.
137 *
138 * @param cls closure, unused
139 * @param type type of the record
140 * @param s human-readable string
141 * @param data set to value in binary encoding (will be allocated)
142 * @param data_size set to number of bytes in @a data
143 * @return #GNUNET_OK on success
144 */
145static int
146credential_string_to_value (void *cls,
147 uint32_t type,
148 const char *s,
149 void **data,
150 size_t *data_size)
151{
152 if (NULL == s)
153 return GNUNET_SYSERR;
154 switch (type)
155 {
156 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
157 {
158 struct GNUNET_CREDENTIAL_DelegationRecord *sets;
159 char attr_str[253 + 1];
160 char subject_pkey[52 + 1];
161 char *token;
162 char *tmp_str;
163 int matches = 0;
164 int entries;
165 size_t tmp_data_size;
166 int i;
167
168 tmp_str = GNUNET_strdup (s);
169 token = strtok (tmp_str, ",");
170 entries = 0;
171 tmp_data_size = 0;
172 *data_size = sizeof (struct GNUNET_CREDENTIAL_DelegationRecord);
173 while (NULL != token)
174 {
175 matches = SSCANF (token,
176 "%s %s",
177 subject_pkey,
178 attr_str);
179 if (0 == matches)
180 {
181 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
182 _("Unable to parse ATTR record string `%s'\n"),
183 s);
184 GNUNET_free (tmp_str);
185 return GNUNET_SYSERR;
186 }
187 if (1 == matches) {
188 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet);
189 } else if (2 == matches) {
190 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
191 }
192 entries++;
193 token = strtok (NULL, ",");
194 }
195 GNUNET_free (tmp_str);
196 tmp_str = GNUNET_strdup (s);
197 token = strtok (tmp_str, ",");
198 struct GNUNET_CREDENTIAL_DelegationSet set[entries];
199 for (i=0;i<entries;i++)
200 {
201 matches = SSCANF (token,
202 "%s %s",
203 subject_pkey,
204 attr_str);
205 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
206 strlen (subject_pkey),
207 &set[i].subject_key);
208 if (2 == matches) {
209 set[i].subject_attribute_len = strlen (attr_str) + 1;
210 set[i].subject_attribute = GNUNET_strdup (attr_str);
211 }
212 token = strtok (NULL , ",");
213 }
214 tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
215 set);
216
217 if (-1 == tmp_data_size)
218 return GNUNET_SYSERR;
219 *data_size += tmp_data_size;
220 *data = sets = GNUNET_malloc (*data_size);
221 GNUNET_CREDENTIAL_delegation_set_serialize (entries,
222 set,
223 tmp_data_size,
224 (char*)&sets[1]);
225 for (i=0;i<entries;i++)
226 {
227 if (0 != set[i].subject_attribute_len)
228 GNUNET_free ((char*)set[i].subject_attribute);
229 }
230 sets->set_count = htonl (entries);
231 sets->data_size = GNUNET_htonll (tmp_data_size);
232
233 GNUNET_free (tmp_str);
234 return GNUNET_OK;
235 }
236 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
237 {
238 struct GNUNET_CREDENTIAL_Credential *cred;
239 cred = GNUNET_CREDENTIAL_credential_from_string (s);
240
241 *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
242 (char**)data);
243 return GNUNET_OK;
244 }
245 default:
246 return GNUNET_SYSERR;
247 }
248}
249
250
251/**
252 * Mapping of record type numbers to human-readable
253 * record type names.
254 */
255static struct {
256 const char *name;
257 uint32_t number;
258} name_map[] = {
259 { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
260 { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
261 { NULL, UINT32_MAX }
262};
263
264
265/**
266 * Convert a type name (i.e. "AAAA") to the corresponding number.
267 *
268 * @param cls closure, unused
269 * @param gns_typename name to convert
270 * @return corresponding number, UINT32_MAX on error
271 */
272static uint32_t
273credential_typename_to_number (void *cls,
274 const char *gns_typename)
275{
276 unsigned int i;
277
278 i=0;
279 while ( (name_map[i].name != NULL) &&
280 (0 != strcasecmp (gns_typename, name_map[i].name)) )
281 i++;
282 return name_map[i].number;
283}
284
285
286/**
287 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
288 *
289 * @param cls closure, unused
290 * @param type number of a type to convert
291 * @return corresponding typestring, NULL on error
292 */
293static const char *
294credential_number_to_typename (void *cls,
295 uint32_t type)
296{
297 unsigned int i;
298
299 i=0;
300 while ( (name_map[i].name != NULL) &&
301 (type != name_map[i].number) )
302 i++;
303 return name_map[i].name;
304}
305
306
307/**
308 * Entry point for the plugin.
309 *
310 * @param cls NULL
311 * @return the exported block API
312 */
313void *
314libgnunet_plugin_gnsrecord_credential_init (void *cls)
315{
316 struct GNUNET_GNSRECORD_PluginFunctions *api;
317
318 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
319 api->value_to_string = &credential_value_to_string;
320 api->string_to_value = &credential_string_to_value;
321 api->typename_to_number = &credential_typename_to_number;
322 api->number_to_typename = &credential_number_to_typename;
323 return api;
324}
325
326
327/**
328 * Exit point from the plugin.
329 *
330 * @param cls the return value from #libgnunet_plugin_block_test_init
331 * @return NULL
332 */
333void *
334libgnunet_plugin_gnsrecord_credential_done (void *cls)
335{
336 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
337
338 GNUNET_free (api);
339 return NULL;
340}
341
342/* end of plugin_gnsrecord_credential.c */
diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c
new file mode 100644
index 000000000..59022e794
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,1179 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file gns/plugin_rest_credential.c
23 * @brief GNUnet CREDENTIAL REST plugin
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_rest_plugin.h"
29#include <gnunet_identity_service.h>
30#include <gnunet_gnsrecord_lib.h>
31#include <gnunet_namestore_service.h>
32#include <gnunet_credential_service.h>
33#include <gnunet_rest_lib.h>
34#include <gnunet_jsonapi_lib.h>
35#include <gnunet_jsonapi_util.h>
36#include <jansson.h>
37
38#define GNUNET_REST_API_NS_CREDENTIAL "/credential"
39
40#define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
41
42#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
43
44#define GNUNET_REST_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_verify_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
197/**
198 * Task run on shutdown. Cleans up everything.
199 *
200 * @param cls unused
201 * @param tc scheduler context
202 */
203static void
204do_error (void *cls)
205{
206 struct RequestHandle *handle = cls;
207 struct MHD_Response *resp;
208
209 resp = GNUNET_REST_create_response (NULL);
210 handle->proc (handle->proc_cls, resp, handle->response_code);
211 cleanup_handle (handle);
212}
213
214/**
215 * Attribute delegation to JSON
216 * @param attr the attribute
217 * @return JSON, NULL if failed
218 */
219static json_t*
220attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
221{
222 char *subject;
223 char *issuer;
224 json_t *attr_obj;
225
226 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
227 if (NULL == issuer)
228 {
229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
230 "Issuer in delegation malformed\n");
231 return NULL;
232 }
233 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
234 if (NULL == subject)
235 {
236 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
237 "Subject in credential malformed\n");
238 GNUNET_free (issuer);
239 return NULL;
240 }
241 attr_obj = json_object ();
242
243 json_object_set_new (attr_obj, "issuer", json_string (issuer));
244 json_object_set_new (attr_obj, "issuer_attribute",
245 json_string (delegation_chain_entry->issuer_attribute));
246
247 json_object_set_new (attr_obj, "subject", json_string (subject));
248 if (0 < delegation_chain_entry->subject_attribute_len)
249 {
250 json_object_set_new (attr_obj, "subject_attribute",
251 json_string (delegation_chain_entry->subject_attribute));
252 }
253 GNUNET_free (issuer);
254 GNUNET_free (subject);
255 return attr_obj;
256}
257
258/**
259 * JSONAPI resource to Credential
260 * @param res the JSONAPI resource
261 * @return the resulting credential, NULL if failed
262 */
263static struct GNUNET_CREDENTIAL_Credential*
264json_to_credential (json_t *res)
265{
266 struct GNUNET_CREDENTIAL_Credential *cred;
267 json_t *tmp;
268 const char *attribute;
269 const char *signature;
270 char *sig;
271
272 tmp = json_object_get (res, "attribute");
273 if (0 == json_is_string (tmp))
274 {
275 return NULL;
276 }
277 attribute = json_string_value (tmp);
278 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
279 + strlen (attribute));
280 cred->issuer_attribute = attribute;
281 cred->issuer_attribute_len = strlen (attribute);
282 tmp = json_object_get (res, "issuer");
283 if (0 == json_is_string (tmp))
284 {
285 GNUNET_free (cred);
286 return NULL;
287 }
288
289 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
290 strlen (json_string_value(tmp)),
291 &cred->issuer_key);
292 tmp = json_object_get (res, "subject");
293 if (0 == json_is_string (tmp))
294 {
295 GNUNET_free (cred);
296 return NULL;
297 }
298 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
299 strlen (json_string_value(tmp)),
300 &cred->subject_key);
301
302 tmp = json_object_get (res, "signature");
303 if (0 == json_is_string (tmp))
304 {
305 GNUNET_free (cred);
306 return NULL;
307 }
308 signature = json_string_value (tmp);
309 GNUNET_STRINGS_base64_decode (signature,
310 strlen (signature),
311 (char**)&sig);
312 GNUNET_memcpy (&cred->signature,
313 sig,
314 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
315 GNUNET_free (sig);
316
317 tmp = json_object_get (res, "expiration");
318 if (0 == json_is_integer (tmp))
319 {
320 GNUNET_free (cred);
321 return NULL;
322 }
323 cred->expiration.abs_value_us = json_integer_value (tmp);
324 return cred;
325}
326
327
328/**
329 * Credential to JSON
330 * @param cred the credential
331 * @return the resulting json, NULL if failed
332 */
333static json_t*
334credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
335{
336 char *issuer;
337 char *subject;
338 char *signature;
339 char attribute[cred->issuer_attribute_len + 1];
340 json_t *cred_obj;
341
342 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
343 if (NULL == issuer)
344 {
345 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
346 "Issuer in credential malformed\n");
347 return NULL;
348 }
349 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
350 if (NULL == subject)
351 {
352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
353 "Subject in credential malformed\n");
354 GNUNET_free (issuer);
355 return NULL;
356 }
357 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
358 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
359 &signature);
360 memcpy (attribute,
361 cred->issuer_attribute,
362 cred->issuer_attribute_len);
363 attribute[cred->issuer_attribute_len] = '\0';
364 cred_obj = json_object ();
365 json_object_set_new (cred_obj, "issuer", json_string (issuer));
366 json_object_set_new (cred_obj, "subject", json_string (subject));
367 json_object_set_new (cred_obj, "attribute", json_string (attribute));
368 json_object_set_new (cred_obj, "signature", json_string (signature));
369 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
370 GNUNET_free (issuer);
371 GNUNET_free (subject);
372 GNUNET_free (signature);
373 return cred_obj;
374}
375
376/**
377 * Function called with the result of a Credential lookup.
378 *
379 * @param cls the 'const char *' name that was resolved
380 * @param cd_count number of records returned
381 * @param cd array of @a cd_count records with the results
382 */
383static void
384handle_collect_response (void *cls,
385 unsigned int d_count,
386 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
387 unsigned int c_count,
388 struct GNUNET_CREDENTIAL_Credential *cred)
389{
390 struct RequestHandle *handle = cls;
391 struct MHD_Response *resp;
392 struct GNUNET_JSONAPI_Document *json_document;
393 struct GNUNET_JSONAPI_Resource *json_resource;
394 json_t *cred_obj;
395 json_t *cred_array;
396 char *result;
397 char *issuer;
398 char *id;
399 uint32_t i;
400
401 handle->verify_request = NULL;
402 if (NULL == cred) {
403 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
404 "Verify failed.\n");
405 handle->response_code = MHD_HTTP_NOT_FOUND;
406 GNUNET_SCHEDULER_add_now (&do_error, handle);
407 return;
408 }
409 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
410 if (NULL == issuer)
411 {
412 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
413 "Issuer in delegation malformed\n");
414 return;
415 }
416 GNUNET_asprintf (&id,
417 "%s.%s",
418 issuer,
419 handle->issuer_attr);
420 GNUNET_free (issuer);
421 json_document = GNUNET_JSONAPI_document_new ();
422 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
423 id);
424 GNUNET_free (id);
425 cred_array = json_array ();
426 for (i=0;i<c_count;i++)
427 {
428 cred_obj = credential_to_json (&cred[i]);
429 json_array_append_new (cred_array, cred_obj);
430 }
431 GNUNET_JSONAPI_resource_add_attr (json_resource,
432 GNUNET_REST_JSONAPI_CREDENTIAL,
433 cred_array);
434 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
435 GNUNET_JSONAPI_document_serialize (json_document, &result);
436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
437 "Result %s\n",
438 result);
439 json_decref (cred_array);
440 GNUNET_JSONAPI_document_delete (json_document);
441 resp = GNUNET_REST_create_response (result);
442 GNUNET_free(result);
443 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
444 cleanup_handle (handle);
445}
446
447static void
448subject_ego_lookup (void *cls,
449 const struct GNUNET_IDENTITY_Ego *ego)
450{
451 struct RequestHandle *handle = cls;
452 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
453 handle->ego_lookup = NULL;
454
455 if (NULL == ego)
456 {
457 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
458 "Subject not found\n");
459 GNUNET_SCHEDULER_add_now (&do_error, handle);
460 return;
461 }
462 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
463 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
464 &handle->issuer_key,
465 handle->issuer_attr,
466 sub_key,
467 &handle_collect_response,
468 handle);
469}
470
471
472
473/**
474 * Function called with the result of a Credential lookup.
475 *
476 * @param cls the 'const char *' name that was resolved
477 * @param cd_count number of records returned
478 * @param cd array of @a cd_count records with the results
479 */
480static void
481handle_verify_response (void *cls,
482 unsigned int d_count,
483 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
484 unsigned int c_count,
485 struct GNUNET_CREDENTIAL_Credential *cred)
486{
487
488 struct RequestHandle *handle = cls;
489 struct MHD_Response *resp;
490 struct GNUNET_JSONAPI_Document *json_document;
491 struct GNUNET_JSONAPI_Resource *json_resource;
492 json_t *cred_obj;
493 json_t *attr_obj;
494 json_t *cred_array;
495 json_t *attr_array;
496 char *result;
497 char *issuer;
498 char *id;
499 uint32_t i;
500
501 handle->verify_request = NULL;
502 if (NULL == cred) {
503 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
504 "Verify failed.\n");
505 handle->response_code = MHD_HTTP_NOT_FOUND;
506 GNUNET_SCHEDULER_add_now (&do_error, handle);
507 return;
508 }
509 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
510 if (NULL == issuer)
511 {
512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
513 "Issuer in delegation malformed\n");
514 return;
515 }
516 GNUNET_asprintf (&id,
517 "%s.%s",
518 issuer,
519 handle->issuer_attr);
520 GNUNET_free (issuer);
521 json_document = GNUNET_JSONAPI_document_new ();
522 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
523 id);
524 GNUNET_free (id);
525 attr_array = json_array ();
526 for (i = 0; i < d_count; i++)
527 {
528 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
529 json_array_append_new (attr_array, attr_obj);
530 }
531 cred_array = json_array ();
532 for (i=0;i<c_count;i++)
533 {
534 cred_obj = credential_to_json (&cred[i]);
535 json_array_append_new (cred_array, cred_obj);
536 }
537 GNUNET_JSONAPI_resource_add_attr (json_resource,
538 GNUNET_REST_JSONAPI_CREDENTIAL,
539 cred_array);
540 GNUNET_JSONAPI_resource_add_attr (json_resource,
541 GNUNET_REST_JSONAPI_DELEGATIONS,
542 attr_array);
543 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
544 GNUNET_JSONAPI_document_serialize (json_document, &result);
545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
546 "Result %s\n",
547 result);
548 json_decref (attr_array);
549 json_decref (cred_array);
550 GNUNET_JSONAPI_document_delete (json_document);
551 resp = GNUNET_REST_create_response (result);
552 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
553 GNUNET_free (result);
554 cleanup_handle (handle);
555}
556
557static void
558collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
559 const char* url,
560 void *cls)
561{
562 struct RequestHandle *handle = cls;
563 struct GNUNET_HashCode key;
564 char *tmp;
565 char *entity_attr;
566
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
568 "Connecting...\n");
569 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
570 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
571 &do_error, handle);
572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
573 "Connected\n");
574 if (NULL == handle->credential)
575 {
576 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
577 "Connecting to CREDENTIAL failed\n");
578 GNUNET_SCHEDULER_add_now (&do_error, handle);
579 return;
580 }
581 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
582 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
583 &key);
584 if ( GNUNET_NO ==
585 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
586 &key) )
587 {
588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
589 "Missing issuer attribute\n");
590 GNUNET_SCHEDULER_add_now (&do_error, handle);
591 return;
592 }
593 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
594 &key);
595 entity_attr = GNUNET_strdup (tmp);
596 tmp = strtok(entity_attr, ".");
597 if (NULL == tmp)
598 {
599 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
600 "Malformed issuer or attribute\n");
601 GNUNET_free (entity_attr);
602 GNUNET_SCHEDULER_add_now (&do_error, handle);
603 return;
604 }
605 if (GNUNET_OK !=
606 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
607 strlen (tmp),
608 &handle->issuer_key))
609 {
610 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
611 "Malformed issuer key\n");
612 GNUNET_free (entity_attr);
613 GNUNET_SCHEDULER_add_now (&do_error, handle);
614 return;
615 }
616 tmp = strtok (NULL, "."); //Issuer attribute
617 if (NULL == tmp)
618 {
619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
620 "Malformed attribute\n");
621 GNUNET_free (entity_attr);
622 GNUNET_SCHEDULER_add_now (&do_error, handle);
623 return;
624 }
625 handle->issuer_attr = GNUNET_strdup (tmp);
626 GNUNET_free (entity_attr);
627
628 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
629 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
630 &key);
631 if ( GNUNET_NO ==
632 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
633 &key) )
634 {
635 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
636 "Missing subject\n");
637 GNUNET_free (entity_attr);
638 GNUNET_SCHEDULER_add_now (&do_error, handle);
639 return;
640 }
641 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
642 &key);
643 if (NULL == tmp)
644 {
645 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
646 "Malformed subject\n");
647 GNUNET_free (entity_attr);
648 GNUNET_SCHEDULER_add_now (&do_error, handle);
649 return;
650 }
651 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
652 tmp,
653 &subject_ego_lookup,
654 handle);
655}
656
657
658
659static void
660verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
661 const char* url,
662 void *cls)
663{
664 struct RequestHandle *handle = cls;
665 struct GNUNET_HashCode key;
666 struct GNUNET_JSONAPI_Document *json_obj;
667 struct GNUNET_JSONAPI_Resource *res;
668 struct GNUNET_CREDENTIAL_Credential *cred;
669 char *tmp;
670 char *entity_attr;
671 int i;
672 uint32_t credential_count;
673 uint32_t resource_count;
674 json_t *cred_json;
675 json_t *data_js;
676 json_error_t err;
677
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
679 "Connecting...\n");
680 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
681 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
682 &do_error, handle);
683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
684 "Connected\n");
685 if (NULL == handle->credential)
686 {
687 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
688 "Connecting to CREDENTIAL failed\n");
689 GNUNET_SCHEDULER_add_now (&do_error, handle);
690 return;
691 }
692 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
693 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
694 &key);
695 if ( GNUNET_NO ==
696 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
697 &key) )
698 {
699 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
700 "Missing issuer attribute\n");
701 GNUNET_SCHEDULER_add_now (&do_error, handle);
702 return;
703 }
704 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
705 &key);
706 entity_attr = GNUNET_strdup (tmp);
707 tmp = strtok(entity_attr, ".");
708 if (NULL == tmp)
709 {
710 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
711 "Malformed issuer or attribute\n");
712 GNUNET_free (entity_attr);
713 GNUNET_SCHEDULER_add_now (&do_error, handle);
714 return;
715 }
716 if (GNUNET_OK !=
717 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
718 strlen (tmp),
719 &handle->issuer_key))
720 {
721 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
722 "Malformed issuer key\n");
723 GNUNET_free (entity_attr);
724 GNUNET_SCHEDULER_add_now (&do_error, handle);
725 return;
726 }
727 tmp = strtok (NULL, "."); //Issuer attribute
728 if (NULL == tmp)
729 {
730 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
731 "Malformed attribute\n");
732 GNUNET_free (entity_attr);
733 GNUNET_SCHEDULER_add_now (&do_error, handle);
734 return;
735 }
736 handle->issuer_attr = GNUNET_strdup (tmp);
737 GNUNET_free (entity_attr);
738
739 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
740 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
741 &key);
742 if ( GNUNET_NO ==
743 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
744 &key) )
745 {
746 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
747 "Missing subject key\n");
748 GNUNET_free (entity_attr);
749 GNUNET_SCHEDULER_add_now (&do_error, handle);
750 return;
751 }
752 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
753 &key);
754 if (NULL == tmp)
755 {
756 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
757 "Malformed subject\n");
758 GNUNET_free (entity_attr);
759 GNUNET_SCHEDULER_add_now (&do_error, handle);
760 return;
761 }
762 if (GNUNET_OK !=
763 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
764 strlen (tmp),
765 &handle->subject_key)) {
766 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
767 "Malformed subject key\n");
768 GNUNET_free (entity_attr);
769 GNUNET_SCHEDULER_add_now (&do_error, handle);
770 return;
771 }
772
773 if (0 >= handle->rest_handle->data_size)
774 {
775 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
776 "Missing credentials\n");
777 GNUNET_SCHEDULER_add_now (&do_error, handle);
778 return;
779 }
780
781 struct GNUNET_JSON_Specification docspec[] = {
782 GNUNET_JSON_spec_jsonapi_document (&json_obj),
783 GNUNET_JSON_spec_end()
784 };
785 char term_data[handle->rest_handle->data_size+1];
786 term_data[handle->rest_handle->data_size] = '\0';
787 credential_count = 0;
788 GNUNET_memcpy (term_data,
789 handle->rest_handle->data,
790 handle->rest_handle->data_size);
791 data_js = json_loads (term_data,
792 JSON_DECODE_ANY,
793 &err);
794 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
795 NULL, NULL));
796 json_decref (data_js);
797 if (NULL == json_obj)
798 {
799 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
800 "Unable to parse JSONAPI Object from %s\n",
801 term_data);
802 GNUNET_SCHEDULER_add_now (&do_error, handle);
803 return;
804 }
805
806 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
807 GNUNET_assert (1 == resource_count);
808 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
809 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
810 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
811 {
812 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
813 "Resource not a credential!\n");
814 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
815 "Unable to parse JSONAPI Object from %s\n",
816 term_data);
817 GNUNET_JSONAPI_document_delete (json_obj);
818 GNUNET_SCHEDULER_add_now (&do_error, handle);
819 return;
820 }
821 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
822 GNUNET_REST_JSONAPI_CREDENTIAL);
823
824 GNUNET_assert (json_is_array (cred_json));
825
826 credential_count = json_array_size(cred_json);
827
828 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
829 for (i=0;i<credential_count;i++)
830 {
831 cred = json_to_credential (json_array_get (cred_json, i));
832 if (NULL == cred)
833 {
834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
835 "Unable to parse credential!\n");
836 continue;
837 }
838 GNUNET_memcpy (&credentials[i],
839 cred,
840 sizeof (struct GNUNET_CREDENTIAL_Credential));
841 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
842 GNUNET_free (cred);
843 }
844 GNUNET_JSONAPI_document_delete(json_obj);
845 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
846 &handle->issuer_key,
847 handle->issuer_attr,
848 &handle->subject_key,
849 credential_count,
850 credentials,
851 &handle_verify_response,
852 handle);
853 for (i=0;i<credential_count;i++)
854 GNUNET_free ((char*)credentials[i].issuer_attribute);
855
856}
857
858void
859send_cred_response (struct RequestHandle *handle,
860 struct GNUNET_CREDENTIAL_Credential *cred)
861{
862 struct MHD_Response *resp;
863 struct GNUNET_JSONAPI_Document *json_document;
864 struct GNUNET_JSONAPI_Resource *json_resource;
865 json_t *cred_obj;
866 char *result;
867 char *issuer;
868 char *subject;
869 char *signature;
870 char *id;
871
872 GNUNET_assert (NULL != cred);
873 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
874 if (NULL == issuer)
875 {
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
877 "Subject malformed\n");
878 return;
879 }
880 GNUNET_asprintf (&id,
881 "%s.%s",
882 issuer,
883 (char*)&cred[1]);
884 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
885 if (NULL == subject)
886 {
887 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
888 "Subject malformed\n");
889 return;
890 }
891 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
892 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
893 &signature);
894 json_document = GNUNET_JSONAPI_document_new ();
895 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
896 id);
897 GNUNET_free (id);
898 cred_obj = json_object();
899 json_object_set_new (cred_obj, "issuer", json_string (issuer));
900 json_object_set_new (cred_obj, "subject", json_string (subject));
901 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
902 json_object_set_new (cred_obj, "signature", json_string (signature));
903 GNUNET_JSONAPI_resource_add_attr (json_resource,
904 GNUNET_REST_JSONAPI_CREDENTIAL,
905 cred_obj);
906 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
907 GNUNET_JSONAPI_document_serialize (json_document, &result);
908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
909 "Result %s\n",
910 result);
911 json_decref (cred_obj);
912 GNUNET_JSONAPI_document_delete (json_document);
913 resp = GNUNET_REST_create_response (result);
914 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
915 GNUNET_free (result);
916 GNUNET_free (signature);
917 GNUNET_free (issuer);
918 GNUNET_free (subject);
919 cleanup_handle (handle);
920}
921
922void
923get_cred_issuer_cb (void *cls,
924 struct GNUNET_IDENTITY_Ego *ego,
925 void **ctx,
926 const char *name)
927{
928 struct RequestHandle *handle = cls;
929 struct GNUNET_TIME_Absolute etime_abs;
930 struct GNUNET_TIME_Relative etime_rel;
931 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
932 struct GNUNET_HashCode key;
933 struct GNUNET_CREDENTIAL_Credential *cred;
934 char* expiration_str;
935 char* tmp;
936
937 handle->id_op = NULL;
938
939 if (NULL == name)
940 {
941 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
942 "Issuer not configured!\n");
943 GNUNET_SCHEDULER_add_now (&do_error, handle);
944 return;
945 }
946
947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
948 "Connecting to credential service...\n");
949 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
951 "Connected\n");
952 if (NULL == handle->credential)
953 {
954 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
955 "Connecting to CREDENTIAL failed\n");
956 GNUNET_SCHEDULER_add_now (&do_error, handle);
957 return;
958 }
959 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
960 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
961 &key);
962 if ( GNUNET_NO ==
963 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
964 &key) )
965 {
966 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
967 "Missing expiration\n");
968 GNUNET_SCHEDULER_add_now (&do_error, handle);
969 return;
970 }
971 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
972 &key);
973 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
974 &etime_rel))
975 {
976 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
977 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
978 &etime_abs))
979 {
980 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
981 "Malformed expiration: %s\n", expiration_str);
982 GNUNET_SCHEDULER_add_now (&do_error, handle);
983 return;
984 }
985 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
986 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
987 &key);
988 if ( GNUNET_NO ==
989 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
990 &key) )
991 {
992 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
993 "Missing issuer attribute\n");
994 GNUNET_SCHEDULER_add_now (&do_error, handle);
995 return;
996 }
997 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
998 (handle->rest_handle->url_param_map,
999 &key));
1000 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
1001 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
1002 &key);
1003 if ( GNUNET_NO ==
1004 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
1005 &key) )
1006 {
1007 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1008 "Missing subject\n");
1009 GNUNET_SCHEDULER_add_now (&do_error, handle);
1010 return;
1011 }
1012 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1013 &key);
1014 if (NULL == tmp)
1015 {
1016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1017 "Malformed subject\n");
1018 GNUNET_SCHEDULER_add_now (&do_error, handle);
1019 return;
1020 }
1021 if (GNUNET_OK !=
1022 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1023 strlen (tmp),
1024 &handle->subject_key)) {
1025 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1026 "Malformed subject key\n");
1027 GNUNET_SCHEDULER_add_now (&do_error, handle);
1028 return;
1029 }
1030 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1031 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1032 &handle->subject_key,
1033 handle->issuer_attr,
1034 &etime_abs);
1035 if (NULL == cred)
1036 {
1037 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1038 "Failed to create credential\n");
1039 GNUNET_SCHEDULER_add_now (&do_error, handle);
1040 return;
1041 }
1042 send_cred_response (handle, cred);
1043}
1044
1045
1046static void
1047issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1048 const char* url,
1049 void *cls)
1050{
1051 struct RequestHandle *handle = cls;
1052
1053 handle->identity = GNUNET_IDENTITY_connect (cfg,
1054 NULL,
1055 NULL);
1056 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1057 "credential-issuer",
1058 &get_cred_issuer_cb,
1059 handle);
1060 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1061 &do_error,
1062 handle);
1063}
1064
1065/**
1066 * Handle rest request
1067 *
1068 * @param handle the lookup handle
1069 */
1070static void
1071options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1072 const char* url,
1073 void *cls)
1074{
1075 struct MHD_Response *resp;
1076 struct RequestHandle *handle = cls;
1077
1078 //For GNS, independent of path return all options
1079 resp = GNUNET_REST_create_response (NULL);
1080 MHD_add_response_header (resp,
1081 "Access-Control-Allow-Methods",
1082 MHD_HTTP_METHOD_GET);
1083 handle->proc (handle->proc_cls,
1084 resp,
1085 MHD_HTTP_OK);
1086 cleanup_handle (handle);
1087}
1088
1089
1090/**
1091 * Function processing the REST call
1092 *
1093 * @param method HTTP method
1094 * @param url URL of the HTTP request
1095 * @param data body of the HTTP request (optional)
1096 * @param data_size length of the body
1097 * @param proc callback function for the result
1098 * @param proc_cls closure for callback function
1099 * @return GNUNET_OK if request accepted
1100 */
1101static void
1102rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1103 GNUNET_REST_ResultProcessor proc,
1104 void *proc_cls)
1105{
1106 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1107 struct GNUNET_REST_RequestHandlerError err;
1108
1109 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1110 handle->proc_cls = proc_cls;
1111 handle->proc = proc;
1112 handle->rest_handle = conndata_handle;
1113
1114 static const struct GNUNET_REST_RequestHandler handlers[] = {
1115 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1116 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1117 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1118 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1119 GNUNET_REST_HANDLER_END
1120 };
1121
1122 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1123 handlers,
1124 &err,
1125 handle))
1126 {
1127 handle->response_code = err.error_code;
1128 GNUNET_SCHEDULER_add_now (&do_error, handle);
1129 }
1130}
1131
1132
1133/**
1134 * Entry point for the plugin.
1135 *
1136 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1137 * @return NULL on error, otherwise the plugin context
1138 */
1139void *
1140libgnunet_plugin_rest_credential_init (void *cls)
1141{
1142 static struct Plugin plugin;
1143 cfg = cls;
1144 struct GNUNET_REST_Plugin *api;
1145
1146 if (NULL != plugin.cfg)
1147 return NULL; /* can only initialize once! */
1148 memset (&plugin, 0, sizeof (struct Plugin));
1149 plugin.cfg = cfg;
1150 api = GNUNET_new (struct GNUNET_REST_Plugin);
1151 api->cls = &plugin;
1152 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1153 api->process_request = &rest_credential_process_request;
1154 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1155 _("GNS REST API initialized\n"));
1156 return api;
1157}
1158
1159
1160/**
1161 * Exit point from the plugin.
1162 *
1163 * @param cls the plugin context (as returned by "init")
1164 * @return always NULL
1165 */
1166void *
1167libgnunet_plugin_rest_credential_done (void *cls)
1168{
1169 struct GNUNET_REST_Plugin *api = cls;
1170 struct Plugin *plugin = api->cls;
1171
1172 plugin->cfg = NULL;
1173 GNUNET_free (api);
1174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1175 "GNS REST plugin is finished\n");
1176 return NULL;
1177}
1178
1179/* 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..833d36f95
--- /dev/null
+++ b/src/credential/test_credential_verify_and.sh
@@ -0,0 +1,81 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR,$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
52
53# (5) GNUnet issues Alice the credential "developer"
54CRED1=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
55# (5) GNUnet issues Alice the credential "user"
56CRED2=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
57
58
59# Alice stores the credential under "mygnunetcreds"
60gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED1" -e 5m -c test_credential_lookup.conf
61gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m -c test_credential_lookup.conf
62
63#TODO2 Add -z swich like in gnunet-gns
64RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
65
66
67#TODO cleanup properly
68gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
69gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
70gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
71gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
72gnunet-arm -e -c test_credential_lookup.conf
73
74if [ "$RES_CRED" != "Failed." ]
75then
76 echo -e "${RES_CRED}"
77 exit 0
78else
79 echo "FAIL: Failed to verify credential $RES_CRED."
80 exit 1
81fi
diff --git a/src/credential/test_credential_verify_rest.sh b/src/credential/test_credential_verify_rest.sh
new file mode 100755
index 000000000..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