aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am14
-rw-r--r--src/abe/Makefile.am50
-rw-r--r--src/abe/abe.c499
-rw-r--r--src/abe/test_cpabe.c87
-rw-r--r--src/credential/Makefile.am112
-rw-r--r--src/credential/credential.conf.in5
-rw-r--r--src/credential/credential.h221
-rw-r--r--src/credential/credential_api.c511
-rw-r--r--src/credential/credential_misc.c168
-rw-r--r--src/credential/credential_misc.h35
-rw-r--r--src/credential/credential_serialization.c460
-rw-r--r--src/credential/credential_serialization.h159
-rw-r--r--src/credential/gnunet-credential.c588
-rw-r--r--src/credential/gnunet-service-credential.c1160
-rw-r--r--src/credential/plugin_gnsrecord_credential.c353
-rw-r--r--src/credential/plugin_rest_credential.c1146
-rwxr-xr-xsrc/credential/test_credential_collect.sh47
-rwxr-xr-xsrc/credential/test_credential_collect_rest.sh90
-rw-r--r--src/credential/test_credential_defaults.conf24
-rwxr-xr-xsrc/credential/test_credential_issue.sh44
-rwxr-xr-xsrc/credential/test_credential_issue_rest.sh53
-rw-r--r--src/credential/test_credential_lookup.conf28
-rwxr-xr-xsrc/credential/test_credential_verify.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_and.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_rest.sh87
-rwxr-xr-xsrc/credential/test_credential_verify_simple.sh50
-rw-r--r--src/exit/gnunet-daemon-exit.c2
-rw-r--r--src/gns/gns_api.c11
-rw-r--r--src/gns/plugin_gnsrecord_gns.c67
-rw-r--r--src/identity-attribute/Makefile.am44
-rw-r--r--src/identity-attribute/identity_attribute.c421
-rw-r--r--src/identity-attribute/identity_attribute.h56
-rw-r--r--src/identity-attribute/plugin_identity_attribute_gnuid.c184
-rw-r--r--src/identity-provider/Makefile.am74
-rw-r--r--src/identity-provider/gnunet-identity-token.c179
-rw-r--r--src/identity-provider/gnunet-idp.c439
-rw-r--r--src/identity-provider/gnunet-service-identity-provider.c3064
-rw-r--r--src/identity-provider/identity-provider.conf4
-rw-r--r--src/identity-provider/identity_provider.h307
-rw-r--r--src/identity-provider/identity_provider_api.c1213
-rw-r--r--src/identity-provider/identity_token.c964
-rw-r--r--src/identity-provider/identity_token.h346
-rw-r--r--src/identity-provider/jwt.c180
-rw-r--r--src/identity-provider/plugin_gnsrecord_identity_provider.c (renamed from src/identity/plugin_gnsrecord_identity.c)48
-rw-r--r--src/identity-provider/plugin_identity_provider_sqlite.c736
-rw-r--r--src/identity-provider/plugin_rest_identity_provider.c1119
-rw-r--r--src/identity-provider/test_idp.conf28
-rwxr-xr-xsrc/identity-provider/test_idp.sh31
-rwxr-xr-xsrc/identity-provider/test_idp_attribute.sh40
-rwxr-xr-xsrc/identity-provider/test_idp_consume.sh43
-rw-r--r--src/identity-provider/test_idp_defaults.conf24
-rwxr-xr-xsrc/identity-provider/test_idp_issue.sh42
-rwxr-xr-xsrc/identity-provider/test_idp_revoke.sh60
-rw-r--r--src/identity/Makefile.am11
-rw-r--r--src/identity/plugin_rest_identity.c3
-rw-r--r--src/include/gnunet_abe_lib.h193
-rw-r--r--src/include/gnunet_credential_service.h297
-rw-r--r--src/include/gnunet_gnsrecord_lib.h22
-rw-r--r--src/include/gnunet_identity_attribute_lib.h277
-rw-r--r--src/include/gnunet_identity_attribute_plugin.h149
-rw-r--r--src/include/gnunet_identity_provider_plugin.h123
-rw-r--r--src/include/gnunet_identity_provider_service.h333
-rw-r--r--src/include/gnunet_jsonapi_lib.h2
-rw-r--r--src/include/gnunet_protocols.h42
-rw-r--r--src/include/gnunet_rest_lib.h4
-rw-r--r--src/include/gnunet_rest_plugin.h2
-rw-r--r--src/include/gnunet_signatures.h5
-rw-r--r--src/jsonapi/jsonapi_document.c32
-rw-r--r--src/jsonapi/jsonapi_resource.c6
-rw-r--r--src/namestore/plugin_rest_namestore.c27
-rw-r--r--src/rest/rest.conf1
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/crypto_abe.c416
73 files changed, 14093 insertions, 3732 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7f1a00177..6d0284157 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,11 +12,12 @@ endif
12if HAVE_EXPERIMENTAL 12if HAVE_EXPERIMENTAL
13 EXP_DIR = \ 13 EXP_DIR = \
14 rps 14 rps
15endif 15# dv (FTBFS)
16 16if HAVE_ABE
17if HAVE_JSON 17 EXP_DIR += abe \
18if HAVE_MHD 18 credential \
19 PROVIDER_DIR = identity-provider 19 identity-attribute \
20 identity-provider
20endif 21endif
21endif 22endif
22 23
@@ -128,7 +129,6 @@ SUBDIRS = \
128 psyc \ 129 psyc \
129 social \ 130 social \
130 $(AUCTION_DIR) \ 131 $(AUCTION_DIR) \
131 $(EXP_DIR) \ 132 $(EXP_DIR)
132 $(PROVIDER_DIR)
133 133
134endif 134endif
diff --git a/src/abe/Makefile.am b/src/abe/Makefile.am
new file mode 100644
index 000000000..308e6c67c
--- /dev/null
+++ b/src/abe/Makefile.am
@@ -0,0 +1,50 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6libexecdir= $(pkglibdir)/libexec/
7
8pkgcfgdir= $(pkgdatadir)/config.d/
9
10dist_pkgcfg_DATA = \
11 abe.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = --coverage -O0
15 XLIB = -lgcov
16endif
17
18libgnunetabe_la_SOURCES = abe.c
19
20libgnunetabe_la_LIBADD = \
21 $(GCLIBADD)\
22 $(LIBGCRYPT_LIBS) \
23 $(LTLIBICONV) \
24 $(LTLIBINTL) \
25 $(ABE_LIBADD) \
26 -lgabe \
27 -lpbc \
28 -lglib-2.0 \
29 -lltdl $(Z_LIBS) -lunistring $(XLIB)
30
31libgnunetabe_la_LDFLAGS = \
32 $(GN_LIB_LDFLAGS) \
33 -version-info 1:0:0
34
35lib_LTLIBRARIES = libgnunetabe.la
36
37if ENABLE_TEST_RUN
38AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
39TESTS = $(check_PROGRAMS)
40endif
41
42check_PROGRAMS = test_cpabe
43
44test_cpabe_SOURCES = \
45 test_cpabe.c
46test_cpabe_LDADD = \
47 libgnunetabe.la \
48 $(top_builddir)/src/util/libgnunetutil.la
49check_PROGRAMS += \
50 test_cpabe
diff --git a/src/abe/abe.c b/src/abe/abe.c
new file mode 100644
index 000000000..3f1f6dc5b
--- /dev/null
+++ b/src/abe/abe.c
@@ -0,0 +1,499 @@
1/*
2 This file is part of GNUnet. Copyright (C) 2001-2018 Christian Grothoff
3 (and other contributing authors)
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 abe/abe.c
24 * @brief functions for Attribute-Based Encryption
25 * @author Martin Schanzenbach
26 */
27
28
29#include "platform.h"
30#include <pbc/pbc.h>
31#include <gabe.h>
32
33#include "gnunet_crypto_lib.h"
34#include "gnunet_abe_lib.h"
35
36struct GNUNET_ABE_AbeMasterKey
37{
38 gabe_pub_t* pub;
39 gabe_msk_t* msk;
40};
41
42struct GNUNET_ABE_AbeKey
43{
44 gabe_pub_t* pub;
45 gabe_prv_t* prv;
46};
47
48static int
49init_aes( element_t k, int enc,
50 gcry_cipher_hd_t* handle,
51 struct GNUNET_CRYPTO_SymmetricSessionKey *key,
52 unsigned char* iv)
53{
54 int rc;
55 int key_len;
56 unsigned char* key_buf;
57
58 key_len = element_length_in_bytes(k) < 33 ? 3 : element_length_in_bytes(k);
59 key_buf = (unsigned char*) malloc(key_len);
60 element_to_bytes(key_buf, k);
61
62 memcpy (key->aes_key, key_buf, GNUNET_CRYPTO_AES_KEY_LENGTH);
63 GNUNET_assert (0 ==
64 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
65 GCRY_CIPHER_MODE_CFB, 0));
66 rc = gcry_cipher_setkey (*handle,
67 key->aes_key,
68 sizeof (key->aes_key));
69 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
70 memset (iv, 0, 16); //TODO make reasonable
71 rc = gcry_cipher_setiv (*handle,
72 iv,
73 16);
74 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
75
76 free(key_buf);
77 return rc;
78}
79
80static int
81aes_128_cbc_encrypt( char* pt,
82 int size,
83 element_t k,
84 char **ct )
85{
86 gcry_cipher_hd_t handle;
87 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
88 unsigned char iv[16];
89 char* buf;
90 int padding;
91 int buf_size;
92 uint8_t len[4];
93 init_aes(k, 1, &handle, &skey, iv);
94
95 /* TODO make less crufty */
96
97 /* stuff in real length (big endian) before padding */
98 len[0] = (size & 0xff000000)>>24;
99 len[1] = (size & 0xff0000)>>16;
100 len[2] = (size & 0xff00)>>8;
101 len[3] = (size & 0xff)>>0;
102 padding = 16 - ((4+size) % 16);
103 buf_size = 4 + size + padding;
104 buf = GNUNET_malloc (buf_size);
105 GNUNET_memcpy (buf, len, 4);
106 GNUNET_memcpy (buf+4, pt, size);
107 *ct = GNUNET_malloc (buf_size);
108
109 GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf, buf_size));
110 gcry_cipher_close (handle);
111 //AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
112 GNUNET_free (buf);
113 return buf_size;
114}
115
116static int
117aes_128_cbc_decrypt( char* ct,
118 int size,
119 element_t k,
120 char **pt )
121{
122 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
123 gcry_cipher_hd_t handle;
124 unsigned char iv[16];
125 char* tmp;
126 uint32_t len;
127
128 init_aes(k, 1, &handle, &skey, iv);
129
130 tmp = GNUNET_malloc (size);
131
132 //AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
133 GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size));
134 gcry_cipher_close (handle);
135 /* TODO make less crufty */
136
137 /* get real length */
138 len = 0;
139 len = len
140 | ((tmp[0])<<24) | ((tmp[1])<<16)
141 | ((tmp[2])<<8) | ((tmp[3])<<0);
142 /* truncate any garbage from the padding */
143 *pt = GNUNET_malloc (len);
144 GNUNET_memcpy (*pt, tmp+4, len);
145 GNUNET_free (tmp);
146 return len;
147}
148
149/**
150 * @ingroup abe
151 * Create a new CP-ABE master key. Caller must free return value.
152 *
153 * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
154 */
155struct GNUNET_ABE_AbeMasterKey*
156GNUNET_ABE_cpabe_create_master_key (void)
157{
158 struct GNUNET_ABE_AbeMasterKey* key;
159 key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
160 gabe_setup(&key->pub, &key->msk);
161 GNUNET_assert (NULL != key->pub);
162 GNUNET_assert (NULL != key->msk);
163 return key;
164}
165
166/**
167 * @ingroup abe
168 * Delete a CP-ABE master key.
169 *
170 * @param key the master key
171 * @return fresh private key; free using #GNUNET_free
172 */
173void
174GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key)
175{
176 gabe_msk_free (key->msk);
177 gabe_pub_free (key->pub);
178 //GNUNET_free (key->msk);
179 //gabe_msk_free (key->msk); //For some reason free of pub implicit?
180 GNUNET_free (key);
181}
182
183/**
184 * @ingroup abe
185 * Create a new CP-ABE key. Caller must free return value.
186 *
187 * @param key the master key
188 * @param attrs the attributes to append to the key
189 * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
190 */
191struct GNUNET_ABE_AbeKey*
192GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
193 char **attrs)
194{
195 struct GNUNET_ABE_AbeKey *prv_key;
196 int size;
197 char *tmp;
198
199 prv_key = GNUNET_new (struct GNUNET_ABE_AbeKey);
200 prv_key->prv = gabe_keygen(key->pub, key->msk, attrs);
201 size = gabe_pub_serialize(key->pub, &tmp);
202 prv_key->pub = gabe_pub_unserialize(tmp, size);
203 GNUNET_free (tmp);
204 GNUNET_assert (NULL != prv_key->prv);
205 return prv_key;
206}
207
208/**
209 * @ingroup abe
210 * Delete a CP-ABE key.
211 *
212 * @param key the key to delete
213 * @param delete_pub GNUNE_YES if the public key should also be freed (bug in gabe)
214 * @return fresh private key; free using #GNUNET_free
215 */
216void
217GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
218 int delete_pub)
219{
220 //Memory management in gabe is buggy
221 gabe_prv_free (key->prv);
222 if (GNUNET_YES == delete_pub)
223 gabe_pub_free (key->pub);
224 GNUNET_free (key);
225}
226
227static ssize_t
228write_cpabe (void **result,
229 uint32_t file_len,
230 char* cph_buf,
231 int cph_buf_len,
232 char* aes_buf,
233 int aes_buf_len)
234{
235 char *ptr;
236 uint32_t *len;
237
238 *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
239 ptr = *result;
240 len = (uint32_t*) ptr;
241 *len = htonl (file_len);
242 ptr += 4;
243 len = (uint32_t*) ptr;
244 *len = htonl (aes_buf_len);
245 ptr += 4;
246 memcpy (ptr, aes_buf, aes_buf_len);
247 ptr += aes_buf_len;
248 len = (uint32_t*) ptr;
249 *len = htonl (cph_buf_len);
250 ptr += 4;
251 memcpy (ptr, cph_buf, cph_buf_len);
252 return 12 + cph_buf_len + aes_buf_len;
253}
254
255static ssize_t
256read_cpabe (const void *data,
257 char** cph_buf,
258 int *cph_buf_len,
259 char** aes_buf,
260 int *aes_buf_len)
261{
262 int buf_len;
263 char *ptr;
264 uint32_t *len;
265
266 ptr = (char*)data;
267 len = (uint32_t*)ptr;
268 buf_len = ntohl (*len);
269 ptr += 4;
270 len = (uint32_t*)ptr;
271 *aes_buf_len = ntohl (*len);
272 ptr += 4;
273 *aes_buf = GNUNET_malloc (*aes_buf_len);
274 memcpy(*aes_buf, ptr, *aes_buf_len);
275 ptr += *aes_buf_len;
276 len = (uint32_t*)ptr;
277 *cph_buf_len = ntohl (*len);
278 ptr += 4;
279 *cph_buf = GNUNET_malloc (*cph_buf_len);
280 memcpy(*cph_buf, ptr, *cph_buf_len);
281
282 return buf_len;
283}
284
285/**
286 * @ingroup abe
287 * Encrypt a block using sessionkey.
288 *
289 * @param block the block to encrypt
290 * @param size the size of the @a block
291 * @param policy the ABE policy
292 * @param key the key used to encrypt
293 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
294 * @return the size of the encrypted block, -1 for errors
295 */
296ssize_t
297GNUNET_ABE_cpabe_encrypt (const void *block,
298 size_t size,
299 const char *policy,
300 const struct GNUNET_ABE_AbeMasterKey *key,
301 void **result)
302{
303 gabe_cph_t* cph;
304 char* plt;
305 char* cph_buf;
306 char* aes_buf;
307 element_t m;
308 int cph_buf_len;
309 int aes_buf_len;
310 ssize_t result_len;
311
312 if( !(cph = gabe_enc(key->pub, m, (char*)policy)) )
313 return GNUNET_SYSERR;
314 cph_buf_len = gabe_cph_serialize(cph,
315 &cph_buf);
316 gabe_cph_free(cph);
317 GNUNET_free (cph);
318 plt = GNUNET_memdup (block, size);
319 aes_buf_len = aes_128_cbc_encrypt(plt, size, m, &aes_buf);
320 GNUNET_free (plt);
321 element_clear(m);
322 result_len = write_cpabe(result, size, cph_buf, cph_buf_len, aes_buf, aes_buf_len);
323 GNUNET_free(cph_buf);
324 GNUNET_free(aes_buf);
325 return result_len;
326}
327
328/**
329 * @ingroup abe
330 * Decrypt a block using the ABE key.
331 *
332 * @param block the block to encrypt
333 * @param size the size of the @a block
334 * @param key the key used to decrypt
335 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
336 * @return the size of the encrypted block, -1 for errors
337 */
338ssize_t
339GNUNET_ABE_cpabe_decrypt (const void *block,
340 size_t size,
341 const struct GNUNET_ABE_AbeKey *key,
342 void **result)
343{
344 char* aes_buf;
345 char* cph_buf;
346 gabe_cph_t* cph;
347 element_t m;
348 int cph_buf_size;
349 int aes_buf_size;
350 int plt_len;
351
352 read_cpabe(block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
353 cph = gabe_cph_unserialize(key->pub, cph_buf, cph_buf_size);
354 if( !gabe_dec(key->pub, key->prv, cph, m) ) {
355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
356 "%s\n", gabe_error());
357 GNUNET_free (aes_buf);
358 GNUNET_free (cph_buf);
359 gabe_cph_free(cph);
360 GNUNET_free (cph);
361 element_clear (m);
362 return GNUNET_SYSERR;
363 }
364 gabe_cph_free(cph);
365 GNUNET_free (cph);
366 plt_len = aes_128_cbc_decrypt(aes_buf, aes_buf_size, m, (char**)result);
367 GNUNET_free (cph_buf);
368 GNUNET_free (aes_buf);
369 element_clear (m);
370 //freeing is buggy in gabe
371 //gabe_prv_free (prv);
372 //gabe_pub_free (pub);
373 return plt_len;
374}
375
376/**
377 * @ingroup abe
378 * Serialize an ABE key.
379 *
380 * @param key the key to serialize
381 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
382 * @return the size of the encrypted block, -1 for errors
383 */
384ssize_t
385GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
386 void **result)
387{
388 ssize_t len;
389 char *pub;
390 char *prv;
391 int pub_len;
392 int prv_len;
393
394 pub_len = gabe_pub_serialize (key->pub, &pub);
395 prv_len = gabe_prv_serialize (key->prv, &prv);
396
397 len = pub_len + prv_len + 12;
398 write_cpabe (result, len, pub, pub_len, prv, prv_len);
399
400 GNUNET_free (pub);
401 GNUNET_free (prv);
402
403 return len;
404}
405
406/**
407 * @ingroup abe
408 * Deserialize a serialized ABE key.
409 *
410 * @param data the data to deserialize
411 * @param len the length of the data.
412 * @return the ABE key. NULL of unsuccessful
413 */
414struct GNUNET_ABE_AbeKey*
415GNUNET_ABE_cpabe_deserialize_key (const void *data,
416 size_t len)
417{
418 struct GNUNET_ABE_AbeKey *key;
419 char *pub;
420 char *prv;
421 int prv_len;
422 int pub_len;
423
424 key = GNUNET_new (struct GNUNET_ABE_AbeKey);
425 read_cpabe (data,
426 &pub,
427 &pub_len,
428 &prv,
429 &prv_len);
430 key->pub = gabe_pub_unserialize (pub, pub_len);
431 key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
432
433 GNUNET_free (pub);
434 GNUNET_free (prv);
435 return key;
436}
437
438/**
439 * @ingroup abe
440 * Serialize an ABE master key.
441 *
442 * @param key the key to serialize
443 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
444 * @return the size of the encrypted block, -1 for errors
445 */
446ssize_t
447GNUNET_ABE_cpabe_serialize_master_key (const struct GNUNET_ABE_AbeMasterKey *key,
448 void **result)
449{
450 ssize_t len;
451 char *pub;
452 char *msk;
453 int pub_len;
454 int msk_len;
455
456 pub_len = gabe_pub_serialize (key->pub, &pub);
457 msk_len = gabe_msk_serialize (key->msk, &msk);
458
459 len = pub_len + msk_len + 12;
460 write_cpabe (result, len, pub, pub_len, msk, msk_len);
461
462 GNUNET_free (pub);
463 GNUNET_free (msk);
464
465 return len;
466}
467
468/**
469 * @ingroup abe
470 * Deserialize an ABE master key.
471 *
472 * @param data the data to deserialize
473 * @param len the length of the data.
474 * @return the ABE key. NULL of unsuccessful
475 */
476struct GNUNET_ABE_AbeMasterKey*
477GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
478 size_t len)
479{
480 struct GNUNET_ABE_AbeMasterKey *key;
481 char *msk;
482 char *pub;
483 int msk_len;
484 int pub_len;
485
486 key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
487 read_cpabe (data,
488 &pub,
489 &pub_len,
490 &msk,
491 &msk_len);
492 key->pub = gabe_pub_unserialize (pub, pub_len);
493 key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
494
495 GNUNET_free (pub);
496 GNUNET_free (msk);
497
498 return key;
499}
diff --git a/src/abe/test_cpabe.c b/src/abe/test_cpabe.c
new file mode 100644
index 000000000..9b2062b23
--- /dev/null
+++ b/src/abe/test_cpabe.c
@@ -0,0 +1,87 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2002, 2003, 2004, 2006 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 * @author Martin Schanzenbach
23 * @file util/test_crypto_abe.c
24 * @brief test for ABE ciphers
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_abe_lib.h"
29
30#define TESTSTRING "Hello World!"
31
32static int
33testAbecipher ()
34{
35 struct GNUNET_ABE_AbeMasterKey *msk;
36 struct GNUNET_ABE_AbeKey *key;
37 char *result;
38 char **attrs;
39 int size;
40 char *res;
41 msk = GNUNET_ABE_cpabe_create_master_key ();
42 size = GNUNET_ABE_cpabe_encrypt (TESTSTRING, strlen (TESTSTRING) + 1,
43 "testattr", //Policy
44 msk,
45 (void*)&result);
46 GNUNET_assert (-1 != size);
47 attrs = GNUNET_malloc (2 * sizeof (char*));
48 attrs[0] = "testattr";
49 attrs[1] = NULL;
50 key = GNUNET_ABE_cpabe_create_key (msk,
51 attrs);
52
53 size = GNUNET_ABE_cpabe_decrypt (result, size,
54 key,
55 (void*)&res);
56 if (strlen (TESTSTRING) + 1 != size)
57 {
58 printf ("abeciphertest failed: decryptBlock returned %d\n", size);
59 return 1;
60 }
61 if (0 != strcmp (res, TESTSTRING))
62 {
63 printf ("abeciphertest failed: %s != %s\n", res, TESTSTRING);
64 return 1;
65 }
66 else
67 return 0;
68}
69
70
71int
72main (int argc, char *argv[])
73{
74 int failureCount = 0;
75
76 GNUNET_log_setup ("test-crypto-abe", "WARNING", NULL);
77 failureCount += testAbecipher ();
78
79 if (failureCount != 0)
80 {
81 printf ("%d TESTS FAILED!\n", failureCount);
82 return -1;
83 }
84 return 0;
85}
86
87/* end of test_crypto_aes.c */
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
new file mode 100644
index 000000000..ca11c5e4f
--- /dev/null
+++ b/src/credential/Makefile.am
@@ -0,0 +1,112 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4EXTRA_DIST = \
5 test_credential_defaults.conf \
6 test_credential_lookup.conf
7
8
9if USE_COVERAGE
10 AM_CFLAGS = --coverage -O0
11endif
12
13pkgcfgdir = $(pkgdatadir)/config.d/
14
15libexecdir= $(pkglibdir)/libexec/
16
17plugindir = $(libdir)/gnunet
18
19pkgcfg_DATA = \
20 credential.conf
21
22
23# /usr/lib - compiles a layer which can be used to be communicagte with the service
24lib_LTLIBRARIES = \
25 libgnunetcredential.la
26
27# /usr/lib/gnunet/libexec - Business logic . Separate process
28libexec_PROGRAMS = \
29 gnunet-service-credential
30
31bin_PROGRAMS = \
32 gnunet-credential
33
34plugin_LTLIBRARIES = \
35 libgnunet_plugin_gnsrecord_credential.la
36
37
38if HAVE_MHD
39if HAVE_JSON
40plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la
41endif
42endif
43
44
45gnunet_credential_SOURCES = \
46 gnunet-credential.c
47gnunet_credential_LDADD = \
48 libgnunetcredential.la \
49 $(top_builddir)/src/util/libgnunetutil.la \
50 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
51 $(top_builddir)/src/identity/libgnunetidentity.la \
52 $(GN_LIBINTL)
53
54
55libgnunet_plugin_gnsrecord_credential_la_SOURCES = \
56 plugin_gnsrecord_credential.c
57libgnunet_plugin_gnsrecord_credential_la_LIBADD = \
58 libgnunetcredential.la \
59 $(top_builddir)/src/util/libgnunetutil.la \
60 $(LTLIBINTL)
61libgnunet_plugin_gnsrecord_credential_la_LDFLAGS = \
62 $(GN_PLUGIN_LDFLAGS)
63
64
65
66gnunet_service_credential_SOURCES = \
67 gnunet-service-credential.c
68gnunet_service_credential_LDADD = \
69 libgnunetcredential.la \
70 $(top_builddir)/src/util/libgnunetutil.la \
71 $(top_builddir)/src/gns/libgnunetgns.la \
72 $(top_builddir)/src/namestore/libgnunetnamestore.la \
73 $(top_builddir)/src/statistics/libgnunetstatistics.la \
74 $(GN_LIBINTL)
75
76
77libgnunetcredential_la_SOURCES = \
78 credential_api.c \
79 credential_serialization.c \
80 credential_misc.c
81libgnunetcredential_la_LIBADD = \
82 $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
83libgnunetcredential_la_LDFLAGS = \
84 $(GN_LIB_LDFLAGS)
85
86
87libgnunet_plugin_rest_credential_la_SOURCES = \
88 plugin_rest_credential.c
89libgnunet_plugin_rest_credential_la_LIBADD = \
90 libgnunetcredential.la \
91 $(top_builddir)/src/rest/libgnunetrest.la \
92 $(top_builddir)/src/identity/libgnunetidentity.la \
93 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
94 $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
95 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
96 $(LTLIBINTL) -ljansson -lmicrohttpd
97libgnunet_plugin_rest_credential_la_LDFLAGS = \
98 $(GN_PLUGIN_LDFLAGS)
99
100
101check_SCRIPTS = \
102 test_credential_issue.sh \
103 test_credential_verify_simple.sh \
104 test_credential_verify.sh \
105 test_credential_verify_and.sh
106
107if ENABLE_TEST_RUN
108if HAVE_SQLITE
109 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
110 TESTS = $(check_SCRIPTS)
111endif
112endif
diff --git a/src/credential/credential.conf.in b/src/credential/credential.conf.in
new file mode 100644
index 000000000..71f3066ca
--- /dev/null
+++ b/src/credential/credential.conf.in
@@ -0,0 +1,5 @@
1[credential]
2BINARY = gnunet-service-credential
3UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-credential.sock
4USER_SERVICE = YES
5OPTIONS = -L DEBUG \ No newline at end of file
diff --git a/src/credential/credential.h b/src/credential/credential.h
new file mode 100644
index 000000000..66a4636fc
--- /dev/null
+++ b/src/credential/credential.h
@@ -0,0 +1,221 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @file credential/credential.h
22 * @brief IPC messages between CREDENTIAL API and CREDENTIAL service
23 * @author Martin Schanzenbach
24 */
25#ifndef CREDENTIAL_H
26#define CREDENTIAL_H
27
28#include "gnunet_credential_service.h"
29
30GNUNET_NETWORK_STRUCT_BEGIN
31
32/**
33 * Message from client to Credential service to collect credentials.
34 */
35struct CollectMessage
36{
37 /**
38 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
39 */
40 struct GNUNET_MessageHeader header;
41
42 /**
43 * Subject public key
44 */
45 struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key;
46
47 /**
48 * Trust anchor
49 */
50 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
51
52 /**
53 * Length of the issuer attribute
54 */
55 uint16_t issuer_attribute_len;
56
57 /**
58 * Unique identifier for this request (for key collisions).
59 */
60 uint32_t id GNUNET_PACKED;
61
62 /* Followed by the zero-terminated attribute */
63
64};
65
66
67/**
68 * Message from client to Credential service to verify attributes.
69 */
70struct VerifyMessage
71{
72 /**
73 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
74 */
75 struct GNUNET_MessageHeader header;
76
77 /**
78 * Subject public key
79 */
80 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
81
82 /**
83 * Trust anchor
84 */
85 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
86
87 /**
88 * Number of credentials
89 */
90 uint32_t c_count;
91
92 /**
93 * Length of the issuer attribute
94 */
95 uint16_t issuer_attribute_len;
96
97 /**
98 * Unique identifier for this request (for key collisions).
99 */
100 uint32_t id GNUNET_PACKED;
101
102 /* Followed by the zero-terminated attribute and credentials to look up */
103
104};
105
106
107/**
108 * Message from CREDENTIAL service to client: new results.
109 */
110struct DelegationChainResultMessage
111{
112 /**
113 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT
114 */
115 struct GNUNET_MessageHeader header;
116
117 /**
118 * Unique identifier for this request (for key collisions).
119 */
120 uint32_t id GNUNET_PACKED;
121
122 /**
123 * Indicates if credential has been found at all
124 */
125 uint32_t cred_found GNUNET_PACKED;
126
127 /**
128 * The number of delegations in the response
129 */
130 uint32_t d_count GNUNET_PACKED;
131
132 /**
133 * The number of credentials in the response
134 */
135 uint32_t c_count GNUNET_PACKED;
136
137 /* followed by ad_count GNUNET_CREDENTIAL_RecordData structs*/
138
139};
140
141struct DelegationRecordData
142{
143 /**
144 * Subject key
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
147
148 /**
149 * Subject attributes
150 */
151 uint32_t subject_attribute_len GNUNET_PACKED;
152};
153
154
155struct ChainEntry
156{
157 /**
158 * Issuer key
159 */
160 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
161
162 /**
163 * Subject key
164 */
165 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
166
167 /**
168 * Issuer attributes
169 */
170 uint32_t issuer_attribute_len GNUNET_PACKED;
171
172 /**
173 * Subject attributes
174 */
175 uint32_t subject_attribute_len GNUNET_PACKED;
176};
177
178
179struct CredentialEntry
180{
181
182 /**
183 * The signature for this credential by the issuer
184 */
185 struct GNUNET_CRYPTO_EcdsaSignature signature;
186
187 /**
188 * Signature meta
189 */
190 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
191
192 /**
193 * Public key of the issuer
194 */
195 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
196
197 /**
198 * Public key of the subject this credential was issued to
199 */
200 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
201
202 /**
203 * Expiration time of this credential
204 */
205 uint64_t expiration GNUNET_PACKED;
206
207 /**
208 * Issuer attribute length
209 */
210 uint32_t issuer_attribute_len;
211
212 /**
213 * Followed by the attribute string
214 */
215};
216
217
218GNUNET_NETWORK_STRUCT_END
219
220#endif
221
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
new file mode 100644
index 000000000..677cb9ad4
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,511 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file credential/credential_api.c
22 * @brief library to access the CREDENTIAL service
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_constants.h"
28#include "gnunet_arm_service.h"
29#include "gnunet_hello_lib.h"
30#include "gnunet_protocols.h"
31#include "gnunet_signatures.h"
32#include "credential.h"
33#include "credential_serialization.h"
34#include "gnunet_credential_service.h"
35#include "gnunet_identity_service.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
39
40/**
41 * Handle to a verify request
42 */
43struct GNUNET_CREDENTIAL_Request
44{
45
46 /**
47 * DLL
48 */
49 struct GNUNET_CREDENTIAL_Request *next;
50
51 /**
52 * DLL
53 */
54 struct GNUNET_CREDENTIAL_Request *prev;
55
56 /**
57 * handle to credential service
58 */
59 struct GNUNET_CREDENTIAL_Handle *credential_handle;
60
61 /**
62 * processor to call on verify result
63 */
64 GNUNET_CREDENTIAL_CredentialResultProcessor verify_proc;
65
66 /**
67 * @e verify_proc closure
68 */
69 void *proc_cls;
70
71 /**
72 * Envelope with the message for this queue entry.
73 */
74 struct GNUNET_MQ_Envelope *env;
75
76 /**
77 * request id
78 */
79 uint32_t r_id;
80
81};
82
83
84/**
85 * Connection to the CREDENTIAL service.
86 */
87struct GNUNET_CREDENTIAL_Handle
88{
89
90 /**
91 * Configuration to use.
92 */
93 const struct GNUNET_CONFIGURATION_Handle *cfg;
94
95 /**
96 * Connection to service (if available).
97 */
98 struct GNUNET_MQ_Handle *mq;
99
100 /**
101 * Head of linked list of active verify requests.
102 */
103 struct GNUNET_CREDENTIAL_Request *request_head;
104
105 /**
106 * Tail of linked list of active verify requests.
107 */
108 struct GNUNET_CREDENTIAL_Request *request_tail;
109
110 /**
111 * Reconnect task
112 */
113 struct GNUNET_SCHEDULER_Task *reconnect_task;
114
115 /**
116 * How long do we wait until we try to reconnect?
117 */
118 struct GNUNET_TIME_Relative reconnect_backoff;
119
120 /**
121 * Request Id generator. Incremented by one for each request.
122 */
123 uint32_t r_id_gen;
124
125};
126
127
128/**
129 * Reconnect to CREDENTIAL service.
130 *
131 * @param handle the handle to the CREDENTIAL service
132 */
133static void
134reconnect (struct GNUNET_CREDENTIAL_Handle *handle);
135
136
137/**
138 * Reconnect to CREDENTIAL
139 *
140 * @param cls the handle
141 */
142static void
143reconnect_task (void *cls)
144{
145 struct GNUNET_CREDENTIAL_Handle *handle = cls;
146
147 handle->reconnect_task = NULL;
148 reconnect (handle);
149}
150
151
152/**
153 * Disconnect from service and then reconnect.
154 *
155 * @param handle our handle
156 */
157static void
158force_reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
159{
160 GNUNET_MQ_destroy (handle->mq);
161 handle->mq = NULL;
162 handle->reconnect_backoff
163 = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
164 handle->reconnect_task
165 = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
166 &reconnect_task,
167 handle);
168}
169
170
171/**
172 * Generic error handler, called with the appropriate error code and
173 * the same closure specified at the creation of the message queue.
174 * Not every message queue implementation supports an error handler.
175 *
176 * @param cls closure with the `struct GNUNET_CREDENTIAL_Handle *`
177 * @param error error code
178 */
179static void
180mq_error_handler (void *cls,
181 enum GNUNET_MQ_Error error)
182{
183 struct GNUNET_CREDENTIAL_Handle *handle = cls;
184
185 force_reconnect (handle);
186}
187
188/**
189 * Check validity of message received from the CREDENTIAL service
190 *
191 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
192 * @param vr_msg the incoming message
193 */
194static int
195check_result (void *cls,
196 const struct DelegationChainResultMessage *vr_msg)
197{
198 //TODO
199 return GNUNET_OK;
200}
201
202
203/**
204 * Handler for messages received from the CREDENTIAL service
205 *
206 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
207 * @param vr_msg the incoming message
208 */
209static void
210handle_result (void *cls,
211 const struct DelegationChainResultMessage *vr_msg)
212{
213 struct GNUNET_CREDENTIAL_Handle *handle = cls;
214 uint32_t r_id = ntohl (vr_msg->id);
215 struct GNUNET_CREDENTIAL_Request *vr;
216 size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg);
217 uint32_t d_count = ntohl (vr_msg->d_count);
218 uint32_t c_count = ntohl (vr_msg->c_count);
219 struct GNUNET_CREDENTIAL_Delegation d_chain[d_count];
220 struct GNUNET_CREDENTIAL_Credential creds[c_count];
221 GNUNET_CREDENTIAL_CredentialResultProcessor proc;
222 void *proc_cls;
223
224 LOG (GNUNET_ERROR_TYPE_DEBUG,
225 "Received verify reply from CREDENTIAL service\n");
226 for (vr = handle->request_head; NULL != vr; vr = vr->next)
227 if (vr->r_id == r_id)
228 break;
229 if (NULL == vr)
230 return;
231 proc = vr->verify_proc;
232 proc_cls = vr->proc_cls;
233 GNUNET_CONTAINER_DLL_remove (handle->request_head,
234 handle->request_tail,
235 vr);
236 GNUNET_MQ_discard (vr->env);
237 GNUNET_free (vr);
238 GNUNET_assert (GNUNET_OK ==
239 GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen,
240 (const char*) &vr_msg[1],
241 d_count,
242 d_chain,
243 c_count,
244 creds));
245 if (GNUNET_NO == ntohl (vr_msg->cred_found))
246 {
247 proc (proc_cls,
248 0,
249 NULL,
250 0,
251 NULL); // TODO
252 } else {
253 proc (proc_cls,
254 d_count,
255 d_chain,
256 c_count,
257 creds);
258 }
259}
260
261
262/**
263 * Reconnect to CREDENTIAL service.
264 *
265 * @param handle the handle to the CREDENTIAL service
266 */
267static void
268reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
269{
270 struct GNUNET_MQ_MessageHandler handlers[] = {
271 GNUNET_MQ_hd_var_size (result,
272 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
273 struct DelegationChainResultMessage,
274 handle),
275 GNUNET_MQ_hd_var_size (result,
276 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT,
277 struct DelegationChainResultMessage,
278 handle),
279 GNUNET_MQ_handler_end ()
280 };
281 struct GNUNET_CREDENTIAL_Request *vr;
282
283 GNUNET_assert (NULL == handle->mq);
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Trying to connect to CREDENTIAL\n");
286 handle->mq = GNUNET_CLIENT_connect (handle->cfg,
287 "credential",
288 handlers,
289 &mq_error_handler,
290 handle);
291 if (NULL == handle->mq)
292 return;
293 for (vr = handle->request_head; NULL != vr; vr = vr->next)
294 GNUNET_MQ_send_copy (handle->mq,
295 vr->env);
296}
297
298
299/**
300 * Initialize the connection with the CREDENTIAL service.
301 *
302 * @param cfg configuration to use
303 * @return handle to the CREDENTIAL service, or NULL on error
304 */
305struct GNUNET_CREDENTIAL_Handle *
306GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
307{
308 struct GNUNET_CREDENTIAL_Handle *handle;
309
310 handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
311 handle->cfg = cfg;
312 reconnect (handle);
313 if (NULL == handle->mq)
314 {
315 GNUNET_free (handle);
316 return NULL;
317 }
318 return handle;
319}
320
321
322/**
323 * Shutdown connection with the CREDENTIAL service.
324 *
325 * @param handle handle of the CREDENTIAL connection to stop
326 */
327void
328GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle)
329{
330 if (NULL != handle->mq)
331 {
332 GNUNET_MQ_destroy (handle->mq);
333 handle->mq = NULL;
334 }
335 if (NULL != handle->reconnect_task)
336 {
337 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
338 handle->reconnect_task = NULL;
339 }
340 GNUNET_assert (NULL == handle->request_head);
341 GNUNET_free (handle);
342}
343
344
345/**
346 * Cancel pending verify request
347 *
348 * @param lr the verify request to cancel
349 */
350void
351GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *lr)
352{
353 struct GNUNET_CREDENTIAL_Handle *handle = lr->credential_handle;
354
355 GNUNET_CONTAINER_DLL_remove (handle->request_head,
356 handle->request_tail,
357 lr);
358 GNUNET_MQ_discard (lr->env);
359 GNUNET_free (lr);
360}
361
362
363/**
364 * Performs attribute collection.
365 * Collects all credentials of subject to fulfill the
366 * attribute, if possible
367 *
368 * @param handle handle to the Credential service
369 * @param issuer_key the issuer public key
370 * @param issuer_attribute the issuer attribute
371 * @param subject_key the subject public key
372 * @param proc function to call on result
373 * @param proc_cls closure for processor
374 * @return handle to the queued request
375 */
376struct GNUNET_CREDENTIAL_Request*
377GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
378 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
379 const char *issuer_attribute,
380 const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
381 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
382 void *proc_cls)
383{
384 /* IPC to shorten credential names, return shorten_handle */
385 struct CollectMessage *c_msg;
386 struct GNUNET_CREDENTIAL_Request *vr;
387 size_t nlen;
388
389 if (NULL == issuer_attribute)
390 {
391 GNUNET_break (0);
392 return NULL;
393 }
394
395 //DEBUG LOG
396 LOG (GNUNET_ERROR_TYPE_DEBUG,
397 "Trying to collect `%s' in CREDENTIAL\n",
398 issuer_attribute);
399 nlen = strlen (issuer_attribute) + 1;
400 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
401 {
402 GNUNET_break (0);
403 return NULL;
404 }
405 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
406 vr->credential_handle = handle;
407 vr->verify_proc = proc;
408 vr->proc_cls = proc_cls;
409 vr->r_id = handle->r_id_gen++;
410 vr->env = GNUNET_MQ_msg_extra (c_msg,
411 nlen,
412 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT);
413 c_msg->id = htonl (vr->r_id);
414 c_msg->subject_key = *subject_key;
415 c_msg->issuer_key = *issuer_key;
416 c_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
417 GNUNET_memcpy (&c_msg[1],
418 issuer_attribute,
419 strlen (issuer_attribute));
420 GNUNET_CONTAINER_DLL_insert (handle->request_head,
421 handle->request_tail,
422 vr);
423 if (NULL != handle->mq)
424 GNUNET_MQ_send_copy (handle->mq,
425 vr->env);
426 return vr;
427}
428/**
429 * Performs attribute verification.
430 * Checks if there is a delegation chain from
431 * attribute ``issuer_attribute'' issued by the issuer
432 * with public key ``issuer_key'' maps to the attribute
433 * ``subject_attribute'' claimed by the subject with key
434 * ``subject_key''
435 *
436 * @param handle handle to the Credential service
437 * @param issuer_key the issuer public key
438 * @param issuer_attribute the issuer attribute
439 * @param subject_key the subject public key
440 * @param credential_count number of credentials provided
441 * @param credentials subject credentials
442 * @param proc function to call on result
443 * @param proc_cls closure for processor
444 * @return handle to the queued request
445 */
446struct GNUNET_CREDENTIAL_Request*
447GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
448 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
449 const char *issuer_attribute,
450 const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
451 uint32_t credential_count,
452 const struct GNUNET_CREDENTIAL_Credential *credentials,
453 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
454 void *proc_cls)
455{
456 /* IPC to shorten credential names, return shorten_handle */
457 struct VerifyMessage *v_msg;
458 struct GNUNET_CREDENTIAL_Request *vr;
459 size_t nlen;
460 size_t clen;
461
462 if (NULL == issuer_attribute || NULL == credentials)
463 {
464 GNUNET_break (0);
465 return NULL;
466 }
467
468 clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
469 credentials);
470
471 //DEBUG LOG
472 LOG (GNUNET_ERROR_TYPE_DEBUG,
473 "Trying to verify `%s' in CREDENTIAL\n",
474 issuer_attribute);
475 nlen = strlen (issuer_attribute) + 1 + clen;
476 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
477 {
478 GNUNET_break (0);
479 return NULL;
480 }
481 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
482 vr->credential_handle = handle;
483 vr->verify_proc = proc;
484 vr->proc_cls = proc_cls;
485 vr->r_id = handle->r_id_gen++;
486 vr->env = GNUNET_MQ_msg_extra (v_msg,
487 nlen,
488 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
489 v_msg->id = htonl (vr->r_id);
490 v_msg->subject_key = *subject_key;
491 v_msg->c_count = htonl(credential_count);
492 v_msg->issuer_key = *issuer_key;
493 v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
494 GNUNET_memcpy (&v_msg[1],
495 issuer_attribute,
496 strlen (issuer_attribute));
497 GNUNET_CREDENTIAL_credentials_serialize (credential_count,
498 credentials,
499 clen,
500 ((char*)&v_msg[1])
501 + strlen (issuer_attribute) + 1);
502 GNUNET_CONTAINER_DLL_insert (handle->request_head,
503 handle->request_tail,
504 vr);
505 if (NULL != handle->mq)
506 GNUNET_MQ_send_copy (handle->mq,
507 vr->env);
508 return vr;
509}
510
511/* end of credential_api.c */
diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c
new file mode 100644
index 000000000..c94c33919
--- /dev/null
+++ b/src/credential/credential_misc.c
@@ -0,0 +1,168 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_misc.c
24 * @brief Misc API for credentials
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34#include <inttypes.h>
35
36char*
37GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred)
38{
39 char *cred_str;
40 char *subject_pkey;
41 char *issuer_pkey;
42 char *signature;
43
44
45 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
46 issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
47 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
48 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
49 &signature);
50 GNUNET_asprintf (&cred_str,
51 "%s.%s -> %s | %s | %"SCNu64,
52 issuer_pkey,
53 cred->issuer_attribute,
54 subject_pkey,
55 signature,
56 cred->expiration.abs_value_us);
57 GNUNET_free (subject_pkey);
58 GNUNET_free (issuer_pkey);
59 GNUNET_free (signature);
60 return cred_str;
61}
62
63struct GNUNET_CREDENTIAL_Credential*
64GNUNET_CREDENTIAL_credential_from_string (const char* s)
65{
66 struct GNUNET_CREDENTIAL_Credential *cred;
67 size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
68 if (enclen % 5 > 0)
69 enclen += 5 - enclen % 5;
70 enclen /= 5; /* 260/5 = 52 */
71 char subject_pkey[enclen + 1];
72 char issuer_pkey[enclen + 1];
73 char name[253 + 1];
74 char signature[256]; //TODO max payload size
75
76 struct GNUNET_CRYPTO_EcdsaSignature *sig;
77 struct GNUNET_TIME_Absolute etime_abs;
78
79 if (5 != SSCANF (s,
80 "%52s.%253s -> %52s | %s | %"SCNu64,
81 issuer_pkey,
82 name,
83 subject_pkey,
84 signature,
85 &etime_abs.abs_value_us))
86 {
87 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
88 _("Unable to parse CRED record string `%s'\n"),
89 s);
90 return NULL;
91 }
92 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1);
93 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
94 strlen (subject_pkey),
95 &cred->subject_key);
96 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
97 strlen (issuer_pkey),
98 &cred->issuer_key);
99 GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature,
100 strlen (signature),
101 (char**)&sig));
102 cred->signature = *sig;
103 cred->expiration = etime_abs;
104 GNUNET_free (sig);
105 GNUNET_memcpy (&cred[1],
106 name,
107 strlen (name)+1);
108 cred->issuer_attribute_len = strlen ((char*)&cred[1]);
109 cred->issuer_attribute = (char*)&cred[1];
110 return cred;
111}
112
113/**
114 * Issue an attribute to a subject
115 *
116 * @param issuer the ego that should be used to issue the attribute
117 * @param subject the subject of the attribute
118 * @param attribute the name of the attribute
119 * @return handle to the queued request
120 */
121struct GNUNET_CREDENTIAL_Credential *
122GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
123 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
124 const char *attribute,
125 struct GNUNET_TIME_Absolute *expiration)
126{
127 struct CredentialEntry *crd;
128 struct GNUNET_CREDENTIAL_Credential *cred;
129 size_t size;
130
131 size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
132 crd = GNUNET_malloc (size);
133 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1);
134 crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
135
136 crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
137 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
138 &crd->issuer_key);
139 crd->subject_key = *subject;
140 crd->expiration = GNUNET_htonll (expiration->abs_value_us);
141 crd->issuer_attribute_len = htonl (strlen (attribute)+1);
142 GNUNET_memcpy ((char*)&crd[1],
143 attribute,
144 strlen (attribute)+1);
145 if (GNUNET_OK !=
146 GNUNET_CRYPTO_ecdsa_sign (issuer,
147 &crd->purpose,
148 &crd->signature))
149 {
150 GNUNET_break (0);
151 GNUNET_free (crd);
152 return NULL;
153 }
154 cred->signature = crd->signature;
155 cred->expiration = *expiration;
156 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
157 &cred->issuer_key);
158
159 cred->subject_key = *subject;
160 GNUNET_memcpy (&cred[1],
161 attribute,
162 strlen (attribute)+1);
163 cred->issuer_attribute = (char*)&cred[1];
164 GNUNET_free (crd);
165 return cred;
166}
167
168
diff --git a/src/credential/credential_misc.h b/src/credential/credential_misc.h
new file mode 100644
index 000000000..c3aa8c214
--- /dev/null
+++ b/src/credential/credential_misc.h
@@ -0,0 +1,35 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @file credential/credential_misc.h
22 * @brief Credential helper functions
23 */
24#ifndef CREDENTIAL_MISC_H
25#define CREDENTIAL_MISC_H
26
27
28
29char*
30GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred);
31
32struct GNUNET_CREDENTIAL_Credential*
33GNUNET_CREDENTIAL_credential_from_string (const char* str);
34
35#endif
diff --git a/src/credential/credential_serialization.c b/src/credential/credential_serialization.c
new file mode 100644
index 000000000..1d23bb08c
--- /dev/null
+++ b/src/credential/credential_serialization.c
@@ -0,0 +1,460 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_serialization.c
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34
35/**
36 * Calculate how many bytes we will need to serialize
37 * the given delegation chain
38 *
39 * @param ds_count number of delegation chain entries
40 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
41 * @return the required size to serialize
42 */
43size_t
44GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
45 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
46{
47 unsigned int i;
48 size_t ret;
49
50 ret = sizeof (struct DelegationRecordData) * (ds_count);
51
52 for (i=0; i<ds_count;i++)
53 {
54 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
55 ret += dsr[i].subject_attribute_len;
56 }
57 return ret;
58}
59
60/**
61 * Serizalize the given delegation chain entries and credential
62 *
63 * @param d_count number of delegation chain entries
64 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
65 * @param dest_size size of the destination
66 * @param dest where to store the result
67 * @return the size of the data, -1 on failure
68 */
69ssize_t
70GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
71 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
72 size_t dest_size,
73 char *dest)
74{
75 struct DelegationRecordData rec;
76 unsigned int i;
77 size_t off;
78
79 off = 0;
80 for (i=0;i<d_count;i++)
81 {
82 rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
83 rec.subject_key = dsr[i].subject_key;
84 if (off + sizeof (rec) > dest_size)
85 return -1;
86 GNUNET_memcpy (&dest[off],
87 &rec,
88 sizeof (rec));
89 off += sizeof (rec);
90 if (0 == dsr[i].subject_attribute_len)
91 continue;
92 if (off + dsr[i].subject_attribute_len > dest_size)
93 return -1;
94 GNUNET_memcpy (&dest[off],
95 dsr[i].subject_attribute,
96 dsr[i].subject_attribute_len);
97 off += dsr[i].subject_attribute_len;
98 }
99 return off;
100}
101
102
103/**
104 * Deserialize the given destination
105 *
106 * @param len size of the serialized delegation chain and cred
107 * @param src the serialized data
108 * @param d_count the number of delegation chain entries
109 * @param dsr where to put the delegation chain entries
110 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
111 */
112int
113GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
114 const char *src,
115 unsigned int d_count,
116 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
117{
118 struct DelegationRecordData rec;
119 unsigned int i;
120 size_t off;
121
122 off = 0;
123 for (i=0;i<d_count;i++)
124 {
125 if (off + sizeof (rec) > len)
126 return GNUNET_SYSERR;
127 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
128 dsr[i].subject_key = rec.subject_key;
129 off += sizeof (rec);
130 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
131 if (off + dsr[i].subject_attribute_len > len)
132 return GNUNET_SYSERR;
133 dsr[i].subject_attribute = (char*)&src[off];
134 off += dsr[i].subject_attribute_len;
135 }
136 return GNUNET_OK;
137}
138
139
140/**
141 * Calculate how many bytes we will need to serialize
142 * the credentials
143 *
144 * @param c_count number of credential entries
145 * @param cd a #GNUNET_CREDENTIAL_Credential
146 * @return the required size to serialize
147 */
148size_t
149GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
150 const struct GNUNET_CREDENTIAL_Credential *cd)
151{
152 unsigned int i;
153 size_t ret;
154
155 ret = sizeof (struct CredentialEntry) * (c_count);
156
157 for (i=0; i<c_count;i++)
158 {
159 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
160 ret += cd[i].issuer_attribute_len;
161 }
162 return ret;
163}
164/**
165 * Serizalize the given credentials
166 *
167 * @param c_count number of credential entries
168 * @param cd a #GNUNET_CREDENTIAL_Credential
169 * @param dest_size size of the destination
170 * @param dest where to store the result
171 * @return the size of the data, -1 on failure
172 */
173ssize_t
174GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
175 const struct GNUNET_CREDENTIAL_Credential *cd,
176 size_t dest_size,
177 char *dest)
178{
179 struct CredentialEntry c_rec;
180 unsigned int i;
181 size_t off;
182
183 off = 0;
184 for (i=0;i<c_count;i++)
185 {
186 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
187 c_rec.issuer_key = cd[i].issuer_key;
188 c_rec.subject_key = cd[i].subject_key;
189 c_rec.signature = cd[i].signature;
190 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
191 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
192 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
193 if (off + sizeof (c_rec) > dest_size)
194 return -1;
195 GNUNET_memcpy (&dest[off],
196 &c_rec,
197 sizeof (c_rec));
198 off += sizeof (c_rec);
199 if (off + cd[i].issuer_attribute_len > dest_size)
200 return -1;
201 GNUNET_memcpy (&dest[off],
202 cd[i].issuer_attribute,
203 cd[i].issuer_attribute_len);
204 off += cd[i].issuer_attribute_len;
205 }
206
207 return off;
208}
209
210
211
212/**
213 * Deserialize the given destination
214 *
215 * @param len size of the serialized creds
216 * @param src the serialized data
217 * @param c_count the number of credential entries
218 * @param cd where to put the credential data
219 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
220 */
221int
222GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
223 const char *src,
224 unsigned int c_count,
225 struct GNUNET_CREDENTIAL_Credential *cd)
226{
227 struct CredentialEntry c_rec;
228 unsigned int i;
229 size_t off;
230
231 off = 0;
232 for (i=0;i<c_count;i++)
233 {
234 if (off + sizeof (c_rec) > len)
235 return GNUNET_SYSERR;
236 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
237 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
238 cd[i].issuer_key = c_rec.issuer_key;
239 cd[i].subject_key = c_rec.subject_key;
240 cd[i].signature = c_rec.signature;
241 cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
242 off += sizeof (c_rec);
243 if (off + cd[i].issuer_attribute_len > len)
244 return GNUNET_SYSERR;
245 cd[i].issuer_attribute = &src[off];
246 off += cd[i].issuer_attribute_len;
247 }
248 return GNUNET_OK;
249}
250
251
252
253/**
254 * Calculate how many bytes we will need to serialize
255 * the given delegation chain and credential
256 *
257 * @param d_count number of delegation chain entries
258 * @param dd array of #GNUNET_CREDENTIAL_Delegation
259 * @param c_count number of credential entries
260 * @param cd a #GNUNET_CREDENTIAL_Credential
261 * @return the required size to serialize
262 */
263size_t
264GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
265 const struct GNUNET_CREDENTIAL_Delegation *dd,
266 unsigned int c_count,
267 const struct GNUNET_CREDENTIAL_Credential *cd)
268{
269 unsigned int i;
270 size_t ret;
271
272 ret = sizeof (struct ChainEntry) * (d_count);
273
274 for (i=0; i<d_count;i++)
275 {
276 GNUNET_assert ((ret +
277 dd[i].issuer_attribute_len +
278 dd[i].subject_attribute_len) >= ret);
279 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
280 }
281 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
282 return ret;
283}
284
285/**
286 * Serizalize the given delegation chain entries and credential
287 *
288 * @param d_count number of delegation chain entries
289 * @param dd array of #GNUNET_CREDENTIAL_Delegation
290 * @param c_count number of credential entries
291 * @param cd a #GNUNET_CREDENTIAL_Credential
292 * @param dest_size size of the destination
293 * @param dest where to store the result
294 * @return the size of the data, -1 on failure
295 */
296ssize_t
297GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
298 const struct GNUNET_CREDENTIAL_Delegation *dd,
299 unsigned int c_count,
300 const struct GNUNET_CREDENTIAL_Credential *cd,
301 size_t dest_size,
302 char *dest)
303{
304 struct ChainEntry rec;
305 unsigned int i;
306 size_t off;
307
308 off = 0;
309 for (i=0;i<d_count;i++)
310 {
311 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
312 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
313 rec.issuer_key = dd[i].issuer_key;
314 rec.subject_key = dd[i].subject_key;
315 if (off + sizeof (rec) > dest_size)
316 return -1;
317 GNUNET_memcpy (&dest[off],
318 &rec,
319 sizeof (rec));
320 off += sizeof (rec);
321 if (off + dd[i].issuer_attribute_len > dest_size)
322 return -1;
323 GNUNET_memcpy (&dest[off],
324 dd[i].issuer_attribute,
325 dd[i].issuer_attribute_len);
326 off += dd[i].issuer_attribute_len;
327 if (0 == dd[i].subject_attribute_len)
328 continue;
329 if (off + dd[i].subject_attribute_len > dest_size)
330 return -1;
331 GNUNET_memcpy (&dest[off],
332 dd[i].subject_attribute,
333 dd[i].subject_attribute_len);
334 off += dd[i].subject_attribute_len;
335 }
336 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
337 cd,
338 dest_size-off,
339 &dest[off]);
340}
341
342
343/**
344 * Deserialize the given destination
345 *
346 * @param len size of the serialized delegation chain and cred
347 * @param src the serialized data
348 * @param d_count the number of delegation chain entries
349 * @param dd where to put the delegation chain entries
350 * @param c_count the number of credential entries
351 * @param cd where to put the credential data
352 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
353 */
354int
355GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
356 const char *src,
357 unsigned int d_count,
358 struct GNUNET_CREDENTIAL_Delegation *dd,
359 unsigned int c_count,
360 struct GNUNET_CREDENTIAL_Credential *cd)
361{
362 struct ChainEntry rec;
363 unsigned int i;
364 size_t off;
365
366 off = 0;
367 for (i=0;i<d_count;i++)
368 {
369 if (off + sizeof (rec) > len)
370 return GNUNET_SYSERR;
371 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
372 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
373 dd[i].issuer_key = rec.issuer_key;
374 dd[i].subject_key = rec.subject_key;
375 off += sizeof (rec);
376 if (off + dd[i].issuer_attribute_len > len)
377 return GNUNET_SYSERR;
378 dd[i].issuer_attribute = &src[off];
379 off += dd[i].issuer_attribute_len;
380 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
381 if (off + dd[i].subject_attribute_len > len)
382 return GNUNET_SYSERR;
383 dd[i].subject_attribute = &src[off];
384 off += dd[i].subject_attribute_len;
385 }
386 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
387 &src[off],
388 c_count,
389 cd);
390}
391int
392GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
393 char **data)
394{
395 size_t size;
396 struct CredentialEntry *cdata;
397
398 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
399 *data = GNUNET_malloc (size);
400 cdata = (struct CredentialEntry*)*data;
401 cdata->subject_key = cred->subject_key;
402 cdata->issuer_key = cred->issuer_key;
403 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
404 cdata->signature = cred->signature;
405 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
406 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
407 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
408 GNUNET_memcpy (&cdata[1],
409 cred->issuer_attribute,
410 strlen (cred->issuer_attribute));
411
412 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
413 &cdata->purpose,
414 &cdata->signature,
415 &cdata->issuer_key))
416 {
417 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
418 "Invalid credential\n");
419 //return NULL;
420 }
421 return size;
422}
423
424struct GNUNET_CREDENTIAL_Credential*
425GNUNET_CREDENTIAL_credential_deserialize (const char* data,
426 size_t data_size)
427{
428 struct GNUNET_CREDENTIAL_Credential *cred;
429 struct CredentialEntry *cdata;
430 char *issuer_attribute;
431
432 if (data_size < sizeof (struct CredentialEntry))
433 return NULL;
434 cdata = (struct CredentialEntry*)data;
435 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
436 &cdata->purpose,
437 &cdata->signature,
438 &cdata->issuer_key))
439 {
440 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
441 "Invalid credential\n");
442 //return NULL;
443 }
444 issuer_attribute = (char*)&cdata[1];
445
446 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
447
448 cred->issuer_key = cdata->issuer_key;
449 cred->subject_key = cdata->subject_key;
450 GNUNET_memcpy (&cred[1],
451 issuer_attribute,
452 ntohl (cdata->issuer_attribute_len));
453 cred->signature = cdata->signature;
454 cred->issuer_attribute = (char*)&cred[1];
455 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
456 return cred;
457}
458
459
460/* end of credential_serialization.c */
diff --git a/src/credential/credential_serialization.h b/src/credential/credential_serialization.h
new file mode 100644
index 000000000..b870d47dc
--- /dev/null
+++ b/src/credential/credential_serialization.h
@@ -0,0 +1,159 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_serialization.h
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#ifndef CREDENTIAL_SERIALIZATION_H
29#define CREDENTIAL_SERIALIZATION_H
30
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_constants.h"
34#include "gnunet_credential_service.h"
35
36/**
37 * Calculate how many bytes we will need to serialize
38 * the given delegation record
39 *
40 * @param ds_count number of delegation chain entries
41 * @param dsr array of #GNUNET_CREDENTIAL_Delegation
42 * @return the required size to serialize
43 */
44size_t
45GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
46 const struct GNUNET_CREDENTIAL_DelegationSet *dsr);
47
48/**
49 * Serizalize the given delegation record entries
50 *
51 * @param d_count number of delegation chain entries
52 * @param dsr array of #GNUNET_CREDENTIAL_Delegation
53 * @param dest_size size of the destination
54 * @param dest where to store the result
55 * @return the size of the data, -1 on failure
56 */
57ssize_t
58GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
59 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
60 size_t dest_size,
61 char *dest);
62
63
64/**
65 * Deserialize the given destination
66 *
67 * @param len size of the serialized delegation recird
68 * @param src the serialized data
69 * @param d_count the number of delegation chain entries
70 * @param dsr where to put the delegation chain entries
71 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
72 */
73int
74GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
75 const char *src,
76 unsigned int d_count,
77 struct GNUNET_CREDENTIAL_DelegationSet *dsr);
78
79 /**
80 * Calculate how many bytes we will need to serialize
81 * the given delegation chain and credential
82 *
83 * @param d_count number of delegation chain entries
84 * @param dd array of #GNUNET_CREDENTIAL_Delegation
85 * @param c_count number of credential entries
86 * @param cd a #GNUNET_CREDENTIAL_Credential
87 * @return the required size to serialize
88 */
89 size_t
90 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
91 const struct GNUNET_CREDENTIAL_Delegation *dd,
92 unsigned int c_count,
93 const struct GNUNET_CREDENTIAL_Credential *cd);
94
95 /**
96 * Serizalize the given delegation chain entries and credential
97 *
98 * @param d_count number of delegation chain entries
99 * @param dd array of #GNUNET_CREDENTIAL_Delegation
100 * @param c_count number of credential entries
101 * @param cd a #GNUNET_CREDENTIAL_Credential
102 * @param dest_size size of the destination
103 * @param dest where to store the result
104 * @return the size of the data, -1 on failure
105 */
106 ssize_t
107 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
108 const struct GNUNET_CREDENTIAL_Delegation *dd,
109 unsigned int c_count,
110 const struct GNUNET_CREDENTIAL_Credential *cd,
111 size_t dest_size,
112 char *dest);
113
114
115 /**
116 * Deserialize the given destination
117 *
118 * @param len size of the serialized delegation chain and cred
119 * @param src the serialized data
120 * @param d_count the number of delegation chain entries
121 * @param dd where to put the delegation chain entries
122 * @param c_count number of credential entries
123 * @param cd where to put the credential data
124 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
125 */
126 int
127 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
128 const char *src,
129 unsigned int d_count,
130 struct GNUNET_CREDENTIAL_Delegation *dd,
131 unsigned int c_count,
132 struct GNUNET_CREDENTIAL_Credential *cd);
133 size_t
134 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
135 const struct GNUNET_CREDENTIAL_Credential *cd);
136
137ssize_t
138GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
139 const struct GNUNET_CREDENTIAL_Credential *cd,
140 size_t dest_size,
141 char *dest);
142
143
144int
145GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
146 const char *src,
147 unsigned int c_count,
148 struct GNUNET_CREDENTIAL_Credential *cd);
149
150
151int
152GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
153 char **data);
154
155struct GNUNET_CREDENTIAL_Credential*
156GNUNET_CREDENTIAL_credential_deserialize (const char* data,
157 size_t data_size);
158#endif
159/* end of credential_serialization.h */
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c
new file mode 100644
index 000000000..03f959b95
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,588 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file gnunet-credential.c
22 * @brief command line tool to access command line Credential service
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26#include <gnunet_util_lib.h>
27#include <gnunet_credential_service.h>
28#include <gnunet_gnsrecord_lib.h>
29#include "credential_misc.h"
30#include "credential_serialization.h"
31
32/**
33 * Configuration we are using.
34 */
35static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37/**
38 * EgoLookup
39 */
40static struct GNUNET_IDENTITY_EgoLookup *el;
41
42/**
43 * Handle to Credential service.
44 */
45static struct GNUNET_CREDENTIAL_Handle *credential;
46
47/**
48 * Desired timeout for the lookup (default is no timeout).
49 */
50static struct GNUNET_TIME_Relative timeout;
51
52/**
53 * Handle to verify request
54 */
55static struct GNUNET_CREDENTIAL_Request *verify_request;
56
57/**
58 * Handle to collect request
59 */
60static struct GNUNET_CREDENTIAL_Request *collect_request;
61
62/**
63 * Task scheduled to handle timeout.
64 */
65static struct GNUNET_SCHEDULER_Task *tt;
66
67/**
68 * Subject pubkey string
69 */
70static char *subject_key;
71
72/**
73 * Subject credential string
74 */
75static char *subject_credential;
76
77/**
78 * Credential TTL
79 */
80static char *expiration;
81
82/**
83 * Subject key
84 */
85struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
86
87/**
88 * Issuer key
89 */
90struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
91
92
93/**
94 * Issuer pubkey string
95 */
96static char *issuer_key;
97
98/**
99 * ego
100 */
101static char *ego_name;
102
103/**
104 * Issuer attribute
105 */
106static char *issuer_attr;
107
108/**
109 * Verify mode
110 */
111static int verify;
112
113/**
114 * Issue mode
115 */
116static int create_cred;
117
118/**
119 * Collect mode
120 */
121static int collect;
122
123/**
124 * Task run on shutdown. Cleans up everything.
125 *
126 * @param cls unused
127 */
128static void
129do_shutdown (void *cls)
130{
131 if (NULL != verify_request)
132 {
133 GNUNET_CREDENTIAL_request_cancel (verify_request);
134 verify_request = NULL;
135 }
136 if (NULL != credential)
137 {
138 GNUNET_CREDENTIAL_disconnect (credential);
139 credential = NULL;
140 }
141 if (NULL != tt)
142 {
143 GNUNET_SCHEDULER_cancel (tt);
144 tt = NULL;
145 }
146}
147
148
149/**
150 * Task run on timeout. Triggers shutdown.
151 *
152 * @param cls unused
153 */
154static void
155do_timeout (void *cls)
156{
157 tt = NULL;
158 GNUNET_SCHEDULER_shutdown ();
159}
160
161static void
162handle_collect_result (void *cls,
163 unsigned int d_count,
164 struct GNUNET_CREDENTIAL_Delegation *dc,
165 unsigned int c_count,
166 struct GNUNET_CREDENTIAL_Credential *cred)
167{
168 int i;
169 char* line;
170
171 verify_request = NULL;
172 if (NULL != cred)
173 {
174 for (i=0;i<c_count;i++)
175 {
176 line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
177 printf ("%s\n",
178 line);
179 GNUNET_free (line);
180 }
181 }
182
183
184 GNUNET_SCHEDULER_shutdown ();
185}
186
187
188static void
189handle_verify_result (void *cls,
190 unsigned int d_count,
191 struct GNUNET_CREDENTIAL_Delegation *dc,
192 unsigned int c_count,
193 struct GNUNET_CREDENTIAL_Credential *cred)
194{
195 int i;
196 char* iss_key;
197 char* sub_key;
198
199 verify_request = NULL;
200 if (NULL == cred)
201 printf ("Failed.\n");
202 else
203 {
204 printf("Delegation Chain:\n");
205 for (i=0;i<d_count;i++)
206 {
207 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
208 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
209 if (0 != dc[i].subject_attribute_len)
210 {
211 printf ("(%d) %s.%s <- %s.%s\n", i,
212 iss_key, dc[i].issuer_attribute,
213 sub_key, dc[i].subject_attribute);
214 } else {
215 printf ("(%d) %s.%s <- %s\n", i,
216 iss_key, dc[i].issuer_attribute,
217 sub_key);
218 }
219 GNUNET_free (iss_key);
220 GNUNET_free (sub_key);
221 }
222 printf("\nCredentials:\n");
223 for (i=0;i<c_count;i++)
224 {
225 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
226 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
227 printf ("%s.%s <- %s\n",
228 iss_key, cred[i].issuer_attribute,
229 sub_key);
230 GNUNET_free (iss_key);
231 GNUNET_free (sub_key);
232
233 }
234 printf ("Successful.\n");
235 }
236
237
238 GNUNET_SCHEDULER_shutdown ();
239}
240
241/**
242 * Callback invoked from identity service with ego information.
243 * An @a ego of NULL means the ego was not found.
244 *
245 * @param cls closure with the configuration
246 * @param ego an ego known to identity service, or NULL
247 */
248static void
249identity_cb (void *cls,
250 const struct GNUNET_IDENTITY_Ego *ego)
251{
252 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
253 struct GNUNET_CREDENTIAL_Credential *crd;
254 struct GNUNET_TIME_Absolute etime_abs;
255 struct GNUNET_TIME_Relative etime_rel;
256 char *res;
257
258 el = NULL;
259 if (NULL == ego)
260 {
261 if (NULL != ego_name)
262 {
263 fprintf (stderr,
264 _("Ego `%s' not known to identity service\n"),
265 ego_name);
266 }
267 GNUNET_SCHEDULER_shutdown ();
268 return;
269 }
270
271 if (GNUNET_YES == collect)
272 {
273
274 if (GNUNET_OK !=
275 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
276 strlen (issuer_key),
277 &issuer_pkey))
278 {
279 fprintf (stderr,
280 _("Issuer public key `%s' is not well-formed\n"),
281 issuer_key);
282 GNUNET_SCHEDULER_shutdown ();
283 }
284 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
285
286 collect_request = GNUNET_CREDENTIAL_collect(credential,
287 &issuer_pkey,
288 issuer_attr, //TODO argument
289 privkey,
290 &handle_collect_result,
291 NULL);
292 return;
293 }
294
295 //Else issue
296
297 if (NULL == expiration)
298 {
299 fprintf (stderr,
300 "Please specify a TTL\n");
301 GNUNET_SCHEDULER_shutdown ();
302 return;
303 } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
304 &etime_rel))
305 {
306 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
307 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
308 &etime_abs))
309 {
310 fprintf (stderr,
311 "%s is not a valid ttl!\n",
312 expiration);
313 GNUNET_SCHEDULER_shutdown ();
314 return;
315 }
316
317
318 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
319 GNUNET_free_non_null (ego_name);
320 ego_name = NULL;
321 crd = GNUNET_CREDENTIAL_credential_issue (privkey,
322 &subject_pkey,
323 issuer_attr,
324 &etime_abs);
325
326 res = GNUNET_CREDENTIAL_credential_to_string (crd);
327 GNUNET_free (crd);
328 printf ("%s\n", res);
329 GNUNET_SCHEDULER_shutdown ();
330}
331
332
333
334
335/**
336 * Main function that will be run.
337 *
338 * @param cls closure
339 * @param args remaining command-line arguments
340 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
341 * @param c configuration
342 */
343static void
344run (void *cls,
345 char *const *args,
346 const char *cfgfile,
347 const struct GNUNET_CONFIGURATION_Handle *c)
348{
349
350 cfg = c;
351
352
353 tt = GNUNET_SCHEDULER_add_delayed (timeout,
354 &do_timeout, NULL);
355 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
356
357 if (GNUNET_YES == collect) {
358 if (NULL == issuer_key)
359 {
360 fprintf (stderr,
361 _("Issuer public key not well-formed\n"));
362 GNUNET_SCHEDULER_shutdown ();
363 return;
364
365 }
366
367 credential = GNUNET_CREDENTIAL_connect (cfg);
368
369 if (NULL == credential)
370 {
371 fprintf (stderr,
372 _("Failed to connect to CREDENTIAL\n"));
373 GNUNET_SCHEDULER_shutdown ();
374 }
375 if (NULL == issuer_attr)
376 {
377 fprintf (stderr,
378 _("You must provide issuer the attribute\n"));
379 GNUNET_SCHEDULER_shutdown ();
380 }
381
382 if (NULL == ego_name)
383 {
384 fprintf (stderr,
385 _("ego required\n"));
386 GNUNET_SCHEDULER_shutdown ();
387 return;
388
389 }
390 el = GNUNET_IDENTITY_ego_lookup (cfg,
391 ego_name,
392 &identity_cb,
393 (void *) cfg);
394 return;
395
396 }
397
398 if (NULL == subject_key)
399 {
400 fprintf (stderr,
401 _("Subject public key needed\n"));
402 GNUNET_SCHEDULER_shutdown ();
403 return;
404
405 }
406 if (GNUNET_OK !=
407 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
408 strlen (subject_key),
409 &subject_pkey))
410 {
411 fprintf (stderr,
412 _("Subject public key `%s' is not well-formed\n"),
413 subject_key);
414 GNUNET_SCHEDULER_shutdown ();
415 return;
416 }
417 if (GNUNET_YES == verify) {
418 if (NULL == issuer_key)
419 {
420 fprintf (stderr,
421 _("Issuer public key not well-formed\n"));
422 GNUNET_SCHEDULER_shutdown ();
423 return;
424
425 }
426 if (GNUNET_OK !=
427 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
428 strlen (issuer_key),
429 &issuer_pkey))
430 {
431 fprintf (stderr,
432 _("Issuer public key `%s' is not well-formed\n"),
433 issuer_key);
434 GNUNET_SCHEDULER_shutdown ();
435 }
436 credential = GNUNET_CREDENTIAL_connect (cfg);
437
438 if (NULL == credential)
439 {
440 fprintf (stderr,
441 _("Failed to connect to CREDENTIAL\n"));
442 GNUNET_SCHEDULER_shutdown ();
443 }
444 if (NULL == issuer_attr || NULL == subject_credential)
445 {
446 fprintf (stderr,
447 _("You must provide issuer and subject attributes\n"));
448 GNUNET_SCHEDULER_shutdown ();
449 }
450
451 //Subject credentials are comma separated
452 char *tmp = GNUNET_strdup (subject_credential);
453 char *tok = strtok (tmp, ",");
454 if (NULL == tok)
455 {
456 fprintf (stderr,
457 "Invalid subject credentials\n");
458 GNUNET_free (tmp);
459 GNUNET_SCHEDULER_shutdown ();
460 }
461 int count = 1;
462 int i;
463 while (NULL != (tok = strtok(NULL, ",")))
464 count++;
465 struct GNUNET_CREDENTIAL_Credential credentials[count];
466 struct GNUNET_CREDENTIAL_Credential *cred;
467 GNUNET_free (tmp);
468 tmp = GNUNET_strdup (subject_credential);
469 tok = strtok (tmp, ",");
470 for (i=0;i<count;i++)
471 {
472 cred = GNUNET_CREDENTIAL_credential_from_string (tok);
473 GNUNET_memcpy (&credentials[i],
474 cred,
475 sizeof (struct GNUNET_CREDENTIAL_Credential));
476 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
477 tok = strtok(NULL, ",");
478 GNUNET_free (cred);
479 }
480
481 verify_request = GNUNET_CREDENTIAL_verify(credential,
482 &issuer_pkey,
483 issuer_attr, //TODO argument
484 &subject_pkey,
485 count,
486 credentials,
487 &handle_verify_result,
488 NULL);
489 for (i=0;i<count;i++)
490 {
491 GNUNET_free ((char*)credentials[i].issuer_attribute);
492 }
493 } else if (GNUNET_YES == create_cred) {
494 if (NULL == ego_name)
495 {
496 fprintf (stderr,
497 _("Issuer ego required\n"));
498 GNUNET_SCHEDULER_shutdown ();
499 return;
500
501 }
502 el = GNUNET_IDENTITY_ego_lookup (cfg,
503 ego_name,
504 &identity_cb,
505 (void *) cfg);
506 return;
507 } else {
508 fprintf (stderr,
509 _("Please specify name to lookup, subject key and issuer key!\n"));
510 GNUNET_SCHEDULER_shutdown ();
511 }
512 return;
513}
514
515
516/**
517 * The main function for gnunet-gns.
518 *
519 * @param argc number of arguments from the command line
520 * @param argv command line arguments
521 * @return 0 ok, 1 on error
522 */
523int
524main (int argc, char *const *argv)
525{
526 struct GNUNET_GETOPT_CommandLineOption options[] = {
527 GNUNET_GETOPT_option_flag ('I',
528 "issue",
529 gettext_noop ("create credential"),
530 &create_cred),
531 GNUNET_GETOPT_option_flag ('V',
532 "verify",
533 gettext_noop ("verify credential against attribute"),
534 &verify),
535 GNUNET_GETOPT_option_string ('s',
536 "subject",
537 "PKEY",
538 gettext_noop ("The public key of the subject to lookup the credential for"),
539 &subject_key),
540 GNUNET_GETOPT_option_string ('b',
541 "credential",
542 "CRED",
543 gettext_noop ("The name of the credential presented by the subject"),
544 &subject_credential),
545 GNUNET_GETOPT_option_string ('i',
546 "issuer",
547 "PKEY",
548 gettext_noop ("The public key of the authority to verify the credential against"),
549 &issuer_key),
550 GNUNET_GETOPT_option_string ('e',
551 "ego",
552 "EGO",
553 gettext_noop ("The ego to use"),
554 &ego_name),
555 GNUNET_GETOPT_option_string ('a',
556 "attribute",
557 "ATTR",
558 gettext_noop ("The issuer attribute to verify against or to issue"),
559 &issuer_attr),
560 GNUNET_GETOPT_option_string ('T',
561 "ttl",
562 "EXP",
563 gettext_noop ("The time to live for the credential"),
564 &expiration),
565 GNUNET_GETOPT_option_flag ('g',
566 "collect",
567 gettext_noop ("collect credentials"),
568 &collect),
569 GNUNET_GETOPT_OPTION_END
570 };
571 int ret;
572
573 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
574 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
575 return 2;
576
577 GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
578 ret =
579 (GNUNET_OK ==
580 GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
581 _("GNUnet credential resolver tool"),
582 options,
583 &run, NULL)) ? 0 : 1;
584 GNUNET_free ((void*) argv);
585 return ret;
586}
587
588/* end of gnunet-credential.c */
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c
new file mode 100644
index 000000000..be88839e9
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1160 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file credential/gnunet-service-credential.c
22 * @brief GNUnet Credential Service (main service)
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_credential_service.h"
28#include "gnunet_statistics_service.h"
29#include "credential.h"
30#include "credential_serialization.h"
31#include "gnunet_protocols.h"
32#include "gnunet_signatures.h"
33
34#include <gnunet_dnsparser_lib.h>
35#include <gnunet_identity_service.h>
36#include <gnunet_gnsrecord_lib.h>
37#include <gnunet_namestore_service.h>
38#include <gnunet_gns_service.h>
39
40
41#define GNUNET_CREDENTIAL_MAX_LENGTH 255
42
43struct VerifyRequestHandle;
44
45struct DelegationSetQueueEntry;
46
47
48struct DelegationChainEntry
49{
50 /**
51 * DLL
52 */
53 struct DelegationChainEntry *next;
54
55 /**
56 * DLL
57 */
58 struct DelegationChainEntry *prev;
59
60 /**
61 * The issuer
62 */
63 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
64
65 /**
66 * The subject
67 */
68 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
69
70 /**
71 * The issued attribute
72 */
73 char *issuer_attribute;
74
75 /**
76 * The delegated attribute
77 */
78 char *subject_attribute;
79};
80
81/**
82 * DLL for record
83 */
84struct CredentialRecordEntry
85{
86 /**
87 * DLL
88 */
89 struct CredentialRecordEntry *next;
90
91 /**
92 * DLL
93 */
94 struct CredentialRecordEntry *prev;
95
96 /**
97 * Number of references in delegation chains
98 */
99 uint32_t refcount;
100
101 /**
102 * Payload
103 */
104 struct GNUNET_CREDENTIAL_Credential *credential;
105};
106
107/**
108 * DLL used for delegations
109 * Used for OR delegations
110 */
111struct DelegationQueueEntry
112{
113 /**
114 * DLL
115 */
116 struct DelegationQueueEntry *next;
117
118 /**
119 * DLL
120 */
121 struct DelegationQueueEntry *prev;
122
123 /**
124 * Sets under this Queue
125 */
126 struct DelegationSetQueueEntry *set_entries_head;
127
128 /**
129 * Sets under this Queue
130 */
131 struct DelegationSetQueueEntry *set_entries_tail;
132
133 /**
134 * Parent set
135 */
136 struct DelegationSetQueueEntry *parent_set;
137
138 /**
139 * Required solutions
140 */
141 uint32_t required_solutions;
142};
143
144/**
145 * DLL for delegation sets
146 * Used for AND delegation set
147 */
148struct DelegationSetQueueEntry
149{
150 /**
151 * DLL
152 */
153 struct DelegationSetQueueEntry *next;
154
155 /**
156 * DLL
157 */
158 struct DelegationSetQueueEntry *prev;
159
160 /**
161 * GNS handle
162 */
163 struct GNUNET_GNS_LookupRequest *lookup_request;
164
165 /**
166 * Verify handle
167 */
168 struct VerifyRequestHandle *handle;
169
170 /**
171 * Parent attribute delegation
172 */
173 struct DelegationQueueEntry *parent;
174
175 /**
176 * Issuer key
177 */
178 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
179
180 /**
181 * Queue entries of this set
182 */
183 struct DelegationQueueEntry *queue_entries_head;
184
185 /**
186 * Queue entries of this set
187 */
188 struct DelegationQueueEntry *queue_entries_tail;
189
190 /**
191 * Parent QueueEntry
192 */
193 struct DelegationQueueEntry *parent_queue_entry;
194
195 /**
196 * Issuer attribute delegated to
197 */
198 char *issuer_attribute;
199
200 /**
201 * The current attribute to look up
202 */
203 char *lookup_attribute;
204
205 /**
206 * Trailing attribute context
207 */
208 char *attr_trailer;
209
210 /**
211 * Still to resolve delegation as string
212 */
213 char *unresolved_attribute_delegation;
214
215 /**
216 * The delegation chain entry
217 */
218 struct DelegationChainEntry *delegation_chain_entry;
219
220};
221
222
223/**
224 * Handle to a lookup operation from api
225 */
226struct VerifyRequestHandle
227{
228
229 /**
230 * We keep these in a DLL.
231 */
232 struct VerifyRequestHandle *next;
233
234 /**
235 * We keep these in a DLL.
236 */
237 struct VerifyRequestHandle *prev;
238
239 /**
240 * Handle to the requesting client
241 */
242 struct GNUNET_SERVICE_Client *client;
243
244 /**
245 * GNS handle
246 */
247 struct GNUNET_GNS_LookupRequest *lookup_request;
248
249 /**
250 * Size of delegation tree
251 */
252 uint32_t delegation_chain_size;
253
254 /**
255 * Children of this attribute
256 */
257 struct DelegationChainEntry *delegation_chain_head;
258
259 /**
260 * Children of this attribute
261 */
262 struct DelegationChainEntry *delegation_chain_tail;
263
264 /**
265 * Issuer public key
266 */
267 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
268
269 /**
270 * Issuer attribute
271 */
272 char *issuer_attribute;
273
274 /**
275 * Subject public key
276 */
277 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
278
279 /**
280 * Credential DLL
281 */
282 struct CredentialRecordEntry *cred_chain_head;
283
284 /**
285 * Credential DLL
286 */
287 struct CredentialRecordEntry *cred_chain_tail;
288
289 /**
290 * Credential DLL size
291 */
292 uint32_t cred_chain_size;
293
294 /**
295 * Root Delegation Set
296 */
297 struct DelegationSetQueueEntry *root_set;
298
299 /**
300 * Current Delegation Pointer
301 */
302 struct DelegationQueueEntry *current_delegation;
303
304 /**
305 * request id
306 */
307 uint32_t request_id;
308
309 /**
310 * Pending lookups
311 */
312 uint64_t pending_lookups;
313
314 /**
315 * Credential iterator
316 */
317 struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
318
319 /**
320 * Collect task
321 */
322 struct GNUNET_SCHEDULER_Task *collect_next_task;
323
324};
325
326
327/**
328 * Head of the DLL.
329 */
330static struct VerifyRequestHandle *vrh_head;
331
332/**
333 * Tail of the DLL.
334 */
335static struct VerifyRequestHandle *vrh_tail;
336
337/**
338 * Handle to the statistics service
339 */
340static struct GNUNET_STATISTICS_Handle *statistics;
341
342/**
343 * Handle to GNS service.
344 */
345static struct GNUNET_GNS_Handle *gns;
346
347
348/**
349 * Handle to namestore service
350 */
351static struct GNUNET_NAMESTORE_Handle *namestore;
352
353static void
354cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
355{
356 struct DelegationQueueEntry *dq_entry;
357 struct DelegationSetQueueEntry *child;
358
359 if (NULL == ds_entry)
360 return;
361
362 for (dq_entry = ds_entry->queue_entries_head;
363 NULL != dq_entry;
364 dq_entry = ds_entry->queue_entries_head)
365 {
366 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
367 ds_entry->queue_entries_tail,
368 dq_entry);
369 for (child = dq_entry->set_entries_head;
370 NULL != child;
371 child = dq_entry->set_entries_head)
372 {
373 GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
374 dq_entry->set_entries_tail,
375 child);
376 cleanup_delegation_set (child);
377 }
378 GNUNET_free (dq_entry);
379 }
380 GNUNET_free_non_null (ds_entry->issuer_key);
381 GNUNET_free_non_null (ds_entry->lookup_attribute);
382 GNUNET_free_non_null (ds_entry->issuer_attribute);
383 GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation);
384 GNUNET_free_non_null (ds_entry->attr_trailer);
385 if (NULL != ds_entry->lookup_request)
386 {
387 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
388 ds_entry->lookup_request = NULL;
389 }
390 if (NULL != ds_entry->delegation_chain_entry)
391 {
392 GNUNET_free_non_null (ds_entry->delegation_chain_entry->subject_attribute);
393 GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute);
394 GNUNET_free (ds_entry->delegation_chain_entry);
395 }
396 GNUNET_free (ds_entry);
397}
398
399static void
400cleanup_handle (struct VerifyRequestHandle *vrh)
401{
402 struct CredentialRecordEntry *cr_entry;
403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
404 "Cleaning up...\n");
405 if (NULL != vrh->lookup_request)
406 {
407 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
408 vrh->lookup_request = NULL;
409 }
410 cleanup_delegation_set (vrh->root_set);
411 GNUNET_free_non_null (vrh->issuer_attribute);
412 for (cr_entry = vrh->cred_chain_head;
413 NULL != vrh->cred_chain_head;
414 cr_entry = vrh->cred_chain_head)
415 {
416 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
417 vrh->cred_chain_tail,
418 cr_entry);
419 GNUNET_free_non_null (cr_entry->credential);
420 GNUNET_free (cr_entry);
421 }
422 GNUNET_free (vrh);
423}
424
425static void
426shutdown_task (void *cls)
427{
428 struct VerifyRequestHandle *vrh;
429
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
431 "Shutting down!\n");
432
433 while (NULL != (vrh = vrh_head))
434 {
435 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
436 GNUNET_CONTAINER_DLL_remove (vrh_head,
437 vrh_tail,
438 vrh);
439 cleanup_handle (vrh);
440 }
441
442 if (NULL != gns)
443 {
444 GNUNET_GNS_disconnect (gns);
445 gns = NULL;
446 }
447 if (NULL != namestore)
448 {
449 GNUNET_NAMESTORE_disconnect (namestore);
450 namestore = NULL;
451 }
452 if (NULL != statistics)
453 {
454 GNUNET_STATISTICS_destroy (statistics,
455 GNUNET_NO);
456 statistics = NULL;
457 }
458
459}
460
461
462
463static void
464send_lookup_response (struct VerifyRequestHandle *vrh)
465{
466 struct GNUNET_MQ_Envelope *env;
467 struct DelegationChainResultMessage *rmsg;
468 struct DelegationChainEntry *dce;
469 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
470 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
471 struct CredentialRecordEntry *cd;
472 struct CredentialRecordEntry *tmp;
473 size_t size;
474
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Sending response\n");
477 dce = vrh->delegation_chain_head;
478 for (uint32_t i=0;i<vrh->delegation_chain_size;i++)
479 {
480 dd[i].issuer_key = dce->issuer_key;
481 dd[i].subject_key = dce->subject_key;
482 dd[i].issuer_attribute = dce->issuer_attribute;
483 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
484 dd[i].subject_attribute_len = 0;
485 dd[i].subject_attribute = NULL;
486 if (NULL != dce->subject_attribute)
487 {
488 dd[i].subject_attribute = dce->subject_attribute;
489 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
490 }
491 dce = dce->next;
492 }
493
494 /**
495 * Remove all credentials not needed
496 */
497 for (cd = vrh->cred_chain_head; NULL != cd;)
498 {
499 if (cd->refcount > 0)
500 {
501 cd = cd->next;
502 continue;
503 }
504 tmp = cd;
505 cd = cd->next;
506 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
507 vrh->cred_chain_tail,
508 tmp);
509 GNUNET_free (tmp->credential);
510 GNUNET_free (tmp);
511 vrh->cred_chain_size--;
512 }
513
514 /**
515 * Get serialized record data
516 * Append at the end of rmsg
517 */
518 cd = vrh->cred_chain_head;
519 for (uint32_t i=0;i<vrh->cred_chain_size;i++)
520 {
521 cred[i].issuer_key = cd->credential->issuer_key;
522 cred[i].subject_key = cd->credential->subject_key;
523 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
524 cred[i].issuer_attribute = cd->credential->issuer_attribute;
525 cred[i].expiration = cd->credential->expiration;
526 cred[i].signature = cd->credential->signature;
527 cd = cd->next;
528 }
529 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
530 dd,
531 vrh->cred_chain_size,
532 cred);
533 env = GNUNET_MQ_msg_extra (rmsg,
534 size,
535 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
536 //Assign id so that client can find associated request
537 rmsg->id = vrh->request_id;
538 rmsg->d_count = htonl (vrh->delegation_chain_size);
539 rmsg->c_count = htonl (vrh->cred_chain_size);
540
541 if (0 < vrh->cred_chain_size)
542 rmsg->cred_found = htonl (GNUNET_YES);
543 else
544 rmsg->cred_found = htonl (GNUNET_NO);
545
546 GNUNET_assert (-1 !=
547 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
548 dd,
549 vrh->cred_chain_size,
550 cred,
551 size,
552 (char*)&rmsg[1]));
553
554 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
555 env);
556 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
557 cleanup_handle(vrh);
558
559 GNUNET_STATISTICS_update (statistics,
560 "Completed verifications", 1,
561 GNUNET_NO);
562}
563
564
565static void
566backward_resolution (void* cls,
567 uint32_t rd_count,
568 const struct GNUNET_GNSRECORD_Data *rd)
569{
570
571 struct VerifyRequestHandle *vrh;
572 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
573 struct CredentialRecordEntry *cred_pointer;
574 struct DelegationSetQueueEntry *current_set;
575 struct DelegationSetQueueEntry *ds_entry;
576 struct DelegationSetQueueEntry *tmp_set;
577 struct DelegationQueueEntry *dq_entry;
578 char *expanded_attr;
579 char *lookup_attribute;
580
581
582 current_set = cls;
583 current_set->lookup_request = NULL;
584 vrh = current_set->handle;
585 vrh->pending_lookups--;
586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
587 "Got %d attrs\n", rd_count);
588
589 // Each OR
590 for (uint32_t i=0; i < rd_count; i++)
591 {
592 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
593 continue;
594
595 sets = rd[i].data;
596 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
598 "Found new attribute delegation with %d sets. Creating new Job...\n",
599 ntohl (sets->set_count));
600
601 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
602 (const char*)&sets[1],
603 ntohl(sets->set_count),
604 set))
605 {
606 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
607 "Failed to deserialize!\n");
608 continue;
609 }
610 dq_entry = GNUNET_new (struct DelegationQueueEntry);
611 dq_entry->required_solutions = ntohl(sets->set_count);
612 dq_entry->parent_set = current_set;
613 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
614 current_set->queue_entries_tail,
615 dq_entry);
616 // Each AND
617 for (uint32_t j=0; j<ntohl(sets->set_count); j++)
618 {
619 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
620 if (NULL != current_set->attr_trailer)
621 {
622 if (0 == set[j].subject_attribute_len)
623 {
624 GNUNET_asprintf (&expanded_attr,
625 "%s",
626 current_set->attr_trailer);
627
628 } else {
629 GNUNET_asprintf (&expanded_attr,
630 "%s.%s",
631 set[j].subject_attribute,
632 current_set->attr_trailer);
633 }
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Expanded to %s\n", expanded_attr);
636 ds_entry->unresolved_attribute_delegation = expanded_attr;
637 } else {
638 if (0 != set[j].subject_attribute_len)
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
641 "Not Expanding %s\n", set[j].subject_attribute);
642 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
643 }
644 }
645
646 //Add a credential chain entry
647 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
648 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
649 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
650 GNUNET_memcpy (ds_entry->issuer_key,
651 &set[j].subject_key,
652 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
653 if (0 < set[j].subject_attribute_len)
654 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
655 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
656 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
657
658 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
659 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
660 dq_entry->set_entries_tail,
661 ds_entry);
662
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
664 "Checking for cred match\n");
665 /**
666 * Check if this delegation already matches one of our credentials
667 */
668 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
669 cred_pointer = cred_pointer->next)
670 {
671 if(0 != memcmp (&set->subject_key,
672 &cred_pointer->credential->issuer_key,
673 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
674 continue;
675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
676 "Checking if %s matches %s\n",
677 ds_entry->unresolved_attribute_delegation,
678 cred_pointer->credential->issuer_attribute);
679
680 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
681 cred_pointer->credential->issuer_attribute))
682 continue;
683
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
685 "Found issuer\n");
686 cred_pointer->refcount++;
687 //Backtrack
688 for (tmp_set = ds_entry;
689 NULL != tmp_set->parent_queue_entry;
690 tmp_set = tmp_set->parent_queue_entry->parent_set)
691 {
692 tmp_set->parent_queue_entry->required_solutions--;
693 if (NULL != tmp_set->delegation_chain_entry)
694 {
695 vrh->delegation_chain_size++;
696 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
697 vrh->delegation_chain_tail,
698 tmp_set->delegation_chain_entry);
699 }
700 if (0 < tmp_set->parent_queue_entry->required_solutions)
701 break;
702 }
703
704 if (NULL == tmp_set->parent_queue_entry)
705 {
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 "All solutions found\n");
708 //Found match
709 send_lookup_response (vrh);
710 return;
711 }
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "Not all solutions found yet.\n");
714 continue;
715
716 }
717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718 "Building new lookup request from %s\n",
719 ds_entry->unresolved_attribute_delegation);
720 //Continue with backward resolution
721 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
722 strcpy (issuer_attribute_name,
723 ds_entry->unresolved_attribute_delegation);
724 char *next_attr = strtok (issuer_attribute_name, ".");
725 GNUNET_asprintf (&lookup_attribute,
726 "%s.gnu",
727 next_attr);
728 GNUNET_asprintf (&ds_entry->lookup_attribute,
729 "%s",
730 next_attr);
731 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
732 {
733 ds_entry->attr_trailer = NULL;
734 } else {
735 next_attr += strlen (next_attr) + 1;
736 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
737 }
738
739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
740 "Looking up %s\n", ds_entry->lookup_attribute);
741 if (NULL != ds_entry->attr_trailer)
742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
743 "%s still to go...\n", ds_entry->attr_trailer);
744
745 vrh->pending_lookups++;
746 ds_entry->handle = vrh;
747 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
748 lookup_attribute,
749 ds_entry->issuer_key, //issuer_key,
750 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
751 GNUNET_GNS_LO_DEFAULT,
752 &backward_resolution,
753 ds_entry);
754 GNUNET_free (lookup_attribute);
755 }
756 }
757
758 if(0 == vrh->pending_lookups)
759 {
760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
761 "We are all out of attributes...\n");
762 send_lookup_response (vrh);
763 return;
764
765 }
766}
767
768
769/**
770 * Result from GNS lookup.
771 *
772 * @param cls the closure (our client lookup handle)
773 */
774static void
775delegation_chain_resolution_start (void* cls)
776{
777 struct VerifyRequestHandle *vrh = cls;
778 struct DelegationSetQueueEntry *ds_entry;
779 struct CredentialRecordEntry *cr_entry;
780 vrh->lookup_request = NULL;
781
782 if (0 == vrh->cred_chain_size)
783 {
784 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
785 "No credentials found\n");
786 send_lookup_response (vrh);
787 return;
788 }
789
790 for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
791 {
792 if (0 != memcmp (&cr_entry->credential->issuer_key,
793 &vrh->issuer_key,
794 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
795 continue;
796 if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
797 continue;
798 cr_entry->refcount++;
799 //Found match prematurely
800 send_lookup_response (vrh);
801 return;
802
803 }
804
805 /**
806 * Check for attributes from the issuer and follow the chain
807 * till you get the required subject's attributes
808 */
809 char issuer_attribute_name[strlen (vrh->issuer_attribute)];
810 strcpy (issuer_attribute_name,
811 vrh->issuer_attribute);
812 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
813 ".gnu");
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815 "Looking up %s\n", issuer_attribute_name);
816 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
817 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
818 memcpy (ds_entry->issuer_key,
819 &vrh->issuer_key,
820 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
821 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
822 ds_entry->handle = vrh;
823 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
824 vrh->root_set = ds_entry;
825 vrh->pending_lookups = 1;
826 //Start with backward resolution
827 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
828 issuer_attribute_name,
829 &vrh->issuer_key, //issuer_key,
830 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
831 GNUNET_GNS_LO_DEFAULT,
832 &backward_resolution,
833 ds_entry);
834}
835
836static int
837check_verify (void *cls,
838 const struct VerifyMessage *v_msg)
839{
840 size_t msg_size;
841 const char* attr;
842
843 msg_size = ntohs (v_msg->header.size);
844 if (msg_size < sizeof (struct VerifyMessage))
845 {
846 GNUNET_break (0);
847 return GNUNET_SYSERR;
848 }
849 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
850 {
851 GNUNET_break (0);
852 return GNUNET_SYSERR;
853 }
854 attr = (const char *) &v_msg[1];
855
856 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
857 {
858 GNUNET_break (0);
859 return GNUNET_SYSERR;
860 }
861 return GNUNET_OK;
862}
863
864static void
865handle_verify (void *cls,
866 const struct VerifyMessage *v_msg)
867{
868 struct VerifyRequestHandle *vrh;
869 struct GNUNET_SERVICE_Client *client = cls;
870 struct CredentialRecordEntry *cr_entry;
871 uint32_t credentials_count;
872 uint32_t credential_data_size;
873 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
874 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
875 char *attrptr = attr;
876 char *credential_data;
877 const char *utf_in;
878
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
880 "Received VERIFY message\n");
881 utf_in = (const char *) &v_msg[1];
882 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
883 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
884 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
885 vrh = GNUNET_new (struct VerifyRequestHandle);
886 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
887 vrh->client = client;
888 vrh->request_id = v_msg->id;
889 vrh->issuer_key = v_msg->issuer_key;
890 vrh->subject_key = v_msg->subject_key;
891 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
892 if (NULL == issuer_attribute)
893 {
894 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
895 "No issuer attribute provided!\n");
896 send_lookup_response (vrh);
897 return;
898 }
899 /**
900 * First, collect credentials
901 * TODO: cleanup!
902 */
903 credentials_count = ntohl(v_msg->c_count);
904 credential_data_size = ntohs (v_msg->header.size)
905 - sizeof (struct VerifyMessage)
906 - ntohs (v_msg->issuer_attribute_len)
907 - 1;
908 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
909 credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
910 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
911 credential_data,
912 credentials_count,
913 credentials))
914 {
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
916 "Cannot deserialize credentials!\n");
917 send_lookup_response (vrh);
918 return;
919 }
920
921 for (uint32_t i=0;i<credentials_count;i++) {
922 cr_entry = GNUNET_new (struct CredentialRecordEntry);
923 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
924 credentials[i].issuer_attribute_len);
925 GNUNET_memcpy (cr_entry->credential,
926 &credentials[i],
927 sizeof (struct GNUNET_CREDENTIAL_Credential));
928 GNUNET_memcpy (&cr_entry->credential[1],
929 credentials[i].issuer_attribute,
930 credentials[i].issuer_attribute_len);
931 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
932 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
933 vrh->cred_chain_tail,
934 cr_entry);
935 vrh->cred_chain_size++;
936 }
937
938 delegation_chain_resolution_start (vrh);
939
940}
941
942static void
943handle_cred_collection_error_cb (void *cls)
944{
945 struct VerifyRequestHandle *vrh = cls;
946 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
947 "Got disconnected from namestore database.\n");
948 vrh->cred_collection_iter = NULL;
949 send_lookup_response (vrh);
950}
951
952static void
953collect_next (void *cls)
954{
955 struct VerifyRequestHandle *vrh = cls;
956 vrh->collect_next_task = NULL;
957 GNUNET_assert (NULL != vrh->cred_collection_iter);
958 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
959}
960
961static void
962handle_cred_collection_cb (void *cls,
963 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
964 const char *label,
965 unsigned int rd_count,
966 const struct GNUNET_GNSRECORD_Data *rd)
967{
968 struct VerifyRequestHandle *vrh = cls;
969 struct GNUNET_CREDENTIAL_Credential *crd;
970 struct CredentialRecordEntry *cr_entry;
971 int cred_record_count;
972
973 cred_record_count = 0;
974 for (uint32_t i=0; i < rd_count; i++)
975 {
976 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
977 continue;
978 cred_record_count++;
979 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
980 rd[i].data_size);
981 if (NULL == crd)
982 {
983 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
984 "Invalid credential found\n");
985 continue;
986 }
987 cr_entry = GNUNET_new (struct CredentialRecordEntry);
988 cr_entry->credential = crd;
989 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
990 vrh->cred_chain_tail,
991 cr_entry);
992 vrh->cred_chain_size++;
993 }
994 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
995 vrh);
996}
997
998static void
999handle_cred_collection_finished_cb (void *cls)
1000{
1001 struct VerifyRequestHandle *vrh = cls;
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 "Done collecting credentials.\n");
1004 vrh->cred_collection_iter = NULL;
1005 delegation_chain_resolution_start (vrh);
1006}
1007
1008static void
1009handle_collect (void *cls,
1010 const struct CollectMessage *c_msg)
1011{
1012 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1013 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1014 struct VerifyRequestHandle *vrh;
1015 struct GNUNET_SERVICE_Client *client = cls;
1016 char *attrptr = attr;
1017 const char *utf_in;
1018
1019 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1020 "Received COLLECT message\n");
1021
1022 utf_in = (const char *) &c_msg[1];
1023 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1024
1025 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1026 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1027 vrh = GNUNET_new (struct VerifyRequestHandle);
1028 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1029 vrh->client = client;
1030 vrh->request_id = c_msg->id;
1031 vrh->issuer_key = c_msg->issuer_key;
1032 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1033 &vrh->subject_key);
1034 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1035
1036 if (NULL == issuer_attribute)
1037 {
1038 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1039 "No issuer attribute provided!\n");
1040 send_lookup_response (vrh);
1041 return;
1042 }
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1044 "Getting credentials for subject\n");
1045 /**
1046 * First, get attribute from subject
1047 */
1048 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
1049 &c_msg->subject_key,
1050 &handle_cred_collection_error_cb,
1051 vrh,
1052 &handle_cred_collection_cb,
1053 vrh,
1054 &handle_cred_collection_finished_cb,
1055 vrh);
1056}
1057
1058
1059static int
1060check_collect (void *cls,
1061 const struct CollectMessage *c_msg)
1062{
1063 size_t msg_size;
1064 const char* attr;
1065
1066 msg_size = ntohs (c_msg->header.size);
1067 if (msg_size < sizeof (struct CollectMessage))
1068 {
1069 GNUNET_break (0);
1070 return GNUNET_SYSERR;
1071 }
1072 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1073 {
1074 GNUNET_break (0);
1075 return GNUNET_SYSERR;
1076 }
1077 attr = (const char *) &c_msg[1];
1078
1079 if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
1080 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1081 {
1082 GNUNET_break (0);
1083 return GNUNET_SYSERR;
1084 }
1085 return GNUNET_OK;
1086}
1087
1088static void
1089client_disconnect_cb (void *cls,
1090 struct GNUNET_SERVICE_Client *client,
1091 void *app_ctx)
1092{
1093 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1094 "Client %p disconnected\n",
1095 client);
1096}
1097
1098static void *
1099client_connect_cb (void *cls,
1100 struct GNUNET_SERVICE_Client *client,
1101 struct GNUNET_MQ_Handle *mq)
1102{
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104 "Client %p connected\n",
1105 client);
1106 return client;
1107}
1108
1109/**
1110 * Process Credential requests.
1111 *
1112 * @param cls closure
1113 * @param c configuration to use
1114 * @param handle service handle
1115 */
1116static void
1117run (void *cls,
1118 const struct GNUNET_CONFIGURATION_Handle *c,
1119 struct GNUNET_SERVICE_Handle *handle)
1120{
1121
1122 gns = GNUNET_GNS_connect (c);
1123 if (NULL == gns)
1124 {
1125 fprintf (stderr,
1126 _("Failed to connect to GNS\n"));
1127 }
1128 namestore = GNUNET_NAMESTORE_connect (c);
1129 if (NULL == namestore)
1130 {
1131 fprintf (stderr,
1132 _("Failed to connect to namestore\n"));
1133 }
1134
1135 statistics = GNUNET_STATISTICS_create ("credential", c);
1136 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1137}
1138
1139
1140/**
1141 * Define "main" method using service macro
1142 */
1143GNUNET_SERVICE_MAIN
1144("credential",
1145 GNUNET_SERVICE_OPTION_NONE,
1146 &run,
1147 &client_connect_cb,
1148 &client_disconnect_cb,
1149 NULL,
1150 GNUNET_MQ_hd_var_size (verify,
1151 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1152 struct VerifyMessage,
1153 NULL),
1154 GNUNET_MQ_hd_var_size (collect,
1155 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1156 struct CollectMessage,
1157 NULL),
1158 GNUNET_MQ_handler_end());
1159
1160/* end of gnunet-service-credential.c */
diff --git a/src/credential/plugin_gnsrecord_credential.c b/src/credential/plugin_gnsrecord_credential.c
new file mode 100644
index 000000000..342790b7a
--- /dev/null
+++ b/src/credential/plugin_gnsrecord_credential.c
@@ -0,0 +1,353 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file credential/plugin_gnsrecord_credential.c
23 * @brief gnsrecord plugin to provide the API for CREDENTIAL records
24 * @author Martin Schanzenbach
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_credential_service.h"
31#include "gnunet_gnsrecord_plugin.h"
32#include "gnunet_signatures.h"
33#include "credential_serialization.h"
34#include "credential_misc.h"
35
36/**
37 * Convert the 'value' of a record to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the record
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46credential_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51
52 const char *cdata;
53
54 switch (type)
55 {
56 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
57 {
58 struct GNUNET_CREDENTIAL_DelegationRecord sets;
59 char *attr_str;
60 char *subject_pkey;
61 char *tmp_str;
62 int i;
63 if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
64 return NULL; /* malformed */
65 memcpy (&sets,
66 data,
67 sizeof (sets));
68 cdata = data;
69 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
70 if (GNUNET_OK != GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll (sets.data_size),
71 &cdata[sizeof (sets)],
72 ntohl (sets.set_count),
73 set))
74 return NULL;
75
76 for (i=0;i<ntohl(sets.set_count);i++)
77 {
78 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key);
79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
80 "%d len attr\n", set[i].subject_attribute_len);
81 if (0 == set[i].subject_attribute_len)
82 {
83 if (0 == i)
84 {
85 GNUNET_asprintf (&attr_str,
86 "%s",
87 subject_pkey);
88 } else {
89 GNUNET_asprintf (&tmp_str,
90 "%s,%s",
91 attr_str,
92 subject_pkey);
93 GNUNET_free (attr_str);
94 attr_str = tmp_str;
95 }
96 } else {
97 if (0 == i)
98 {
99 GNUNET_asprintf (&attr_str,
100 "%s %s",
101 subject_pkey,
102 set[i].subject_attribute);
103 } else {
104 GNUNET_asprintf (&tmp_str,
105 "%s,%s %s",
106 attr_str,
107 subject_pkey,
108 set[i].subject_attribute);
109 GNUNET_free (attr_str);
110 attr_str = tmp_str;
111 }
112 }
113 GNUNET_free (subject_pkey);
114 }
115 return attr_str;
116 }
117 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
118 {
119 struct GNUNET_CREDENTIAL_Credential *cred;
120 char *cred_str;
121
122 cred = GNUNET_CREDENTIAL_credential_deserialize (data,
123 data_size);
124 cred_str = GNUNET_CREDENTIAL_credential_to_string (cred);
125 GNUNET_free (cred);
126 return cred_str;
127 }
128 case GNUNET_GNSRECORD_TYPE_POLICY:
129 {
130 return GNUNET_strndup (data,data_size);
131 }
132 default:
133 return NULL;
134 }
135}
136
137
138/**
139 * Convert human-readable version of a 'value' of a record to the binary
140 * representation.
141 *
142 * @param cls closure, unused
143 * @param type type of the record
144 * @param s human-readable string
145 * @param data set to value in binary encoding (will be allocated)
146 * @param data_size set to number of bytes in @a data
147 * @return #GNUNET_OK on success
148 */
149static int
150credential_string_to_value (void *cls,
151 uint32_t type,
152 const char *s,
153 void **data,
154 size_t *data_size)
155{
156 if (NULL == s)
157 return GNUNET_SYSERR;
158 switch (type)
159 {
160 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
161 {
162 struct GNUNET_CREDENTIAL_DelegationRecord *sets;
163 char attr_str[253 + 1];
164 char subject_pkey[52 + 1];
165 char *token;
166 char *tmp_str;
167 int matches = 0;
168 int entries;
169 size_t tmp_data_size;
170 int i;
171
172 tmp_str = GNUNET_strdup (s);
173 token = strtok (tmp_str, ",");
174 entries = 0;
175 tmp_data_size = 0;
176 *data_size = sizeof (struct GNUNET_CREDENTIAL_DelegationRecord);
177 while (NULL != token)
178 {
179 matches = SSCANF (token,
180 "%s %s",
181 subject_pkey,
182 attr_str);
183 if (0 == matches)
184 {
185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186 _("Unable to parse ATTR record string `%s'\n"),
187 s);
188 GNUNET_free (tmp_str);
189 return GNUNET_SYSERR;
190 }
191 if (1 == matches) {
192 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet);
193 } else if (2 == matches) {
194 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
195 }
196 entries++;
197 token = strtok (NULL, ",");
198 }
199 GNUNET_free (tmp_str);
200 tmp_str = GNUNET_strdup (s);
201 token = strtok (tmp_str, ",");
202 struct GNUNET_CREDENTIAL_DelegationSet set[entries];
203 for (i=0;i<entries;i++)
204 {
205 matches = SSCANF (token,
206 "%s %s",
207 subject_pkey,
208 attr_str);
209 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
210 strlen (subject_pkey),
211 &set[i].subject_key);
212 if (2 == matches) {
213 set[i].subject_attribute_len = strlen (attr_str) + 1;
214 set[i].subject_attribute = GNUNET_strdup (attr_str);
215 }
216 token = strtok (NULL , ",");
217 }
218 tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
219 set);
220
221 if (-1 == tmp_data_size)
222 return GNUNET_SYSERR;
223 *data_size += tmp_data_size;
224 *data = sets = GNUNET_malloc (*data_size);
225 GNUNET_CREDENTIAL_delegation_set_serialize (entries,
226 set,
227 tmp_data_size,
228 (char*)&sets[1]);
229 for (i=0;i<entries;i++)
230 {
231 if (0 != set[i].subject_attribute_len)
232 GNUNET_free ((char*)set[i].subject_attribute);
233 }
234 sets->set_count = htonl (entries);
235 sets->data_size = GNUNET_htonll (tmp_data_size);
236
237 GNUNET_free (tmp_str);
238 return GNUNET_OK;
239 }
240 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
241 {
242 struct GNUNET_CREDENTIAL_Credential *cred;
243 cred = GNUNET_CREDENTIAL_credential_from_string (s);
244
245 *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
246 (char**)data);
247 return GNUNET_OK;
248 }
249 case GNUNET_GNSRECORD_TYPE_POLICY:
250 {
251 *data_size = strlen (s);
252 *data = GNUNET_strdup (s);
253 return GNUNET_OK;
254 }
255 default:
256 return GNUNET_SYSERR;
257 }
258}
259
260
261/**
262 * Mapping of record type numbers to human-readable
263 * record type names.
264 */
265static struct {
266 const char *name;
267 uint32_t number;
268} name_map[] = {
269 { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
270 { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
271 { "POLICY", GNUNET_GNSRECORD_TYPE_POLICY },
272 { NULL, UINT32_MAX }
273};
274
275
276/**
277 * Convert a type name (i.e. "AAAA") to the corresponding number.
278 *
279 * @param cls closure, unused
280 * @param gns_typename name to convert
281 * @return corresponding number, UINT32_MAX on error
282 */
283static uint32_t
284credential_typename_to_number (void *cls,
285 const char *gns_typename)
286{
287 unsigned int i;
288
289 i=0;
290 while ( (name_map[i].name != NULL) &&
291 (0 != strcasecmp (gns_typename, name_map[i].name)) )
292 i++;
293 return name_map[i].number;
294}
295
296
297/**
298 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
299 *
300 * @param cls closure, unused
301 * @param type number of a type to convert
302 * @return corresponding typestring, NULL on error
303 */
304static const char *
305credential_number_to_typename (void *cls,
306 uint32_t type)
307{
308 unsigned int i;
309
310 i=0;
311 while ( (name_map[i].name != NULL) &&
312 (type != name_map[i].number) )
313 i++;
314 return name_map[i].name;
315}
316
317
318/**
319 * Entry point for the plugin.
320 *
321 * @param cls NULL
322 * @return the exported block API
323 */
324void *
325libgnunet_plugin_gnsrecord_credential_init (void *cls)
326{
327 struct GNUNET_GNSRECORD_PluginFunctions *api;
328
329 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
330 api->value_to_string = &credential_value_to_string;
331 api->string_to_value = &credential_string_to_value;
332 api->typename_to_number = &credential_typename_to_number;
333 api->number_to_typename = &credential_number_to_typename;
334 return api;
335}
336
337
338/**
339 * Exit point from the plugin.
340 *
341 * @param cls the return value from #libgnunet_plugin_block_test_init
342 * @return NULL
343 */
344void *
345libgnunet_plugin_gnsrecord_credential_done (void *cls)
346{
347 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
348
349 GNUNET_free (api);
350 return NULL;
351}
352
353/* end of plugin_gnsrecord_credential.c */
diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c
new file mode 100644
index 000000000..480658822
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,1146 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file credential/plugin_rest_credential.c
23 * @brief GNUnet CREDENTIAL REST plugin
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_rest_plugin.h"
29#include <gnunet_identity_service.h>
30#include <gnunet_gnsrecord_lib.h>
31#include <gnunet_namestore_service.h>
32#include <gnunet_credential_service.h>
33#include <gnunet_rest_lib.h>
34#include <gnunet_jsonapi_lib.h>
35#include <gnunet_jsonapi_util.h>
36#include <jansson.h>
37
38#define GNUNET_REST_API_NS_CREDENTIAL "/credential"
39
40#define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
41
42#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
43
44#define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
45
46#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
47
48#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
49
50#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
51
52#define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
53
54#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
55
56#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
57
58#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
59
60#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
61
62/**
63 * @brief struct returned by the initialization function of the plugin
64 */
65struct Plugin
66{
67 const struct GNUNET_CONFIGURATION_Handle *cfg;
68};
69
70const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72struct RequestHandle
73{
74 /**
75 * Handle to Credential service.
76 */
77 struct GNUNET_CREDENTIAL_Handle *credential;
78
79 /**
80 * Handle to lookup request
81 */
82 struct GNUNET_CREDENTIAL_Request *verify_request;
83
84 /**
85 * Handle to issue request
86 */
87 struct GNUNET_CREDENTIAL_Request *issue_request;
88
89 /**
90 * Handle to identity
91 */
92 struct GNUNET_IDENTITY_Handle *identity;
93
94 /**
95 * Handle to identity operation
96 */
97 struct GNUNET_IDENTITY_Operation *id_op;
98
99 /**
100 * Handle to ego lookup
101 */
102 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
103
104 /**
105 * Handle to rest request
106 */
107 struct GNUNET_REST_RequestHandle *rest_handle;
108
109 /**
110 * ID of a task associated with the resolution process.
111 */
112 struct GNUNET_SCHEDULER_Task * timeout_task;
113
114 /**
115 * The root of the received JSON or NULL
116 */
117 json_t *json_root;
118
119 /**
120 * The plugin result processor
121 */
122 GNUNET_REST_ResultProcessor proc;
123
124 /**
125 * The closure of the result processor
126 */
127 void *proc_cls;
128
129 /**
130 * The issuer attribute to verify
131 */
132 char *issuer_attr;
133
134 /**
135 * The subject attribute
136 */
137 char *subject_attr;
138
139 /**
140 * The public key of the issuer
141 */
142 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
143
144 /**
145 * The public key of the subject
146 */
147 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
148
149 /**
150 * HTTP response code
151 */
152 int response_code;
153
154 /**
155 * Timeout
156 */
157 struct GNUNET_TIME_Relative timeout;
158
159};
160
161
162/**
163 * Cleanup lookup handle.
164 *
165 * @param handle Handle to clean up
166 */
167static void
168cleanup_handle (struct RequestHandle *handle)
169{
170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
171 "Cleaning up\n");
172 if (NULL != handle->json_root)
173 json_decref (handle->json_root);
174
175 if (NULL != handle->issuer_attr)
176 GNUNET_free (handle->issuer_attr);
177 if (NULL != handle->subject_attr)
178 GNUNET_free (handle->subject_attr);
179 if (NULL != handle->verify_request)
180 GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
181 if (NULL != handle->credential)
182 GNUNET_CREDENTIAL_disconnect (handle->credential);
183 if (NULL != handle->id_op)
184 GNUNET_IDENTITY_cancel (handle->id_op);
185 if (NULL != handle->ego_lookup)
186 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
187 if (NULL != handle->identity)
188 GNUNET_IDENTITY_disconnect (handle->identity);
189 if (NULL != handle->timeout_task)
190 {
191 GNUNET_SCHEDULER_cancel (handle->timeout_task);
192 }
193 GNUNET_free (handle);
194}
195
196
197static void
198do_error (void *cls)
199{
200 struct RequestHandle *handle = cls;
201 struct MHD_Response *resp;
202
203 resp = GNUNET_REST_create_response (NULL);
204 handle->proc (handle->proc_cls, resp, handle->response_code);
205 cleanup_handle (handle);
206}
207
208/**
209 * Attribute delegation to JSON
210 *
211 * @param delegation_chain_entry the DSE
212 * @return JSON, NULL if failed
213 */
214static json_t*
215attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
216{
217 char *subject;
218 char *issuer;
219 json_t *attr_obj;
220
221 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
222 if (NULL == issuer)
223 {
224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 "Issuer in delegation malformed\n");
226 return NULL;
227 }
228 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
229 if (NULL == subject)
230 {
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 "Subject in credential malformed\n");
233 GNUNET_free (issuer);
234 return NULL;
235 }
236 attr_obj = json_object ();
237
238 json_object_set_new (attr_obj, "issuer", json_string (issuer));
239 json_object_set_new (attr_obj, "issuer_attribute",
240 json_string (delegation_chain_entry->issuer_attribute));
241
242 json_object_set_new (attr_obj, "subject", json_string (subject));
243 if (0 < delegation_chain_entry->subject_attribute_len)
244 {
245 json_object_set_new (attr_obj, "subject_attribute",
246 json_string (delegation_chain_entry->subject_attribute));
247 }
248 GNUNET_free (issuer);
249 GNUNET_free (subject);
250 return attr_obj;
251}
252
253/**
254 * JSONAPI resource to Credential
255 *
256 * @param res the JSONAPI resource
257 * @return the resulting credential, NULL if failed
258 */
259static struct GNUNET_CREDENTIAL_Credential*
260json_to_credential (json_t *res)
261{
262 struct GNUNET_CREDENTIAL_Credential *cred;
263 json_t *tmp;
264 const char *attribute;
265 const char *signature;
266 char *sig;
267
268 tmp = json_object_get (res, "attribute");
269 if (0 == json_is_string (tmp))
270 {
271 return NULL;
272 }
273 attribute = json_string_value (tmp);
274 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
275 + strlen (attribute));
276 cred->issuer_attribute = attribute;
277 cred->issuer_attribute_len = strlen (attribute);
278 tmp = json_object_get (res, "issuer");
279 if (0 == json_is_string (tmp))
280 {
281 GNUNET_free (cred);
282 return NULL;
283 }
284
285 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
286 strlen (json_string_value(tmp)),
287 &cred->issuer_key);
288 tmp = json_object_get (res, "subject");
289 if (0 == json_is_string (tmp))
290 {
291 GNUNET_free (cred);
292 return NULL;
293 }
294 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
295 strlen (json_string_value(tmp)),
296 &cred->subject_key);
297
298 tmp = json_object_get (res, "signature");
299 if (0 == json_is_string (tmp))
300 {
301 GNUNET_free (cred);
302 return NULL;
303 }
304 signature = json_string_value (tmp);
305 GNUNET_STRINGS_base64_decode (signature,
306 strlen (signature),
307 (char**)&sig);
308 GNUNET_memcpy (&cred->signature,
309 sig,
310 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
311 GNUNET_free (sig);
312
313 tmp = json_object_get (res, "expiration");
314 if (0 == json_is_integer (tmp))
315 {
316 GNUNET_free (cred);
317 return NULL;
318 }
319 cred->expiration.abs_value_us = json_integer_value (tmp);
320 return cred;
321}
322
323
324/**
325 * Credential to JSON
326 *
327 * @param cred the credential
328 * @return the resulting json, NULL if failed
329 */
330static json_t*
331credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
332{
333 char *issuer;
334 char *subject;
335 char *signature;
336 char attribute[cred->issuer_attribute_len + 1];
337 json_t *cred_obj;
338
339 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
340 if (NULL == issuer)
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
343 "Issuer in credential malformed\n");
344 return NULL;
345 }
346 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
347 if (NULL == subject)
348 {
349 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
350 "Subject in credential malformed\n");
351 GNUNET_free (issuer);
352 return NULL;
353 }
354 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
355 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
356 &signature);
357 memcpy (attribute,
358 cred->issuer_attribute,
359 cred->issuer_attribute_len);
360 attribute[cred->issuer_attribute_len] = '\0';
361 cred_obj = json_object ();
362 json_object_set_new (cred_obj, "issuer", json_string (issuer));
363 json_object_set_new (cred_obj, "subject", json_string (subject));
364 json_object_set_new (cred_obj, "attribute", json_string (attribute));
365 json_object_set_new (cred_obj, "signature", json_string (signature));
366 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
367 GNUNET_free (issuer);
368 GNUNET_free (subject);
369 GNUNET_free (signature);
370 return cred_obj;
371}
372
373static void
374handle_collect_response (void *cls,
375 unsigned int d_count,
376 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
377 unsigned int c_count,
378 struct GNUNET_CREDENTIAL_Credential *cred)
379{
380 struct RequestHandle *handle = cls;
381 struct MHD_Response *resp;
382 struct GNUNET_JSONAPI_Document *json_document;
383 struct GNUNET_JSONAPI_Resource *json_resource;
384 json_t *cred_obj;
385 json_t *cred_array;
386 char *result;
387 char *issuer;
388 char *id;
389 uint32_t i;
390
391 handle->verify_request = NULL;
392 if (NULL == cred) {
393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
394 "Verify failed.\n");
395 handle->response_code = MHD_HTTP_NOT_FOUND;
396 GNUNET_SCHEDULER_add_now (&do_error, handle);
397 return;
398 }
399 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
400 if (NULL == issuer)
401 {
402 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403 "Issuer in delegation malformed\n");
404 return;
405 }
406 GNUNET_asprintf (&id,
407 "%s.%s",
408 issuer,
409 handle->issuer_attr);
410 GNUNET_free (issuer);
411 json_document = GNUNET_JSONAPI_document_new ();
412 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
413 id);
414 GNUNET_free (id);
415 cred_array = json_array ();
416 for (i=0;i<c_count;i++)
417 {
418 cred_obj = credential_to_json (&cred[i]);
419 json_array_append_new (cred_array, cred_obj);
420 }
421 GNUNET_JSONAPI_resource_add_attr (json_resource,
422 GNUNET_REST_JSONAPI_CREDENTIAL,
423 cred_array);
424 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
425 GNUNET_JSONAPI_document_serialize (json_document, &result);
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
427 "Result %s\n",
428 result);
429 json_decref (cred_array);
430 GNUNET_JSONAPI_document_delete (json_document);
431 resp = GNUNET_REST_create_response (result);
432 GNUNET_free(result);
433 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
434 cleanup_handle (handle);
435}
436
437static void
438subject_ego_lookup (void *cls,
439 const struct GNUNET_IDENTITY_Ego *ego)
440{
441 struct RequestHandle *handle = cls;
442 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
443 handle->ego_lookup = NULL;
444
445 if (NULL == ego)
446 {
447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
448 "Subject not found\n");
449 GNUNET_SCHEDULER_add_now (&do_error, handle);
450 return;
451 }
452 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
453 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
454 &handle->issuer_key,
455 handle->issuer_attr,
456 sub_key,
457 &handle_collect_response,
458 handle);
459}
460
461
462
463static void
464handle_verify_response (void *cls,
465 unsigned int d_count,
466 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
467 unsigned int c_count,
468 struct GNUNET_CREDENTIAL_Credential *cred)
469{
470
471 struct RequestHandle *handle = cls;
472 struct MHD_Response *resp;
473 struct GNUNET_JSONAPI_Document *json_document;
474 struct GNUNET_JSONAPI_Resource *json_resource;
475 json_t *cred_obj;
476 json_t *attr_obj;
477 json_t *cred_array;
478 json_t *attr_array;
479 char *result;
480 char *issuer;
481 char *id;
482 uint32_t i;
483
484 handle->verify_request = NULL;
485 if (NULL == cred) {
486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
487 "Verify failed.\n");
488 handle->response_code = MHD_HTTP_NOT_FOUND;
489 GNUNET_SCHEDULER_add_now (&do_error, handle);
490 return;
491 }
492 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
493 if (NULL == issuer)
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
496 "Issuer in delegation malformed\n");
497 return;
498 }
499 GNUNET_asprintf (&id,
500 "%s.%s",
501 issuer,
502 handle->issuer_attr);
503 GNUNET_free (issuer);
504 json_document = GNUNET_JSONAPI_document_new ();
505 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
506 id);
507 GNUNET_free (id);
508 attr_array = json_array ();
509 for (i = 0; i < d_count; i++)
510 {
511 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
512 json_array_append_new (attr_array, attr_obj);
513 }
514 cred_array = json_array ();
515 for (i=0;i<c_count;i++)
516 {
517 cred_obj = credential_to_json (&cred[i]);
518 json_array_append_new (cred_array, cred_obj);
519 }
520 GNUNET_JSONAPI_resource_add_attr (json_resource,
521 GNUNET_REST_JSONAPI_CREDENTIAL,
522 cred_array);
523 GNUNET_JSONAPI_resource_add_attr (json_resource,
524 GNUNET_REST_JSONAPI_DELEGATIONS,
525 attr_array);
526 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
527 GNUNET_JSONAPI_document_serialize (json_document, &result);
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Result %s\n",
530 result);
531 json_decref (attr_array);
532 json_decref (cred_array);
533 GNUNET_JSONAPI_document_delete (json_document);
534 resp = GNUNET_REST_create_response (result);
535 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
536 GNUNET_free (result);
537 cleanup_handle (handle);
538}
539
540static void
541collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
542 const char* url,
543 void *cls)
544{
545 struct RequestHandle *handle = cls;
546 struct GNUNET_HashCode key;
547 char *tmp;
548 char *entity_attr;
549
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
551 "Connecting...\n");
552 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
553 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
554 &do_error, handle);
555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
556 "Connected\n");
557 if (NULL == handle->credential)
558 {
559 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560 "Connecting to CREDENTIAL failed\n");
561 GNUNET_SCHEDULER_add_now (&do_error, handle);
562 return;
563 }
564 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
565 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
566 &key);
567 if ( GNUNET_NO ==
568 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
569 &key) )
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 "Missing issuer attribute\n");
573 GNUNET_SCHEDULER_add_now (&do_error, handle);
574 return;
575 }
576 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
577 &key);
578 entity_attr = GNUNET_strdup (tmp);
579 tmp = strtok(entity_attr, ".");
580 if (NULL == tmp)
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
583 "Malformed issuer or attribute\n");
584 GNUNET_free (entity_attr);
585 GNUNET_SCHEDULER_add_now (&do_error, handle);
586 return;
587 }
588 if (GNUNET_OK !=
589 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
590 strlen (tmp),
591 &handle->issuer_key))
592 {
593 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
594 "Malformed issuer key\n");
595 GNUNET_free (entity_attr);
596 GNUNET_SCHEDULER_add_now (&do_error, handle);
597 return;
598 }
599 tmp = strtok (NULL, "."); //Issuer attribute
600 if (NULL == tmp)
601 {
602 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603 "Malformed attribute\n");
604 GNUNET_free (entity_attr);
605 GNUNET_SCHEDULER_add_now (&do_error, handle);
606 return;
607 }
608 handle->issuer_attr = GNUNET_strdup (tmp);
609 GNUNET_free (entity_attr);
610
611 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
612 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
613 &key);
614 if ( GNUNET_NO ==
615 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
616 &key) )
617 {
618 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619 "Missing subject\n");
620 GNUNET_free (entity_attr);
621 GNUNET_SCHEDULER_add_now (&do_error, handle);
622 return;
623 }
624 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
625 &key);
626 if (NULL == tmp)
627 {
628 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
629 "Malformed subject\n");
630 GNUNET_free (entity_attr);
631 GNUNET_SCHEDULER_add_now (&do_error, handle);
632 return;
633 }
634 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
635 tmp,
636 &subject_ego_lookup,
637 handle);
638}
639
640
641
642static void
643verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
644 const char* url,
645 void *cls)
646{
647 struct RequestHandle *handle = cls;
648 struct GNUNET_HashCode key;
649 struct GNUNET_JSONAPI_Document *json_obj;
650 struct GNUNET_JSONAPI_Resource *res;
651 struct GNUNET_CREDENTIAL_Credential *cred;
652 char *tmp;
653 char *entity_attr;
654 int i;
655 uint32_t credential_count;
656 uint32_t resource_count;
657 json_t *cred_json;
658 json_t *data_js;
659 json_error_t err;
660
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "Connecting...\n");
663 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
664 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
665 &do_error, handle);
666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
667 "Connected\n");
668 if (NULL == handle->credential)
669 {
670 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
671 "Connecting to CREDENTIAL failed\n");
672 GNUNET_SCHEDULER_add_now (&do_error, handle);
673 return;
674 }
675 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
676 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
677 &key);
678 if ( GNUNET_NO ==
679 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
680 &key) )
681 {
682 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
683 "Missing issuer attribute\n");
684 GNUNET_SCHEDULER_add_now (&do_error, handle);
685 return;
686 }
687 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
688 &key);
689 entity_attr = GNUNET_strdup (tmp);
690 tmp = strtok(entity_attr, ".");
691 if (NULL == tmp)
692 {
693 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
694 "Malformed issuer or attribute\n");
695 GNUNET_free (entity_attr);
696 GNUNET_SCHEDULER_add_now (&do_error, handle);
697 return;
698 }
699 if (GNUNET_OK !=
700 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
701 strlen (tmp),
702 &handle->issuer_key))
703 {
704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
705 "Malformed issuer key\n");
706 GNUNET_free (entity_attr);
707 GNUNET_SCHEDULER_add_now (&do_error, handle);
708 return;
709 }
710 tmp = strtok (NULL, "."); //Issuer attribute
711 if (NULL == tmp)
712 {
713 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
714 "Malformed attribute\n");
715 GNUNET_free (entity_attr);
716 GNUNET_SCHEDULER_add_now (&do_error, handle);
717 return;
718 }
719 handle->issuer_attr = GNUNET_strdup (tmp);
720 GNUNET_free (entity_attr);
721
722 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
723 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
724 &key);
725 if ( GNUNET_NO ==
726 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
727 &key) )
728 {
729 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
730 "Missing subject key\n");
731 GNUNET_free (entity_attr);
732 GNUNET_SCHEDULER_add_now (&do_error, handle);
733 return;
734 }
735 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
736 &key);
737 if (NULL == tmp)
738 {
739 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
740 "Malformed subject\n");
741 GNUNET_free (entity_attr);
742 GNUNET_SCHEDULER_add_now (&do_error, handle);
743 return;
744 }
745 if (GNUNET_OK !=
746 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
747 strlen (tmp),
748 &handle->subject_key)) {
749 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
750 "Malformed subject key\n");
751 GNUNET_free (entity_attr);
752 GNUNET_SCHEDULER_add_now (&do_error, handle);
753 return;
754 }
755
756 if (0 >= handle->rest_handle->data_size)
757 {
758 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
759 "Missing credentials\n");
760 GNUNET_SCHEDULER_add_now (&do_error, handle);
761 return;
762 }
763
764 struct GNUNET_JSON_Specification docspec[] = {
765 GNUNET_JSON_spec_jsonapi_document (&json_obj),
766 GNUNET_JSON_spec_end()
767 };
768 char term_data[handle->rest_handle->data_size+1];
769 term_data[handle->rest_handle->data_size] = '\0';
770 credential_count = 0;
771 GNUNET_memcpy (term_data,
772 handle->rest_handle->data,
773 handle->rest_handle->data_size);
774 data_js = json_loads (term_data,
775 JSON_DECODE_ANY,
776 &err);
777 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
778 NULL, NULL));
779 json_decref (data_js);
780 if (NULL == json_obj)
781 {
782 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
783 "Unable to parse JSONAPI Object from %s\n",
784 term_data);
785 GNUNET_SCHEDULER_add_now (&do_error, handle);
786 return;
787 }
788
789 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
790 GNUNET_assert (1 == resource_count);
791 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
792 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
793 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
794 {
795 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
796 "Resource not a credential!\n");
797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
798 "Unable to parse JSONAPI Object from %s\n",
799 term_data);
800 GNUNET_JSONAPI_document_delete (json_obj);
801 GNUNET_SCHEDULER_add_now (&do_error, handle);
802 return;
803 }
804 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
805 GNUNET_REST_JSONAPI_CREDENTIAL);
806
807 GNUNET_assert (json_is_array (cred_json));
808
809 credential_count = json_array_size(cred_json);
810
811 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
812 for (i=0;i<credential_count;i++)
813 {
814 cred = json_to_credential (json_array_get (cred_json, i));
815 if (NULL == cred)
816 {
817 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
818 "Unable to parse credential!\n");
819 continue;
820 }
821 GNUNET_memcpy (&credentials[i],
822 cred,
823 sizeof (struct GNUNET_CREDENTIAL_Credential));
824 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
825 GNUNET_free (cred);
826 }
827 GNUNET_JSONAPI_document_delete(json_obj);
828 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
829 &handle->issuer_key,
830 handle->issuer_attr,
831 &handle->subject_key,
832 credential_count,
833 credentials,
834 &handle_verify_response,
835 handle);
836 for (i=0;i<credential_count;i++)
837 GNUNET_free ((char*)credentials[i].issuer_attribute);
838
839}
840
841void
842send_cred_response (struct RequestHandle *handle,
843 struct GNUNET_CREDENTIAL_Credential *cred)
844{
845 struct MHD_Response *resp;
846 struct GNUNET_JSONAPI_Document *json_document;
847 struct GNUNET_JSONAPI_Resource *json_resource;
848 json_t *cred_obj;
849 char *result;
850 char *issuer;
851 char *subject;
852 char *signature;
853 char *id;
854
855 GNUNET_assert (NULL != cred);
856 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
857 if (NULL == issuer)
858 {
859 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
860 "Subject malformed\n");
861 return;
862 }
863 GNUNET_asprintf (&id,
864 "%s.%s",
865 issuer,
866 (char*)&cred[1]);
867 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
868 if (NULL == subject)
869 {
870 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
871 "Subject malformed\n");
872 return;
873 }
874 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
875 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
876 &signature);
877 json_document = GNUNET_JSONAPI_document_new ();
878 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
879 id);
880 GNUNET_free (id);
881 cred_obj = json_object();
882 json_object_set_new (cred_obj, "issuer", json_string (issuer));
883 json_object_set_new (cred_obj, "subject", json_string (subject));
884 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
885 json_object_set_new (cred_obj, "signature", json_string (signature));
886 GNUNET_JSONAPI_resource_add_attr (json_resource,
887 GNUNET_REST_JSONAPI_CREDENTIAL,
888 cred_obj);
889 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
890 GNUNET_JSONAPI_document_serialize (json_document, &result);
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
892 "Result %s\n",
893 result);
894 json_decref (cred_obj);
895 GNUNET_JSONAPI_document_delete (json_document);
896 resp = GNUNET_REST_create_response (result);
897 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
898 GNUNET_free (result);
899 GNUNET_free (signature);
900 GNUNET_free (issuer);
901 GNUNET_free (subject);
902 cleanup_handle (handle);
903}
904
905void
906get_cred_issuer_cb (void *cls,
907 struct GNUNET_IDENTITY_Ego *ego,
908 void **ctx,
909 const char *name)
910{
911 struct RequestHandle *handle = cls;
912 struct GNUNET_TIME_Absolute etime_abs;
913 struct GNUNET_TIME_Relative etime_rel;
914 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
915 struct GNUNET_HashCode key;
916 struct GNUNET_CREDENTIAL_Credential *cred;
917 char* expiration_str;
918 char* tmp;
919
920 handle->id_op = NULL;
921
922 if (NULL == name)
923 {
924 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
925 "Issuer not configured!\n");
926 GNUNET_SCHEDULER_add_now (&do_error, handle);
927 return;
928 }
929
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 "Connecting to credential service...\n");
932 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
934 "Connected\n");
935 if (NULL == handle->credential)
936 {
937 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
938 "Connecting to CREDENTIAL failed\n");
939 GNUNET_SCHEDULER_add_now (&do_error, handle);
940 return;
941 }
942 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
943 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
944 &key);
945 if ( GNUNET_NO ==
946 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
947 &key) )
948 {
949 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
950 "Missing expiration\n");
951 GNUNET_SCHEDULER_add_now (&do_error, handle);
952 return;
953 }
954 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
955 &key);
956 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
957 &etime_rel))
958 {
959 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
960 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
961 &etime_abs))
962 {
963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
964 "Malformed expiration: %s\n", expiration_str);
965 GNUNET_SCHEDULER_add_now (&do_error, handle);
966 return;
967 }
968 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
969 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
970 &key);
971 if ( GNUNET_NO ==
972 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
973 &key) )
974 {
975 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
976 "Missing issuer attribute\n");
977 GNUNET_SCHEDULER_add_now (&do_error, handle);
978 return;
979 }
980 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
981 (handle->rest_handle->url_param_map,
982 &key));
983 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
984 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
985 &key);
986 if ( GNUNET_NO ==
987 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
988 &key) )
989 {
990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
991 "Missing subject\n");
992 GNUNET_SCHEDULER_add_now (&do_error, handle);
993 return;
994 }
995 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
996 &key);
997 if (NULL == tmp)
998 {
999 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1000 "Malformed subject\n");
1001 GNUNET_SCHEDULER_add_now (&do_error, handle);
1002 return;
1003 }
1004 if (GNUNET_OK !=
1005 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1006 strlen (tmp),
1007 &handle->subject_key)) {
1008 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1009 "Malformed subject key\n");
1010 GNUNET_SCHEDULER_add_now (&do_error, handle);
1011 return;
1012 }
1013 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1014 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1015 &handle->subject_key,
1016 handle->issuer_attr,
1017 &etime_abs);
1018 if (NULL == cred)
1019 {
1020 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1021 "Failed to create credential\n");
1022 GNUNET_SCHEDULER_add_now (&do_error, handle);
1023 return;
1024 }
1025 send_cred_response (handle, cred);
1026}
1027
1028
1029static void
1030issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1031 const char* url,
1032 void *cls)
1033{
1034 struct RequestHandle *handle = cls;
1035
1036 handle->identity = GNUNET_IDENTITY_connect (cfg,
1037 NULL,
1038 NULL);
1039 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1040 "credential-issuer",
1041 &get_cred_issuer_cb,
1042 handle);
1043 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1044 &do_error,
1045 handle);
1046}
1047
1048static void
1049options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1050 const char* url,
1051 void *cls)
1052{
1053 struct MHD_Response *resp;
1054 struct RequestHandle *handle = cls;
1055
1056 //For GNS, independent of path return all options
1057 resp = GNUNET_REST_create_response (NULL);
1058 MHD_add_response_header (resp,
1059 "Access-Control-Allow-Methods",
1060 MHD_HTTP_METHOD_GET);
1061 handle->proc (handle->proc_cls,
1062 resp,
1063 MHD_HTTP_OK);
1064 cleanup_handle (handle);
1065}
1066
1067
1068static void
1069rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1070 GNUNET_REST_ResultProcessor proc,
1071 void *proc_cls)
1072{
1073 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1074 struct GNUNET_REST_RequestHandlerError err;
1075
1076 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1077 handle->proc_cls = proc_cls;
1078 handle->proc = proc;
1079 handle->rest_handle = conndata_handle;
1080
1081 static const struct GNUNET_REST_RequestHandler handlers[] = {
1082 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1083 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1084 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1085 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1086 GNUNET_REST_HANDLER_END
1087 };
1088
1089 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1090 handlers,
1091 &err,
1092 handle))
1093 {
1094 handle->response_code = err.error_code;
1095 GNUNET_SCHEDULER_add_now (&do_error, handle);
1096 }
1097}
1098
1099
1100/**
1101 * Entry point for the plugin.
1102 *
1103 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1104 * @return NULL on error, otherwise the plugin context
1105 */
1106void *
1107libgnunet_plugin_rest_credential_init (void *cls)
1108{
1109 static struct Plugin plugin;
1110 cfg = cls;
1111 struct GNUNET_REST_Plugin *api;
1112
1113 if (NULL != plugin.cfg)
1114 return NULL; /* can only initialize once! */
1115 memset (&plugin, 0, sizeof (struct Plugin));
1116 plugin.cfg = cfg;
1117 api = GNUNET_new (struct GNUNET_REST_Plugin);
1118 api->cls = &plugin;
1119 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1120 api->process_request = &rest_credential_process_request;
1121 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1122 _("GNS REST API initialized\n"));
1123 return api;
1124}
1125
1126
1127/**
1128 * Exit point from the plugin.
1129 *
1130 * @param cls the plugin context (as returned by "init")
1131 * @return always NULL
1132 */
1133void *
1134libgnunet_plugin_rest_credential_done (void *cls)
1135{
1136 struct GNUNET_REST_Plugin *api = cls;
1137 struct Plugin *plugin = api->cls;
1138
1139 plugin->cfg = NULL;
1140 GNUNET_free (api);
1141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1142 "GNS REST plugin is finished\n");
1143 return NULL;
1144}
1145
1146/* end of plugin_rest_gns.c */
diff --git a/src/credential/test_credential_collect.sh b/src/credential/test_credential_collect.sh
new file mode 100755
index 000000000..6c713063f
--- /dev/null
+++ b/src/credential/test_credential_collect.sh
@@ -0,0 +1,47 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26TEST_ATTR2="test2"
27gnunet-arm -s -c test_credential_lookup.conf
28gnunet-identity -C testissuer -c test_credential_lookup.conf
29gnunet-identity -C testsubject -c test_credential_lookup.conf
30SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
31ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
32#TODO1 Get credential and store it with subject (3)
33CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
34$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
35CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c test_credential_lookup.conf`
36$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
37CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste -d, -s`
38echo $CREDS
39RES=$?
40gnunet-arm -e -c test_credential_lookup.conf
41
42if test $? != 0
43then
44 echo "Error collecting..."
45 exit 1
46fi
47
diff --git a/src/credential/test_credential_collect_rest.sh b/src/credential/test_credential_collect_rest.sh
new file mode 100755
index 000000000..0b31f85bc
--- /dev/null
+++ b/src/credential/test_credential_collect_rest.sh
@@ -0,0 +1,90 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60# (5) GNUnet issues Alice the credential "developer"
61CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
62
63# Alice stores the credential under "mygnunetcreds"
64gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
65
66#TODO2 Add -z swich like in gnunet-gns
67#RES_CRED=`gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY -c test_credential_lookup.conf`
68
69gnunet-arm -i rest -c test_credential_lookup.conf
70
71sleep 5
72
73curl -v "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"
74
75#TODO cleanup properly
76gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
77gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
78gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
79gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
80echo "Stopping arm..."
81gnunet-arm -e -c test_credential_lookup.conf
82echo "Done"
83if [ "$RES_CRED" != "Failed." ]
84then
85 echo -e "${RES_CRED}"
86 exit 0
87else
88 echo "FAIL: Failed to verify credential $RES_CRED."
89 exit 1
90fi
diff --git a/src/credential/test_credential_defaults.conf b/src/credential/test_credential_defaults.conf
new file mode 100644
index 000000000..d157ddd43
--- /dev/null
+++ b/src/credential/test_credential_defaults.conf
@@ -0,0 +1,24 @@
1@INLINE@ ../../contrib/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-credential-testing/
5
6[namestore-sqlite]
7FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
8
9[namecache-sqlite]
10FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
11
12[identity]
13# Directory where we store information about our egos
14EGODIR = $GNUNET_TEST_HOME/identity/egos/
15
16[dhtcache]
17DATABASE = heap
18
19[transport]
20PLUGINS = tcp
21
22[transport-tcp]
23BINDTO = 127.0.0.1
24
diff --git a/src/credential/test_credential_issue.sh b/src/credential/test_credential_issue.sh
new file mode 100755
index 000000000..158d91c5b
--- /dev/null
+++ b/src/credential/test_credential_issue.sh
@@ -0,0 +1,44 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C testissuer -c test_credential_lookup.conf
28gnunet-identity -C testsubject -c test_credential_lookup.conf
29SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
30ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
31#TODO1 Get credential and store it with subject (3)
32CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
33STATUS=$?
34
35if test $? != 0
36then
37 echo "Error issuing..."
38 exit 1
39fi
40#Try import
41$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
42RES=$?
43gnunet-arm -e -c test_credential_lookup.conf
44exit $RES
diff --git a/src/credential/test_credential_issue_rest.sh b/src/credential/test_credential_issue_rest.sh
new file mode 100755
index 000000000..15cd55083
--- /dev/null
+++ b/src/credential/test_credential_issue_rest.sh
@@ -0,0 +1,53 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-arm -i gns
28gnunet-arm -i credential
29gnunet-arm -i identity
30gnunet-arm -i rest -c test_credential_lookup.conf
31
32gnunet-arm -I -c test_credential_lookup.conf
33gnunet-identity -C testissuer -c test_credential_lookup.conf
34gnunet-identity -C testsubject -c test_credential_lookup.conf
35gnunet-identity -s credential-issuer -e testissuer
36SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
37ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
38#TODO1 Get credential and store it with subject (3)
39sleep 5
40curl "localhost:7776/credential/issue?subject_key=$SUBJECT_KEY&attribute=$TEST_ATTR&expiration=1d"
41#CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
42STATUS=$?
43
44if test $? != 0
45then
46 echo "Error issuing..."
47 exit 1
48fi
49#Try import
50#$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
51RES=$?
52gnunet-arm -e -c test_credential_lookup.conf
53exit $RES
diff --git a/src/credential/test_credential_lookup.conf b/src/credential/test_credential_lookup.conf
new file mode 100644
index 000000000..3684063b1
--- /dev/null
+++ b/src/credential/test_credential_lookup.conf
@@ -0,0 +1,28 @@
1@INLINE@ test_credential_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-credential-peer-1/
5
6[dht]
7AUTOSTART = YES
8
9[transport]
10PLUGINS =
11
12[credential]
13AUTOSTART = YES
14PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
15
16[rest]
17PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
18
19[gns]
20#PREFIX = valgrind --leak-check=full --track-origins=yes
21AUTOSTART = YES
22AUTO_IMPORT_PKEY = YES
23MAX_PARALLEL_BACKGROUND_QUERIES = 10
24DEFAULT_LOOKUP_TIMEOUT = 15 s
25RECORD_PUT_INTERVAL = 1 h
26ZONE_PUBLISH_TIME_WINDOW = 1 h
27DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
28
diff --git a/src/credential/test_credential_verify.sh b/src/credential/test_credential_verify.sh
new file mode 100755
index 000000000..d042bcfe6
--- /dev/null
+++ b/src/credential/test_credential_verify.sh
@@ -0,0 +1,81 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
61
62echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf
63#TODO2 Add -z swich like in gnunet-gns
64gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf
65
66
67#TODO cleanup properly
68gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
69gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
70gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
71gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
72gnunet-arm -e -c test_credential_lookup.conf
73
74if [ "$RES_CRED" != "Failed." ]
75then
76 echo -e "${RES_CRED}"
77 exit 0
78else
79 echo "FAIL: Failed to verify credential $RES_CRED."
80 exit 1
81fi
diff --git a/src/credential/test_credential_verify_and.sh b/src/credential/test_credential_verify_and.sh
new file mode 100755
index 000000000..9d5c1962e
--- /dev/null
+++ b/src/credential/test_credential_verify_and.sh
@@ -0,0 +1,81 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR,$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
52
53# (5) GNUnet issues Alice the credential "developer"
54CRED1=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
55# (5) GNUnet issues Alice the credential "user"
56CRED2=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED1" -e 5m -c test_credential_lookup.conf
59gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m -c test_credential_lookup.conf
60
61CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
62
63#TODO2 Add -z swich like in gnunet-gns
64RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf`
65
66
67#TODO cleanup properly
68gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
69gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
70gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
71gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
72gnunet-arm -e -c test_credential_lookup.conf
73
74if [ "$RES_CRED" != "Failed." ]
75then
76 echo -e "${RES_CRED}"
77 exit 0
78else
79 echo "FAIL: Failed to verify credential $RES_CRED."
80 exit 1
81fi
diff --git a/src/credential/test_credential_verify_rest.sh b/src/credential/test_credential_verify_rest.sh
new file mode 100755
index 000000000..6133ea25e
--- /dev/null
+++ b/src/credential/test_credential_verify_rest.sh
@@ -0,0 +1,87 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60#TODO2 Add -z swich like in gnunet-gns
61#RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
62
63gnunet-arm -i rest -c test_credential_lookup.conf
64
65sleep 5
66
67CREDS=`curl "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"`
68
69echo $CREDS
70
71curl -v "localhost:7776/credential/verify?attribute=$SERVICE_KEY.$USER_ATTR&subject_key=$ALICE_KEY" --data "$CREDS"
72
73#TODO cleanup properly
74gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
75gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
76gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
77gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
78gnunet-arm -e -c test_credential_lookup.conf
79
80if [ "$RES_CRED" != "Failed." ]
81then
82 echo -e "${RES_CRED}"
83 exit 0
84else
85 echo "FAIL: Failed to verify credential $RES_CRED."
86 exit 1
87fi
diff --git a/src/credential/test_credential_verify_simple.sh b/src/credential/test_credential_verify_simple.sh
new file mode 100755
index 000000000..c4fd8c7a3
--- /dev/null
+++ b/src/credential/test_credential_verify_simple.sh
@@ -0,0 +1,50 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (3) Isser.user -> Subject
19
20
21which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
22gnunet-arm -s -c test_credential_lookup.conf
23gnunet-identity -C testissuer -c test_credential_lookup.conf
24gnunet-identity -C testsubject -c test_credential_lookup.conf
25
26TEST_ATTR="user"
27SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
28ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
29CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
30
31TEST_CREDENTIAL="t1"
32gnunet-namestore -p -z testsubject -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
33
34#TODO2 Add -z swich like in gnunet-gns
35#RES_CRED=`$DO_TIMEOUT gnunet-credential --verify --issuer=$ISSUER_KEY --attribute="$TEST_ATTR" --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
36RES_CRED=`gnunet-credential --verify --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
37
38#TODO cleanup properly
39gnunet-namestore -z testsubject -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
40gnunet-identity -D testsubject -c test_credential_lookup.conf
41gnunet-arm -e -c test_credential_lookup.conf
42echo $RES_CRED
43#TODO3 proper test
44if [ "$RES_CRED" == "Successful." ]
45then
46 exit 0
47else
48 echo "FAIL: Failed to verify credential."
49 exit 1
50fi
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 7196a1844..d9a5dd684 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -3802,7 +3802,7 @@ run (void *cls,
3802 if (GNUNET_YES != 3802 if (GNUNET_YES !=
3803 GNUNET_OS_check_helper_binary (binary, 3803 GNUNET_OS_check_helper_binary (binary,
3804 GNUNET_YES, 3804 GNUNET_YES,
3805 "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) //no nat, ipv4 only 3805 "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) //no nat, ipv4 only
3806 { 3806 {
3807 GNUNET_free (binary); 3807 GNUNET_free (binary);
3808 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3808 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index 26293f4df..84c4ae189 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -244,10 +244,7 @@ handle_result (void *cls,
244 return; 244 return;
245 proc = lr->lookup_proc; 245 proc = lr->lookup_proc;
246 proc_cls = lr->proc_cls; 246 proc_cls = lr->proc_cls;
247 GNUNET_CONTAINER_DLL_remove (handle->lookup_head, 247
248 handle->lookup_tail,
249 lr);
250 GNUNET_free (lr);
251 GNUNET_assert (GNUNET_OK == 248 GNUNET_assert (GNUNET_OK ==
252 GNUNET_GNSRECORD_records_deserialize (mlen, 249 GNUNET_GNSRECORD_records_deserialize (mlen,
253 (const char*) &lookup_msg[1], 250 (const char*) &lookup_msg[1],
@@ -256,6 +253,12 @@ handle_result (void *cls,
256 proc (proc_cls, 253 proc (proc_cls,
257 rd_count, 254 rd_count,
258 rd); 255 rd);
256 GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
257 handle->lookup_tail,
258 lr);
259 if (NULL != lr->env)
260 GNUNET_MQ_discard (lr->env);
261 GNUNET_free (lr);
259} 262}
260 263
261 264
diff --git a/src/gns/plugin_gnsrecord_gns.c b/src/gns/plugin_gnsrecord_gns.c
index 5d611e19e..6adad0f34 100644
--- a/src/gns/plugin_gnsrecord_gns.c
+++ b/src/gns/plugin_gnsrecord_gns.c
@@ -140,30 +140,6 @@ gns_value_to_string (void *cls,
140 GNUNET_free (ival); 140 GNUNET_free (ival);
141 return box_str; 141 return box_str;
142 } 142 }
143 case GNUNET_GNSRECORD_TYPE_REVERSE:
144 {
145 struct GNUNET_GNSRECORD_ReverseRecord rev;
146 char *rev_str;
147 char *pkey_str;
148
149 if (data_size < sizeof (struct GNUNET_GNSRECORD_ReverseRecord))
150 return NULL; /* malformed */
151
152 memcpy (&rev,
153 data,
154 sizeof (rev));
155 cdata = data;
156 pkey_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&rev.pkey);
157
158 GNUNET_asprintf (&rev_str,
159 "%s %s %"SCNu64,
160 &cdata[sizeof (rev)],
161 pkey_str,
162 rev.expiration.abs_value_us);
163 GNUNET_free (pkey_str);
164 return rev_str;
165
166 }
167 default: 143 default:
168 return NULL; 144 return NULL;
169 } 145 }
@@ -335,48 +311,6 @@ gns_string_to_value (void *cls,
335 GNUNET_free (bval); 311 GNUNET_free (bval);
336 return GNUNET_OK; 312 return GNUNET_OK;
337 } 313 }
338 case GNUNET_GNSRECORD_TYPE_REVERSE:
339 {
340 struct GNUNET_GNSRECORD_ReverseRecord *rev;
341 char known_by[253 + 1];
342 struct GNUNET_TIME_Absolute expiration;
343
344 /* TODO: From crypto_ecc.c
345 * Why is this not a constant???
346 */
347 size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
348 if (enclen % 5 > 0)
349 enclen += 5 - enclen % 5;
350 enclen /= 5; /* 260/5 = 52 */
351 char pkey_str[enclen + 1];
352
353 if (3 != SSCANF (s,
354 "%253s %52s %"SCNu64,
355 known_by,
356 pkey_str,
357 &expiration.abs_value_us))
358 {
359 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
360 _("Unable to parse REVERSE record string `%s'\n"),
361 s);
362 return GNUNET_SYSERR;
363 }
364 *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1;
365 *data = rev = GNUNET_malloc (*data_size);
366 if (GNUNET_OK !=
367 GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str,
368 strlen (pkey_str),
369 &rev->pkey))
370 {
371 GNUNET_free (rev);
372 return GNUNET_SYSERR;
373 }
374 rev->expiration = expiration;
375 GNUNET_memcpy (&rev[1],
376 known_by,
377 strlen (known_by));
378 return GNUNET_OK;
379 }
380 default: 314 default:
381 return GNUNET_SYSERR; 315 return GNUNET_SYSERR;
382 } 316 }
@@ -397,7 +331,6 @@ static struct {
397 { "VPN", GNUNET_GNSRECORD_TYPE_VPN }, 331 { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
398 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS }, 332 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
399 { "BOX", GNUNET_GNSRECORD_TYPE_BOX }, 333 { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
400 { "REVERSE", GNUNET_GNSRECORD_TYPE_REVERSE },
401 { NULL, UINT32_MAX } 334 { NULL, UINT32_MAX }
402}; 335};
403 336
diff --git a/src/identity-attribute/Makefile.am b/src/identity-attribute/Makefile.am
new file mode 100644
index 000000000..2c73a443e
--- /dev/null
+++ b/src/identity-attribute/Makefile.am
@@ -0,0 +1,44 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8libexecdir= $(pkglibdir)/libexec/
9
10if MINGW
11 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
12endif
13
14if USE_COVERAGE
15 AM_CFLAGS = --coverage -O0
16 XLIBS = -lgcov
17endif
18
19lib_LTLIBRARIES = \
20 libgnunetidentityattribute.la
21
22libgnunetidentityattribute_la_SOURCES = \
23 identity_attribute.c
24libgnunetidentityattribute_la_LIBADD = \
25 $(top_builddir)/src/util/libgnunetutil.la \
26 $(GN_LIBINTL)
27libgnunetidentityattribute_la_LDFLAGS = \
28 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
29 -version-info 0:0:0
30
31
32plugin_LTLIBRARIES = \
33 libgnunet_plugin_identity_attribute_gnuid.la
34
35
36libgnunet_plugin_identity_attribute_gnuid_la_SOURCES = \
37 plugin_identity_attribute_gnuid.c
38libgnunet_plugin_identity_attribute_gnuid_la_LIBADD = \
39 $(top_builddir)/src/util/libgnunetutil.la \
40 $(LTLIBINTL)
41libgnunet_plugin_identity_attribute_gnuid_la_LDFLAGS = \
42 $(GN_PLUGIN_LDFLAGS)
43
44
diff --git a/src/identity-attribute/identity_attribute.c b/src/identity-attribute/identity_attribute.c
new file mode 100644
index 000000000..cf50d058e
--- /dev/null
+++ b/src/identity-attribute/identity_attribute.c
@@ -0,0 +1,421 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 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 identity-attribute/identity_attribute.c
23 * @brief helper library to manage identity attributes
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "identity_attribute.h"
29#include "gnunet_identity_attribute_plugin.h"
30
31/**
32 * Handle for a plugin
33 */
34struct Plugin
35{
36 /**
37 * Name of the plugin
38 */
39 char *library_name;
40
41 /**
42 * Plugin API
43 */
44 struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
45};
46
47/**
48 * Plugins
49 */
50static struct Plugin **attr_plugins;
51
52/**
53 * Number of plugins
54 */
55static unsigned int num_plugins;
56
57/**
58 * Init canary
59 */
60static int initialized;
61
62/**
63 * Add a plugin
64 */
65static void
66add_plugin (void* cls,
67 const char *library_name,
68 void *lib_ret)
69{
70 struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = lib_ret;
71 struct Plugin *plugin;
72
73 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
74 "Loading attribute plugin `%s'\n",
75 library_name);
76 plugin = GNUNET_new (struct Plugin);
77 plugin->api = api;
78 plugin->library_name = GNUNET_strdup (library_name);
79 GNUNET_array_append (attr_plugins, num_plugins, plugin);
80}
81
82/**
83 * Load plugins
84 */
85static void
86init()
87{
88 if (GNUNET_YES == initialized)
89 return;
90 initialized = GNUNET_YES;
91 GNUNET_PLUGIN_load_all ("libgnunet_plugin_identity_attribute_", NULL,
92 &add_plugin, NULL);
93}
94
95/**
96 * Convert a type name to the corresponding number
97 *
98 * @param typename name to convert
99 * @return corresponding number, UINT32_MAX on error
100 */
101uint32_t
102GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename)
103{
104 unsigned int i;
105 struct Plugin *plugin;
106 uint32_t ret;
107
108 init ();
109 for (i = 0; i < num_plugins; i++)
110 {
111 plugin = attr_plugins[i];
112 if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
113 typename)))
114 return ret;
115 }
116 return UINT32_MAX;
117}
118
119/**
120 * Convert a type number to the corresponding type string
121 *
122 * @param type number of a type
123 * @return corresponding typestring, NULL on error
124 */
125const char*
126GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type)
127{
128 unsigned int i;
129 struct Plugin *plugin;
130 const char *ret;
131
132 init ();
133 for (i = 0; i < num_plugins; i++)
134 {
135 plugin = attr_plugins[i];
136 if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
137 type)))
138 return ret;
139 }
140 return NULL;
141}
142
143/**
144 * Convert human-readable version of a 'claim' of an attribute to the binary
145 * representation
146 *
147 * @param type type of the claim
148 * @param s human-readable string
149 * @param data set to value in binary encoding (will be allocated)
150 * @param data_size set to number of bytes in @a data
151 * @return #GNUNET_OK on success
152 */
153int
154GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
155 const char *s,
156 void **data,
157 size_t *data_size)
158{
159 unsigned int i;
160 struct Plugin *plugin;
161
162 init ();
163 for (i = 0; i < num_plugins; i++)
164 {
165 plugin = attr_plugins[i];
166 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
167 type,
168 s,
169 data,
170 data_size))
171 return GNUNET_OK;
172 }
173 return GNUNET_SYSERR;
174}
175
176/**
177 * Convert the 'claim' of an attribute to a string
178 *
179 * @param type the type of attribute
180 * @param data claim in binary encoding
181 * @param data_size number of bytes in @a data
182 * @return NULL on error, otherwise human-readable representation of the claim
183 */
184char *
185GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
186 const void* data,
187 size_t data_size)
188{
189 unsigned int i;
190 struct Plugin *plugin;
191 char *ret;
192
193 init();
194 for (i = 0; i < num_plugins; i++)
195 {
196 plugin = attr_plugins[i];
197 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
198 type,
199 data,
200 data_size)))
201 return ret;
202 }
203 return NULL;
204}
205
206/**
207 * Create a new attribute.
208 *
209 * @param attr_name the attribute name
210 * @param type the attribute type
211 * @param data the attribute value
212 * @param data_size the attribute value size
213 * @return the new attribute
214 */
215struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
216GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
217 uint32_t type,
218 const void* data,
219 size_t data_size)
220{
221 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
222 char *write_ptr;
223
224 attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) +
225 strlen (attr_name) + 1 +
226 data_size);
227 attr->type = type;
228 attr->data_size = data_size;
229 attr->version = 0;
230 write_ptr = (char*)&attr[1];
231 GNUNET_memcpy (write_ptr,
232 attr_name,
233 strlen (attr_name) + 1);
234 attr->name = write_ptr;
235 write_ptr += strlen (attr->name) + 1;
236 GNUNET_memcpy (write_ptr,
237 data,
238 data_size);
239 attr->data = write_ptr;
240 return attr;
241}
242
243size_t
244GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
245{
246 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
247 size_t len = 0;
248 for (le = attrs->list_head; NULL != le; le = le->next)
249 len += GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
250 return len;
251}
252
253size_t
254GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
255 char *result)
256{
257 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
258 size_t len;
259 size_t total_len;
260 char* write_ptr;
261
262 write_ptr = result;
263 total_len = 0;
264 for (le = attrs->list_head; NULL != le; le = le->next)
265 {
266 len = GNUNET_IDENTITY_ATTRIBUTE_serialize (le->claim,
267 write_ptr);
268 total_len += len;
269 write_ptr += len;
270 }
271 return total_len;
272}
273
274struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
275GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
276 size_t data_size)
277{
278 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
279 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
280 size_t attr_len;
281 const char* read_ptr;
282
283 if (data_size < sizeof (struct Attribute))
284 return NULL;
285
286 attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
287 read_ptr = data;
288 while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
289 {
290
291 le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
292 le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (read_ptr,
293 data_size - (read_ptr - data));
294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
295 "Deserialized attribute %s\n", le->claim->name);
296 GNUNET_CONTAINER_DLL_insert (attrs->list_head,
297 attrs->list_tail,
298 le);
299 attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
300 read_ptr += attr_len;
301 }
302 return attrs;
303}
304
305struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
306GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
307{
308 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
309 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *result_le;
310 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *result;
311 size_t len;
312
313 result = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
314 for (le = attrs->list_head; NULL != le; le = le->next)
315 {
316 result_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
317 len = sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) + le->claim->data_size;
318 result_le->claim = GNUNET_malloc (len);
319 GNUNET_memcpy (result_le->claim,
320 le->claim,
321 len);
322 result_le->claim->name = (const char*)&result_le->claim[1];
323 GNUNET_CONTAINER_DLL_insert (result->list_head,
324 result->list_tail,
325 result_le);
326 }
327 return result;
328}
329
330
331void
332GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
333{
334 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
335 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *tmp_le;
336
337 for (le = attrs->list_head; NULL != le;)
338 {
339 GNUNET_free (le->claim);
340 tmp_le = le;
341 le = le->next;
342 GNUNET_free (tmp_le);
343 }
344 GNUNET_free (attrs);
345
346}
347
348size_t
349GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
350{
351 return sizeof (struct Attribute)
352 + strlen (attr->name)
353 + attr->data_size;
354}
355
356size_t
357GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
358 char *result)
359{
360 size_t data_len_ser;
361 size_t name_len;
362 struct Attribute *attr_ser;
363 char* write_ptr;
364
365 attr_ser = (struct Attribute*)result;
366 attr_ser->attribute_type = htons (attr->type);
367 attr_ser->attribute_version = htonl (attr->version);
368 name_len = strlen (attr->name);
369 attr_ser->name_len = htons (name_len);
370 write_ptr = (char*)&attr_ser[1];
371 GNUNET_memcpy (write_ptr, attr->name, name_len);
372 write_ptr += name_len;
373 //TODO plugin-ize
374 //data_len_ser = plugin->serialize_attribute_value (attr,
375 // &attr_ser[1]);
376 data_len_ser = attr->data_size;
377 GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
378 attr_ser->data_size = htons (data_len_ser);
379
380 return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
381}
382
383struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
384GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
385 size_t data_size)
386{
387 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
388 struct Attribute *attr_ser;
389 size_t data_len;
390 size_t name_len;
391 char* write_ptr;
392
393 if (data_size < sizeof (struct Attribute))
394 return NULL;
395
396 attr_ser = (struct Attribute*)data;
397 data_len = ntohs (attr_ser->data_size);
398 name_len = ntohs (attr_ser->name_len);
399 attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim)
400 + data_len + name_len + 1);
401 attr->type = ntohs (attr_ser->attribute_type);
402 attr->version = ntohl (attr_ser->attribute_version);
403 attr->data_size = ntohs (attr_ser->data_size);
404
405 write_ptr = (char*)&attr[1];
406 GNUNET_memcpy (write_ptr,
407 &attr_ser[1],
408 name_len);
409 write_ptr[name_len] = '\0';
410 attr->name = write_ptr;
411
412 write_ptr += name_len + 1;
413 GNUNET_memcpy (write_ptr,
414 (char*)&attr_ser[1] + name_len,
415 attr->data_size);
416 attr->data = write_ptr;
417 return attr;
418
419}
420
421/* end of identity_attribute.c */
diff --git a/src/identity-attribute/identity_attribute.h b/src/identity-attribute/identity_attribute.h
new file mode 100644
index 000000000..8dfc17521
--- /dev/null
+++ b/src/identity-attribute/identity_attribute.h
@@ -0,0 +1,56 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 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 identity-attribute/identity_attribute.h
23 * @brief GNUnet Identity attributes
24 *
25 */
26#ifndef IDENTITY_ATTRIBUTE_H
27#define IDENTITY_ATTRIBUTE_H
28
29#include "gnunet_identity_provider_service.h"
30
31struct Attribute
32{
33 /**
34 * Attribute type
35 */
36 uint32_t attribute_type;
37
38 /**
39 * Attribute version
40 */
41 uint32_t attribute_version;
42
43 /**
44 * Name length
45 */
46 uint32_t name_len;
47
48 /**
49 * Data size
50 */
51 uint32_t data_size;
52
53 //followed by data_size Attribute value data
54};
55
56#endif
diff --git a/src/identity-attribute/plugin_identity_attribute_gnuid.c b/src/identity-attribute/plugin_identity_attribute_gnuid.c
new file mode 100644
index 000000000..006b45ea2
--- /dev/null
+++ b/src/identity-attribute/plugin_identity_attribute_gnuid.c
@@ -0,0 +1,184 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 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 * @file identity-attribute/plugin_identity_attribute_gnuid.c
23 * @brief identity attribute plugin to provide the API for fundamental
24 * attribute types.
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_attribute_plugin.h"
31#include <inttypes.h>
32
33
34/**
35 * Convert the 'value' of an attribute to a string.
36 *
37 * @param cls closure, unused
38 * @param type type of the attribute
39 * @param data value in binary encoding
40 * @param data_size number of bytes in @a data
41 * @return NULL on error, otherwise human-readable representation of the value
42 */
43static char *
44gnuid_value_to_string (void *cls,
45 uint32_t type,
46 const void *data,
47 size_t data_size)
48{
49
50 switch (type)
51 {
52 case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
53 return GNUNET_strndup (data, data_size);
54 default:
55 return NULL;
56 }
57}
58
59
60/**
61 * Convert human-readable version of a 'value' of an attribute to the binary
62 * representation.
63 *
64 * @param cls closure, unused
65 * @param type type of the attribute
66 * @param s human-readable string
67 * @param data set to value in binary encoding (will be allocated)
68 * @param data_size set to number of bytes in @a data
69 * @return #GNUNET_OK on success
70 */
71static int
72gnuid_string_to_value (void *cls,
73 uint32_t type,
74 const char *s,
75 void **data,
76 size_t *data_size)
77{
78 if (NULL == s)
79 return GNUNET_SYSERR;
80 switch (type)
81 {
82
83 case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
84 *data = GNUNET_strdup (s);
85 *data_size = strlen (s);
86 return GNUNET_OK;
87 default:
88 return GNUNET_SYSERR;
89 }
90}
91
92
93/**
94 * Mapping of attribute type numbers to human-readable
95 * attribute type names.
96 */
97static struct {
98 const char *name;
99 uint32_t number;
100} gnuid_name_map[] = {
101 { "STRING", GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING },
102 { NULL, UINT32_MAX }
103};
104
105
106/**
107 * Convert a type name to the corresponding number.
108 *
109 * @param cls closure, unused
110 * @param gnuid_typename name to convert
111 * @return corresponding number, UINT32_MAX on error
112 */
113static uint32_t
114gnuid_typename_to_number (void *cls,
115 const char *gnuid_typename)
116{
117 unsigned int i;
118
119 i=0;
120 while ( (NULL != gnuid_name_map[i].name) &&
121 (0 != strcasecmp (gnuid_typename,
122 gnuid_name_map[i].name)) )
123 i++;
124 return gnuid_name_map[i].number;
125}
126
127
128/**
129 * Convert a type number (i.e. 1) to the corresponding type string
130 *
131 * @param cls closure, unused
132 * @param type number of a type to convert
133 * @return corresponding typestring, NULL on error
134 */
135static const char *
136gnuid_number_to_typename (void *cls,
137 uint32_t type)
138{
139 unsigned int i;
140
141 i=0;
142 while ( (NULL != gnuid_name_map[i].name) &&
143 (type != gnuid_name_map[i].number) )
144 i++;
145 return gnuid_name_map[i].name;
146}
147
148
149/**
150 * Entry point for the plugin.
151 *
152 * @param cls NULL
153 * @return the exported block API
154 */
155void *
156libgnunet_plugin_identity_attribute_gnuid_init (void *cls)
157{
158 struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
159
160 api = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions);
161 api->value_to_string = &gnuid_value_to_string;
162 api->string_to_value = &gnuid_string_to_value;
163 api->typename_to_number = &gnuid_typename_to_number;
164 api->number_to_typename = &gnuid_number_to_typename;
165 return api;
166}
167
168
169/**
170 * Exit point from the plugin.
171 *
172 * @param cls the return value from #libgnunet_plugin_block_test_init()
173 * @return NULL
174 */
175void *
176libgnunet_plugin_identity_attribute_gnuid_done (void *cls)
177{
178 struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = cls;
179
180 GNUNET_free (api);
181 return NULL;
182}
183
184/* end of plugin_identity_attribute_type_gnuid.c */
diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am
index 0d8752c4c..adf6af3b3 100644
--- a/src/identity-provider/Makefile.am
+++ b/src/identity-provider/Makefile.am
@@ -12,6 +12,15 @@ if USE_COVERAGE
12 XLIB = -lgcov 12 XLIB = -lgcov
13endif 13endif
14 14
15if HAVE_SQLITE
16SQLITE_PLUGIN = libgnunet_plugin_identity_provider_sqlite.la
17endif
18
19EXTRA_DIST = \
20 test_idp_defaults.conf \
21 test_idp.conf \
22 $(check_SCRIPTS)
23
15pkgcfgdir= $(pkgdatadir)/config.d/ 24pkgcfgdir= $(pkgdatadir)/config.d/
16 25
17libexecdir= $(pkglibdir)/libexec/ 26libexecdir= $(pkglibdir)/libexec/
@@ -22,29 +31,51 @@ pkgcfg_DATA = \
22lib_LTLIBRARIES = \ 31lib_LTLIBRARIES = \
23 libgnunetidentityprovider.la 32 libgnunetidentityprovider.la
24plugin_LTLIBRARIES = \ 33plugin_LTLIBRARIES = \
25 libgnunet_plugin_rest_identity_provider.la 34 libgnunet_plugin_rest_identity_provider.la \
35 libgnunet_plugin_gnsrecord_identity_provider.la \
36 $(SQLITE_PLUGIN)
26 37
27bin_PROGRAMS = \ 38bin_PROGRAMS = \
28 gnunet-identity-token 39 gnunet-idp
29 40
30libexec_PROGRAMS = \ 41libexec_PROGRAMS = \
31 gnunet-service-identity-provider 42 gnunet-service-identity-provider
32 43
33EXTRA_DIST = \ 44libgnunet_plugin_gnsrecord_identity_provider_la_SOURCES = \
34 $(pkgcfg_DATA) 45 plugin_gnsrecord_identity_provider.c
46libgnunet_plugin_gnsrecord_identity_provider_la_LIBADD = \
47 $(top_builddir)/src/util/libgnunetutil.la \
48 $(LTLIBINTL)
49libgnunet_plugin_gnsrecord_identity_provider_la_LDFLAGS = \
50 $(GN_PLUGIN_LDFLAGS)
51
52libgnunet_plugin_identity_provider_sqlite_la_SOURCES = \
53 plugin_identity_provider_sqlite.c
54libgnunet_plugin_identity_provider_sqlite_la_LIBADD = \
55 libgnunetidentityprovider.la \
56 $(top_builddir)/src/sq/libgnunetsq.la \
57 $(top_builddir)/src/statistics/libgnunetstatistics.la \
58 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
59 $(LTLIBINTL)
60libgnunet_plugin_identity_provider_sqlite_la_LDFLAGS = \
61 $(GN_PLUGIN_LDFLAGS)
62
63
35 64
36gnunet_service_identity_provider_SOURCES = \ 65gnunet_service_identity_provider_SOURCES = \
37 gnunet-service-identity-provider.c \ 66 gnunet-service-identity-provider.c
38 identity_token.c identity_token.h
39gnunet_service_identity_provider_LDADD = \ 67gnunet_service_identity_provider_LDADD = \
40 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 68 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
41 $(top_builddir)/src/util/libgnunetutil.la \ 69 $(top_builddir)/src/util/libgnunetutil.la \
42 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 70 $(top_builddir)/src/namestore/libgnunetnamestore.la \
43 $(top_builddir)/src/identity/libgnunetidentity.la \ 71 $(top_builddir)/src/identity/libgnunetidentity.la \
44 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 72 $(top_builddir)/src/statistics/libgnunetstatistics.la \
73 $(top_builddir)/src/abe/libgnunetabe.la \
74 $(top_builddir)/src/credential/libgnunetcredential.la \
75 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
76 libgnunetidentityprovider.la \
45 $(top_builddir)/src/gns/libgnunetgns.la \ 77 $(top_builddir)/src/gns/libgnunetgns.la \
46 $(GN_LIBINTL) \ 78 $(GN_LIBINTL)
47 -ljansson
48 79
49libgnunetidentityprovider_la_SOURCES = \ 80libgnunetidentityprovider_la_SOURCES = \
50 identity_provider_api.c \ 81 identity_provider_api.c \
@@ -57,22 +88,37 @@ libgnunetidentityprovider_la_LDFLAGS = \
57 -version-info 0:0:0 88 -version-info 0:0:0
58 89
59libgnunet_plugin_rest_identity_provider_la_SOURCES = \ 90libgnunet_plugin_rest_identity_provider_la_SOURCES = \
60 plugin_rest_identity_provider.c 91 plugin_rest_identity_provider.c \
92 jwt.c
61libgnunet_plugin_rest_identity_provider_la_LIBADD = \ 93libgnunet_plugin_rest_identity_provider_la_LIBADD = \
62 $(top_builddir)/src/identity/libgnunetidentity.la \ 94 $(top_builddir)/src/identity/libgnunetidentity.la \
63 libgnunetidentityprovider.la \ 95 libgnunetidentityprovider.la \
64 $(top_builddir)/src/rest/libgnunetrest.la \ 96 $(top_builddir)/src/rest/libgnunetrest.la \
65 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ 97 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
98 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
66 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 99 $(top_builddir)/src/namestore/libgnunetnamestore.la \
67 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ 100 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
68 $(LTLIBINTL) -ljansson -lmicrohttpd 101 $(LTLIBINTL) -ljansson -lmicrohttpd
69libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \ 102libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \
70 $(GN_PLUGIN_LDFLAGS) 103 $(GN_PLUGIN_LDFLAGS)
71 104
72 105gnunet_idp_SOURCES = \
73gnunet_identity_token_SOURCES = \ 106 gnunet-idp.c
74 gnunet-identity-token.c 107gnunet_idp_LDADD = \
75gnunet_identity_token_LDADD = \
76 $(top_builddir)/src/util/libgnunetutil.la \ 108 $(top_builddir)/src/util/libgnunetutil.la \
77 -ljansson -lmicrohttpd \ 109 $(top_builddir)/src/namestore/libgnunetnamestore.la \
110 libgnunetidentityprovider.la \
111 $(top_builddir)/src/identity/libgnunetidentity.la \
112 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
78 $(GN_LIBINTL) 113 $(GN_LIBINTL)
114
115check_SCRIPTS = \
116 test_idp_attribute.sh \
117 test_idp_issue.sh \
118 test_idp_consume.sh \
119 test_idp_revoke.sh
120
121if ENABLE_TEST_RUN
122 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
123 TESTS = $(check_SCRIPTS)
124endif
diff --git a/src/identity-provider/gnunet-identity-token.c b/src/identity-provider/gnunet-identity-token.c
deleted file mode 100644
index 30b63bfc4..000000000
--- a/src/identity-provider/gnunet-identity-token.c
+++ /dev/null
@@ -1,179 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 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 src/identity-provider/gnunet-service-identity-provider.c
23 * @brief Identity Token Service
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include <jansson.h>
30#include "gnunet_signatures.h"
31
32/**
33 * The token
34 */
35static char* token;
36
37/**
38 * Weather to print the token
39 */
40static int print_token;
41
42static void
43run (void *cls,
44 char *const *args,
45 const char *cfgfile,
46 const struct GNUNET_CONFIGURATION_Handle *c)
47{
48 char *payload;
49 char *header;
50 //Get token parts
51 const char *header_b64;
52 const char *payload_b64;
53 const char *signature_b32;
54 const char *keystring;
55 char *data;
56 json_t *payload_json;
57 json_t *keystring_json;
58 json_error_t error;
59 struct GNUNET_CRYPTO_EcdsaPublicKey key;
60 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
61 struct GNUNET_CRYPTO_EcdsaSignature sig;
62
63 if (NULL == token)
64 {
65 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
66 _("Option `-t' is required\n"));
67 return;
68 }
69 header_b64 = strtok (token, ".");
70 payload_b64 = strtok (NULL, ".");
71 signature_b32 = strtok (NULL, ".");
72 if ( (NULL == header_b64) ||
73 (NULL == payload_b64) ||
74 (NULL == signature_b32) )
75 {
76 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
77 _("Token `%s' is malformed\n"),
78 token);
79 GNUNET_free (token);
80 token = NULL;
81 return;
82 }
83
84 //Decode payload
85 GNUNET_STRINGS_base64_decode (payload_b64,
86 strlen (payload_b64),
87 &payload);
88 //Decode header
89 GNUNET_STRINGS_base64_decode (header_b64,
90 strlen (header_b64),
91 &header);
92
93
94 GNUNET_asprintf(&data,
95 "%s,%s",
96 header_b64,
97 payload_b64);
98 char *val = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
99 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose*)val;
100 purpose->size = htonl(sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
101 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
102 GNUNET_memcpy (&purpose[1], data, strlen(data));
103 GNUNET_free (data);
104 GNUNET_free (token);
105 token = NULL;
106
107 if (print_token)
108 printf ("Token:\nHeader:\t\t%s\nPayload:\t%s\n",
109 header,
110 payload);
111 GNUNET_free (header);
112
113 payload_json = json_loads (payload, 0, &error);
114 GNUNET_free (payload);
115
116 if ((NULL == payload_json) || (! json_is_object (payload_json)) )
117 {
118 GNUNET_free (val);
119 return;
120 }
121 keystring_json = json_object_get (payload_json, "iss");
122 if (! json_is_string (keystring_json))
123 {
124 GNUNET_free (val);
125 return;
126 }
127 keystring = json_string_value (keystring_json);
128 if (GNUNET_OK !=
129 GNUNET_CRYPTO_ecdsa_public_key_from_string (keystring,
130 strlen (keystring),
131 &key))
132 {
133 GNUNET_free (val);
134 return;
135 }
136 GNUNET_STRINGS_string_to_data (signature_b32,
137 strlen (signature_b32),
138 &sig,
139 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
140
141 if (print_token)
142 printf ("Signature:\t%s\n",
143 keystring);
144
145 if (GNUNET_OK !=
146 GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN,
147 purpose,
148 &sig,
149 &key))
150 printf("Signature not OK!\n");
151 else
152 printf("Signature OK!\n");
153 GNUNET_free (val);
154 return;
155}
156
157
158int
159main(int argc, char *const argv[])
160{
161 struct GNUNET_GETOPT_CommandLineOption options[] = {
162
163 GNUNET_GETOPT_option_string ('t',
164 "token",
165 NULL,
166 gettext_noop ("GNUid token"),
167 &token),
168
169 GNUNET_GETOPT_option_flag ('p',
170 "print",
171 gettext_noop ("Print token contents"),
172 &print_token),
173
174 GNUNET_GETOPT_OPTION_END
175 };
176 return GNUNET_PROGRAM_run (argc, argv, "ct",
177 "ct", options,
178 &run, NULL);
179}
diff --git a/src/identity-provider/gnunet-idp.c b/src/identity-provider/gnunet-idp.c
new file mode 100644
index 000000000..62f07842b
--- /dev/null
+++ b/src/identity-provider/gnunet-idp.c
@@ -0,0 +1,439 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 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 src/identity-provider/gnunet-idp.c
23 * @brief Identity Provider utility
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_identity_provider_service.h"
31#include "gnunet_identity_service.h"
32#include "gnunet_signatures.h"
33
34/**
35 * return value
36 */
37static int ret;
38
39/**
40 * List attribute flag
41 */
42static int list;
43
44/**
45 * Relying party
46 */
47static char* rp;
48
49/**
50 * The attribute
51 */
52static char* attr_name;
53
54/**
55 * Attribute value
56 */
57static char* attr_value;
58
59/**
60 * Attributes to issue
61 */
62static char* issue_attrs;
63
64/**
65 * Ticket to consume
66 */
67static char* consume_ticket;
68
69/**
70 * Attribute type
71 */
72static char* type_str;
73
74/**
75 * Ticket to revoke
76 */
77static char* revoke_ticket;
78
79/**
80 * Ego name
81 */
82static char* ego_name;
83
84/**
85 * Identity handle
86 */
87static struct GNUNET_IDENTITY_Handle *identity_handle;
88
89/**
90 * IdP handle
91 */
92static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle;
93
94/**
95 * IdP operation
96 */
97static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
98
99/**
100 * Attribute iterator
101 */
102static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator;
103
104/**
105 * Master ABE key
106 */
107static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
108
109/**
110 * ego private key
111 */
112static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
113
114/**
115 * rp public key
116 */
117static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
118
119/**
120 * Ticket to consume
121 */
122static struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
123
124/**
125 * Attribute list
126 */
127static struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list;
128
129static void
130do_cleanup(void *cls)
131{
132 if (NULL != attr_iterator)
133 GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator);
134 if (NULL != idp_handle)
135 GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle);
136 if (NULL != identity_handle)
137 GNUNET_IDENTITY_disconnect (identity_handle);
138 if (NULL != abe_key)
139 GNUNET_free (abe_key);
140 if (NULL != attr_list)
141 GNUNET_free (attr_list);
142}
143
144static void
145ticket_issue_cb (void* cls,
146 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
147{
148 char* ticket_str;
149 if (NULL != ticket) {
150 ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
151 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
152 printf("%s\n",
153 ticket_str);
154 GNUNET_free (ticket_str);
155 }
156 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
157}
158
159static void
160store_attr_cont (void *cls,
161 int32_t success,
162 const char*emsg)
163{
164 if (GNUNET_SYSERR == success) {
165 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
166 "%s\n", emsg);
167 }
168 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
169}
170
171static void
172process_attrs (void *cls,
173 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
174 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
175{
176 char *value_str;
177 if (NULL == identity)
178 {
179 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
180 return;
181 }
182 if (NULL == attr)
183 {
184 ret = 1;
185 return;
186 }
187 value_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
188 attr->data,
189 attr->data_size);
190 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
191 "%s: %s\n", attr->name, value_str);
192}
193
194
195static void
196iter_error (void *cls)
197{
198 attr_iterator = NULL;
199 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200 "Failed to iterate over attributes\n");
201 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
202}
203
204static void
205process_rvk (void *cls, int success, const char* msg)
206{
207 if (GNUNET_OK != success)
208 {
209 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
210 "Revocation failed.\n");
211 ret = 1;
212 }
213 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
214}
215
216static void
217iter_finished (void *cls)
218{
219 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
220 char *data;
221 size_t data_size;
222 int type;
223
224 attr_iterator = NULL;
225 if (list)
226 {
227 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
228 return;
229 }
230
231 if (issue_attrs)
232 {
233 idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (idp_handle,
234 pkey,
235 &rp_key,
236 attr_list,
237 &ticket_issue_cb,
238 NULL);
239 return;
240 }
241 if (consume_ticket)
242 {
243 idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (idp_handle,
244 pkey,
245 &ticket,
246 &process_attrs,
247 NULL);
248 return;
249 }
250 if (revoke_ticket)
251 {
252 idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle,
253 pkey,
254 &ticket,
255 &process_rvk,
256 NULL);
257 return;
258 }
259 if (NULL == type_str)
260 type = GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING;
261 else
262 type = GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (type_str);
263
264 GNUNET_assert (GNUNET_SYSERR != GNUNET_IDENTITY_ATTRIBUTE_string_to_value (type,
265 attr_value,
266 (void**)&data,
267 &data_size));
268 claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
269 type,
270 data,
271 data_size);
272 idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
273 pkey,
274 claim,
275 &store_attr_cont,
276 NULL);
277
278
279}
280
281static void
282iter_cb (void *cls,
283 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
284 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
285{
286 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
287 char *attrs_tmp;
288 char *attr_str;
289
290 if (issue_attrs)
291 {
292 attrs_tmp = GNUNET_strdup (issue_attrs);
293 attr_str = strtok (attrs_tmp, ",");
294 while (NULL != attr_str) {
295 if (0 != strcmp (attr_str, attr->name)) {
296 attr_str = strtok (NULL, ",");
297 continue;
298 }
299 le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
300 le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name,
301 attr->type,
302 attr->data,
303 attr->data_size);
304 GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
305 attr_list->list_tail,
306 le);
307 break;
308 }
309 GNUNET_free (attrs_tmp);
310 } else if (list) {
311 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
312 "%s: %s\n", attr->name, (char*)attr->data);
313 }
314 GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
315}
316
317static void
318ego_cb (void *cls,
319 struct GNUNET_IDENTITY_Ego *ego,
320 void **ctx,
321 const char *name)
322{
323 if (NULL == name)
324 return;
325 if (0 != strcmp (name, ego_name))
326 return;
327 pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
328
329 if (NULL != rp)
330 GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
331 strlen (rp),
332 &rp_key);
333 if (NULL != consume_ticket)
334 GNUNET_STRINGS_string_to_data (consume_ticket,
335 strlen (consume_ticket),
336 &ticket,
337 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
338 if (NULL != revoke_ticket)
339 GNUNET_STRINGS_string_to_data (revoke_ticket,
340 strlen (revoke_ticket),
341 &ticket,
342 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
343
344
345 attr_list = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
346
347 attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
348 pkey,
349 &iter_error,
350 NULL,
351 &iter_cb,
352 NULL,
353 &iter_finished,
354 NULL);
355
356
357}
358
359static void
360run (void *cls,
361 char *const *args,
362 const char *cfgfile,
363 const struct GNUNET_CONFIGURATION_Handle *c)
364{
365 ret = 0;
366 if (NULL == ego_name)
367 {
368 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
369 _("Ego is required\n"));
370 return;
371 }
372
373 idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
374 //Get Ego
375 identity_handle = GNUNET_IDENTITY_connect (c,
376 &ego_cb,
377 NULL);
378
379
380}
381
382
383int
384main(int argc, char *const argv[])
385{
386 struct GNUNET_GETOPT_CommandLineOption options[] = {
387
388 GNUNET_GETOPT_option_string ('a',
389 "add",
390 NULL,
391 gettext_noop ("Add attribute"),
392 &attr_name),
393
394 GNUNET_GETOPT_option_string ('V',
395 "value",
396 NULL,
397 gettext_noop ("Attribute value"),
398 &attr_value),
399 GNUNET_GETOPT_option_string ('e',
400 "ego",
401 NULL,
402 gettext_noop ("Ego"),
403 &ego_name),
404 GNUNET_GETOPT_option_string ('r',
405 "rp",
406 NULL,
407 gettext_noop ("Audience (relying party)"),
408 &rp),
409 GNUNET_GETOPT_option_flag ('D',
410 "dump",
411 gettext_noop ("List attributes for Ego"),
412 &list),
413 GNUNET_GETOPT_option_string ('i',
414 "issue",
415 NULL,
416 gettext_noop ("Issue a ticket"),
417 &issue_attrs),
418 GNUNET_GETOPT_option_string ('C',
419 "consume",
420 NULL,
421 gettext_noop ("Consume a ticket"),
422 &consume_ticket),
423 GNUNET_GETOPT_option_string ('R',
424 "revoke",
425 NULL,
426 gettext_noop ("Revoke a ticket"),
427 &revoke_ticket),
428 GNUNET_GETOPT_option_string ('t',
429 "type",
430 NULL,
431 gettext_noop ("Type of attribute"),
432 &type_str),
433 GNUNET_GETOPT_OPTION_END
434 };
435 GNUNET_PROGRAM_run (argc, argv, "ct",
436 "ct", options,
437 &run, NULL);
438 return ret;
439}
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c
index 53fd02c9f..4e1de36cd 100644
--- a/src/identity-provider/gnunet-service-identity-provider.c
+++ b/src/identity-provider/gnunet-service-identity-provider.c
@@ -30,12 +30,14 @@
30#include "gnunet_identity_service.h" 30#include "gnunet_identity_service.h"
31#include "gnunet_gnsrecord_lib.h" 31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_namestore_service.h" 32#include "gnunet_namestore_service.h"
33#include "gnunet_abe_lib.h"
34#include "gnunet_credential_service.h"
33#include "gnunet_statistics_service.h" 35#include "gnunet_statistics_service.h"
34#include "gnunet_gns_service.h" 36#include "gnunet_gns_service.h"
37#include "gnunet_identity_provider_plugin.h"
38#include "gnunet_identity_attribute_lib.h"
35#include "gnunet_signatures.h" 39#include "gnunet_signatures.h"
36#include "identity_provider.h" 40#include "identity_provider.h"
37#include "identity_token.h"
38#include <inttypes.h>
39 41
40/** 42/**
41 * First pass state 43 * First pass state
@@ -58,24 +60,19 @@
58#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS 60#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
59 61
60/** 62/**
61 * Service state (to detect initial update pass) 63 * Identity handle
62 */
63static int state;
64
65/**
66 * Head of ego entry DLL
67 */ 64 */
68static struct EgoEntry *ego_head; 65static struct GNUNET_IDENTITY_Handle *identity_handle;
69 66
70/** 67/**
71 * Tail of ego entry DLL 68 * Database handle
72 */ 69 */
73static struct EgoEntry *ego_tail; 70static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
74 71
75/** 72/**
76 * Identity handle 73 * Name of DB plugin
77 */ 74 */
78static struct GNUNET_IDENTITY_Handle *identity_handle; 75static char *db_lib_name;
79 76
80/** 77/**
81 * Token expiration interval 78 * Token expiration interval
@@ -93,6 +90,16 @@ static struct GNUNET_NAMESTORE_Handle *ns_handle;
93static struct GNUNET_GNS_Handle *gns_handle; 90static struct GNUNET_GNS_Handle *gns_handle;
94 91
95/** 92/**
93 * Credential handle
94 */
95static struct GNUNET_CREDENTIAL_Handle *credential_handle;
96
97/**
98 * Stats handle
99 */
100static struct GNUNET_STATISTICS_Handle *stats_handle;
101
102/**
96 * Namestore qe 103 * Namestore qe
97 */ 104 */
98static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 105static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
@@ -112,11 +119,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task;
112 */ 119 */
113static struct GNUNET_SCHEDULER_Task *update_task; 120static struct GNUNET_SCHEDULER_Task *update_task;
114 121
115/**
116 * Timeout for next update pass
117 */
118static struct GNUNET_TIME_Relative min_rel_exp;
119
120 122
121/** 123/**
122 * Currently processed token 124 * Currently processed token
@@ -134,43 +136,260 @@ static char* label;
134static char* scopes; 136static char* scopes;
135 137
136/** 138/**
137 * Expiration for processed token 139 * Handle to the statistics service.
138 */ 140 */
139static uint64_t rd_exp; 141static struct GNUNET_STATISTICS_Handle *stats;
140 142
141/** 143/**
142 * ECDHE Privkey for processed token metadata 144 * Our configuration.
143 */ 145 */
144static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey; 146static const struct GNUNET_CONFIGURATION_Handle *cfg;
145 147
146/** 148/**
147 * Handle to the statistics service. 149 * An idp client
148 */ 150 */
149static struct GNUNET_STATISTICS_Handle *stats; 151struct IdpClient;
150 152
151/** 153/**
152 * Our configuration. 154 * A ticket iteration operation.
153 */ 155 */
154static const struct GNUNET_CONFIGURATION_Handle *cfg; 156struct TicketIteration
157{
158 /**
159 * DLL
160 */
161 struct TicketIteration *next;
162
163 /**
164 * DLL
165 */
166 struct TicketIteration *prev;
167
168 /**
169 * Client which intiated this zone iteration
170 */
171 struct IdpClient *client;
155 172
173 /**
174 * Key of the identity we are iterating over.
175 */
176 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
156 177
157struct ExchangeHandle 178 /**
179 * Identity is audience
180 */
181 uint32_t is_audience;
182
183 /**
184 * The operation id fot the iteration in the response for the client
185 */
186 uint32_t r_id;
187
188 /**
189 * Offset of the iteration used to address next result of the
190 * iteration in the store
191 *
192 * Initialy set to 0 in handle_iteration_start
193 * Incremented with by every call to handle_iteration_next
194 */
195 uint32_t offset;
196
197};
198
199
200
201/**
202 * Callback after an ABE bootstrap
203 *
204 * @param cls closure
205 * @param abe_key the ABE key that exists or was created
206 */
207typedef void
208(*AbeBootstrapResult) (void *cls,
209 struct GNUNET_ABE_AbeMasterKey *abe_key);
210
211
212struct AbeBootstrapHandle
158{ 213{
214 /**
215 * Function to call when finished
216 */
217 AbeBootstrapResult proc;
159 218
160 /** 219 /**
161 * Client connection 220 * Callback closure
221 */
222 char *proc_cls;
223
224 /**
225 * Key of the zone we are iterating over.
226 */
227 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
228
229 /**
230 * Namestore Queue Entry
231 */
232 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
233
234 /**
235 * The issuer egos ABE master key
236 */
237 struct GNUNET_ABE_AbeMasterKey *abe_key;
238};
239
240/**
241 * An attribute iteration operation.
242 */
243struct AttributeIterator
244{
245 /**
246 * Next element in the DLL
247 */
248 struct AttributeIterator *next;
249
250 /**
251 * Previous element in the DLL
252 */
253 struct AttributeIterator *prev;
254
255 /**
256 * IDP client which intiated this zone iteration
257 */
258 struct IdpClient *client;
259
260 /**
261 * Key of the zone we are iterating over.
262 */
263 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
264
265 /**
266 * The issuer egos ABE master key
267 */
268 struct GNUNET_ABE_AbeMasterKey *abe_key;
269
270 /**
271 * Namestore iterator
272 */
273 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
274
275 /**
276 * The operation id fot the zone iteration in the response for the client
277 */
278 uint32_t request_id;
279
280};
281
282
283
284/**
285 * An idp client
286 */
287struct IdpClient
288{
289
290 /**
291 * The client
162 */ 292 */
163 struct GNUNET_SERVICE_Client *client; 293 struct GNUNET_SERVICE_Client *client;
164 294
165 /** 295 /**
166 * Ticket 296 * Message queue for transmission to @e client
297 */
298 struct GNUNET_MQ_Handle *mq;
299
300 /**
301 * Head of the DLL of
302 * Attribute iteration operations in
303 * progress initiated by this client
304 */
305 struct AttributeIterator *op_head;
306
307 /**
308 * Tail of the DLL of
309 * Attribute iteration operations
310 * in progress initiated by this client
311 */
312 struct AttributeIterator *op_tail;
313
314 /**
315 * Head of DLL of ticket iteration ops
316 */
317 struct TicketIteration *ticket_iter_head;
318
319 /**
320 * Tail of DLL of ticket iteration ops
321 */
322 struct TicketIteration *ticket_iter_tail;
323
324
325 /**
326 * Head of DLL of ticket revocation ops
327 */
328 struct TicketRevocationHandle *revocation_list_head;
329
330 /**
331 * Tail of DLL of ticket revocation ops
332 */
333 struct TicketRevocationHandle *revocation_list_tail;
334};
335
336
337
338struct AttributeStoreHandle
339{
340
341 /**
342 * Client connection
343 */
344 struct IdpClient *client;
345
346 /**
347 * Identity
348 */
349 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
350
351 /**
352 * Identity pubkey
353 */
354 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
355
356 /**
357 * The issuer egos ABE master key
358 */
359 struct GNUNET_ABE_AbeMasterKey *abe_key;
360
361 /**
362 * QueueEntry
363 */
364 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
365
366 /**
367 * The attribute to store
368 */
369 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
370
371 /**
372 * request id
373 */
374 uint32_t r_id;
375};
376
377
378/* Prototype */
379struct ParallelLookup;
380
381struct ConsumeTicketHandle
382{
383
384 /**
385 * Client connection
167 */ 386 */
168 struct TokenTicket *ticket; 387 struct IdpClient *client;
169 388
170 /** 389 /**
171 * Token returned 390 * Ticket
172 */ 391 */
173 struct IdentityToken *token; 392 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
174 393
175 /** 394 /**
176 * LookupRequest 395 * LookupRequest
@@ -180,86 +399,173 @@ struct ExchangeHandle
180 /** 399 /**
181 * Audience Key 400 * Audience Key
182 */ 401 */
183 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey; 402 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
184 403
185 /** 404 /**
186 * Label to return 405 * Audience Key
187 */ 406 */
188 char *label; 407 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
189 408
190 /** 409 /**
410 * Lookup DLL
411 */
412 struct ParallelLookup *parallel_lookups_head;
413
414 /**
415 * Lookup DLL
416 */
417 struct ParallelLookup *parallel_lookups_tail;
418
419 /**
420 * Kill task
421 */
422 struct GNUNET_SCHEDULER_Task *kill_task;
423
424 /**
425 * The ABE key
426 */
427 struct GNUNET_ABE_AbeKey *key;
428
429 /**
430 * Attributes
431 */
432 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
433
434 /**
435 * Lookup time
436 */
437 struct GNUNET_TIME_Absolute lookup_start_time;
438
439 /**
191 * request id 440 * request id
192 */ 441 */
193 uint32_t r_id; 442 uint32_t r_id;
194}; 443};
195 444
196struct IssueHandle 445/**
446 * Handle for a parallel GNS lookup job
447 */
448struct ParallelLookup
197{ 449{
450 /* DLL */
451 struct ParallelLookup *next;
452
453 /* DLL */
454 struct ParallelLookup *prev;
455
456 /* The GNS request */
457 struct GNUNET_GNS_LookupRequest *lookup_request;
458
459 /* The handle the return to */
460 struct ConsumeTicketHandle *handle;
461
462 /**
463 * Lookup time
464 */
465 struct GNUNET_TIME_Absolute lookup_start_time;
466
467 /* The label to look up */
468 char *label;
469};
470
471/**
472 * Ticket revocation request handle
473 */
474struct TicketRevocationHandle
475{
476 /**
477 * DLL
478 */
479 struct TicketRevocationHandle *next;
480
481 /**
482 * DLL
483 */
484 struct TicketRevocationHandle *prev;
198 485
199 /** 486 /**
200 * Client connection 487 * Client connection
201 */ 488 */
202 struct GNUNET_SERVICE_Client *client; 489 struct IdpClient *client;
490
491 /**
492 * Attributes to reissue
493 */
494 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
495
496 /**
497 * Attributes to revoke
498 */
499 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs;
203 500
204 /** 501 /**
205 * Issuer Key 502 * Issuer Key
206 */ 503 */
207 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key; 504 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
208 505
209 /** 506 /**
210 * Issue pubkey 507 * Ticket to issue
211 */ 508 */
212 struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey; 509 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
213 510
214 /** 511 /**
215 * Audience Key 512 * QueueEntry
216 */ 513 */
217 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 514 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
218 515
219 /** 516 /**
220 * Expiration 517 * Namestore iterator
221 */ 518 */
222 struct GNUNET_TIME_Absolute expiration; 519 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
223 520
224 /** 521 /**
225 * Scopes 522 * The ABE master key
226 */ 523 */
227 char *scopes; 524 struct GNUNET_ABE_AbeMasterKey *abe_key;
228 525
229 /** 526 /**
230 * nonce 527 * Offset
231 */ 528 */
232 uint64_t nonce; 529 uint32_t offset;
233 530
234 /** 531 /**
235 * NS iterator 532 * request id
236 */ 533 */
237 struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 534 uint32_t r_id;
535};
536
537
538
539/**
540 * Ticket issue request handle
541 */
542struct TicketIssueHandle
543{
238 544
239 /** 545 /**
240 * Attribute map 546 * Client connection
241 */ 547 */
242 struct GNUNET_CONTAINER_MultiHashMap *attr_map; 548 struct IdpClient *client;
243 549
244 /** 550 /**
245 * Token 551 * Attributes to issue
246 */ 552 */
247 struct IdentityToken *token; 553 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
248 554
249 /** 555 /**
250 * Ticket 556 * Issuer Key
251 */ 557 */
252 struct TokenTicket *ticket; 558 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
253 559
254 /** 560 /**
255 * QueueEntry 561 * Ticket to issue
256 */ 562 */
257 struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 563 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
258 564
259 /** 565 /**
260 * The label the token is stored under 566 * QueueEntry
261 */ 567 */
262 char *label; 568 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
263 569
264 /** 570 /**
265 * request id 571 * request id
@@ -267,6 +573,7 @@ struct IssueHandle
267 uint32_t r_id; 573 uint32_t r_id;
268}; 574};
269 575
576
270/** 577/**
271 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format 578 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
272 * 579 *
@@ -293,1303 +600,1774 @@ struct EgoEntry
293 */ 600 */
294 struct GNUNET_CONTAINER_MultiHashMap *attr_map; 601 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
295 602
296 /**
297 * Attributes are old and should be updated if GNUNET_YES
298 */
299 int attributes_dirty;
300}; 603};
301 604
302/** 605/**
303 * Continuation for token store call 606 * Cleanup task
607 */
608static void
609cleanup()
610{
611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
612 "Cleaning up\n");
613 if (NULL != stats)
614 {
615 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
616 stats = NULL;
617 }
618 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
619 TKT_database));
620 GNUNET_free (db_lib_name);
621 db_lib_name = NULL;
622 if (NULL != timeout_task)
623 GNUNET_SCHEDULER_cancel (timeout_task);
624 if (NULL != update_task)
625 GNUNET_SCHEDULER_cancel (update_task);
626 if (NULL != identity_handle)
627 GNUNET_IDENTITY_disconnect (identity_handle);
628 if (NULL != gns_handle)
629 GNUNET_GNS_disconnect (gns_handle);
630 if (NULL != credential_handle)
631 GNUNET_CREDENTIAL_disconnect (credential_handle);
632 if (NULL != ns_it)
633 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
634 if (NULL != ns_qe)
635 GNUNET_NAMESTORE_cancel (ns_qe);
636 if (NULL != ns_handle)
637 GNUNET_NAMESTORE_disconnect (ns_handle);
638 if (NULL != stats_handle)
639 GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO);
640 GNUNET_free_non_null (token);
641 GNUNET_free_non_null (label);
642
643}
644
645/**
646 * Shutdown task
304 * 647 *
305 * @param cls NULL 648 * @param cls NULL
306 * @param success error code
307 * @param emsg error message
308 */ 649 */
309static void 650static void
310store_token_cont (void *cls, 651do_shutdown (void *cls)
311 int32_t success, 652{
312 const char *emsg) 653 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
654 "Shutting down...\n");
655 cleanup();
656}
657
658/**
659 * Finished storing newly bootstrapped ABE key
660 */
661static void
662bootstrap_store_cont (void *cls,
663 int32_t success,
664 const char *emsg)
313{ 665{
314 ns_qe = NULL; 666 struct AbeBootstrapHandle *abh = cls;
315 if (GNUNET_SYSERR == success) 667 if (GNUNET_SYSERR == success)
316 { 668 {
317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 669 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
318 "Failed to update token: %s\n", 670 "Failed to bootstrap ABE master %s\n",
319 emsg); 671 emsg);
672 abh->proc (abh->proc_cls, NULL);
673 GNUNET_free (abh->abe_key);
674 GNUNET_free (abh);
320 return; 675 return;
321 } 676 }
322 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 677 abh->proc (abh->proc_cls, abh->abe_key);
678 GNUNET_free (abh);
323} 679}
324 680
325
326/** 681/**
327 * This function updates the old token with new attributes, 682 * Generates and stores a new ABE key
328 * removes deleted attributes and expiration times.
329 *
330 * @param cls the ego entry
331 */ 683 */
332static void 684static void
333handle_token_update (void *cls) 685bootstrap_store_task (void *cls)
334{ 686{
335 char *token_metadata; 687 struct AbeBootstrapHandle *abh = cls;
336 char *write_ptr; 688 struct GNUNET_GNSRECORD_Data rd[1];
337 char *enc_token_str; 689 char *key;
338 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 690
339 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 691 rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
340 struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey; 692 (void**)&key);
341 struct EgoEntry *ego_entry = cls; 693 rd[0].data = key;
342 struct GNUNET_GNSRECORD_Data token_record[2]; 694 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
343 struct GNUNET_HashCode key_hash; 695 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
344 struct GNUNET_TIME_Relative token_rel_exp; 696 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
345 struct GNUNET_TIME_Relative token_ttl; 697 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
346 struct GNUNET_TIME_Absolute token_exp; 698 &abh->identity,
347 struct GNUNET_TIME_Absolute token_nbf; 699 "+",
348 struct GNUNET_TIME_Absolute new_exp; 700 1,
349 struct GNUNET_TIME_Absolute new_iat; 701 rd,
350 struct GNUNET_TIME_Absolute new_nbf; 702 &bootstrap_store_cont,
351 struct IdentityToken *new_token; 703 abh);
352 struct TokenAttr *cur_value; 704 GNUNET_free (key);
353 struct TokenAttr *attr; 705}
354 size_t token_metadata_len;
355
356 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
357 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
358 &pub_key);
359
360 //Note: We need the token expiration time here. Not the record expiration
361 //time.
362 //There are two types of tokens: Token that expire on GNS level with
363 //an absolute expiration time. Those are basically tokens that will
364 //be automatically revoked on (record)expiration.
365 //Tokens stored with relative expiration times will expire on the token level (token expiration)
366 //but this service will reissue new tokens that can be retrieved from GNS
367 //automatically.
368
369 for (attr = token->attr_head; NULL != attr; attr = attr->next)
370 {
371 if (0 == strcmp (attr->name, "exp"))
372 {
373 GNUNET_assert (1 == sscanf (attr->val_head->value,
374 "%"SCNu64,
375 &token_exp.abs_value_us));
376 } else if (0 == strcmp (attr->name, "nbf")) {
377 GNUNET_assert (1 == sscanf (attr->val_head->value,
378 "%"SCNu64,
379 &token_nbf.abs_value_us));
380 }
381 }
382 token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp);
383
384 token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp);
385 if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us)
386 {
387 //This token is not yet expired! Save and skip
388 if (min_rel_exp.rel_value_us > token_ttl.rel_value_us)
389 {
390 min_rel_exp = token_ttl;
391 }
392 GNUNET_free (token);
393 token = NULL;
394 GNUNET_free (label);
395 label = NULL;
396 GNUNET_free (scopes);
397 scopes = NULL;
398 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
399 return;
400 }
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
402 "Token is expired. Create a new one\n");
403 new_token = token_create (&pub_key,
404 &token->aud_key);
405 new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
406 new_nbf = GNUNET_TIME_absolute_get ();
407 new_iat = new_nbf;
408 for (attr = token->attr_head; NULL != attr; attr = attr->next)
409 {
410 if (0 == strcmp (attr->name, "exp"))
411 {
412 token_add_attr_int (new_token, attr->name, new_exp.abs_value_us);
413 }
414 else if (0 == strcmp (attr->name, "nbf"))
415 {
416 token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us);
417 }
418 else if (0 == strcmp (attr->name, "iat"))
419 {
420 token_add_attr_int (new_token, attr->name, new_iat.abs_value_us);
421 }
422 else if ((0 == strcmp (attr->name, "iss"))
423 || (0 == strcmp (attr->name, "aud")))
424 {
425 //Omit
426 }
427 else if (0 == strcmp (attr->name, "sub"))
428 {
429 token_add_attr (new_token,
430 attr->name,
431 attr->val_head->value);
432 }
433 else
434 {
435 GNUNET_CRYPTO_hash (attr->name,
436 strlen (attr->name),
437 &key_hash);
438 //Check if attr still exists. omit of not
439 if (GNUNET_NO !=
440 GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
441 &key_hash))
442 {
443 cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
444 &key_hash);
445 GNUNET_assert (NULL != cur_value);
446 GNUNET_CONTAINER_DLL_insert (new_token->attr_head,
447 new_token->attr_tail,
448 cur_value);
449 }
450 }
451 }
452 706
453 // reassemble and set 707/**
454 GNUNET_assert (token_serialize (new_token, 708 * Error checking for ABE master
455 priv_key, 709 */
456 &new_ecdhe_privkey, 710static void
457 &enc_token_str)); 711bootstrap_abe_error (void *cls)
458 712{
459 token_record[0].data = enc_token_str; 713 struct AbeBootstrapHandle *abh = cls;
460 token_record[0].data_size = strlen (enc_token_str) + 1; 714 GNUNET_free (abh);
461 token_record[0].expiration_time = rd_exp; //Old expiration time 715 abh->proc (abh->proc_cls, NULL);
462 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; 716 GNUNET_free (abh);
463 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
464
465 //Meta
466 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
467 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
468 + strlen (scopes) + 1; //With 0-Terminator
469 token_metadata = GNUNET_malloc (token_metadata_len);
470 write_ptr = token_metadata;
471 GNUNET_memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
472 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
473 GNUNET_memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
474 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
475 GNUNET_memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
476
477 token_record[1].data = token_metadata;
478 token_record[1].data_size = token_metadata_len;
479 token_record[1].expiration_time = rd_exp;
480 token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
481 token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
482
483 ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
484 priv_key,
485 label,
486 2,
487 token_record,
488 &store_token_cont,
489 ego_entry);
490 token_destroy (new_token);
491 token_destroy (token);
492 GNUNET_free (new_ecdhe_privkey);
493 GNUNET_free (enc_token_str);
494 token = NULL;
495 GNUNET_free (label);
496 label = NULL;
497 GNUNET_free (scopes);
498 scopes = NULL;
499} 717}
500 718
501 719
720/**
721 * Handle ABE lookup in namestore
722 */
502static void 723static void
503update_identities(void *cls); 724bootstrap_abe_result (void *cls,
725 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
726 const char *label,
727 unsigned int rd_count,
728 const struct GNUNET_GNSRECORD_Data *rd)
729{
730 struct AbeBootstrapHandle *abh = cls;
731 struct GNUNET_ABE_AbeMasterKey *abe_key;
732
733 for (uint32_t i=0;i<rd_count;i++) {
734 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
735 continue;
736 abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
737 rd[i].data_size);
738 abh->proc (abh->proc_cls, abe_key);
739 GNUNET_free (abh);
740 return;
741 }
504 742
743 //No ABE master found, bootstrapping...
744 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
745 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
746}
505 747
506/** 748/**
507 * 749 * Bootstrap ABE master if it does not yet exists.
508 * Cleanup attr_map 750 * Will call the AbeBootstrapResult processor when done.
509 * 751 * will always recreate the ABE key of GNUNET_YES == recreate
510 * @param cls NULL
511 * @param key the key
512 * @param value the json_t attribute value
513 * @return #GNUNET_YES
514 */ 752 */
515static int 753static void
516clear_ego_attrs (void *cls, 754bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
517 const struct GNUNET_HashCode *key, 755 AbeBootstrapResult proc,
518 void *value) 756 void* cls,
519{ 757 int recreate)
520 struct TokenAttr *attr = value; 758{
521 struct TokenAttrValue *val; 759 struct AbeBootstrapHandle *abh;
522 struct TokenAttrValue *tmp_val; 760
523 for (val = attr->val_head; NULL != val;) 761 abh = GNUNET_new (struct AbeBootstrapHandle);
762 abh->proc = proc;
763 abh->proc_cls = cls;
764 abh->identity = *identity;
765 if (GNUNET_YES == recreate)
524 { 766 {
525 tmp_val = val->next; 767 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
526 GNUNET_CONTAINER_DLL_remove (attr->val_head, 768 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
527 attr->val_tail, 769 } else {
528 val); 770 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
529 GNUNET_free (val->value); 771 identity,
530 GNUNET_free (val); 772 "+",
531 val = tmp_val; 773 &bootstrap_abe_error,
774 abh,
775 &bootstrap_abe_result,
776 abh);
532 } 777 }
533 GNUNET_free (attr->name);
534 GNUNET_free (attr);
535
536 return GNUNET_YES;
537} 778}
538 779
539 780
540static void
541token_collect_error_cb (void *cls)
542{
543 struct EgoEntry *ego_entry = cls;
544 781
545 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 782static int
546 ">>> Updating Ego failed!\n"); 783create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
547 //Clear attribute map for ego 784 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
548 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, 785 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
549 &clear_ego_attrs, 786{
550 ego_entry); 787 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
551 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); 788
552 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 789 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
553 ego_entry->next); 790 &new_key_hash_str);
791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
792 static const char ctx_key[] = "gnuid-aes-ctx-key";
793 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
794 new_key_hash, sizeof (struct GNUNET_HashCode),
795 ctx_key, strlen (ctx_key),
796 NULL, 0);
797 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
798 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
799 new_key_hash, sizeof (struct GNUNET_HashCode),
800 ctx_iv, strlen (ctx_iv),
801 NULL, 0);
802 return GNUNET_OK;
803}
554 804
805static void
806cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
807{
808 if (NULL != handle->attrs)
809 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
810 if (NULL != handle->ns_qe)
811 GNUNET_NAMESTORE_cancel (handle->ns_qe);
812 GNUNET_free (handle);
555} 813}
556 814
557 815
558static void 816static void
559token_collect_finished_cb (void *cls) 817send_ticket_result (struct IdpClient *client,
818 uint32_t r_id,
819 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
820 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
560{ 821{
561 struct EgoEntry *ego_entry = cls; 822 struct TicketResultMessage *irm;
823 struct GNUNET_MQ_Envelope *env;
824 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
562 825
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 826 /* store ticket in DB */
564 ">>> Updating Ego finished\n"); 827 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
565 //Clear attribute map for ego 828 ticket,
566 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, 829 attrs))
567 &clear_ego_attrs, 830 {
568 ego_entry); 831 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
569 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); 832 "Unable to store ticket after issue\n");
570 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 833 GNUNET_break (0);
571 ego_entry->next); 834 }
572}
573 835
836 env = GNUNET_MQ_msg_extra (irm,
837 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
838 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
839 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
840 *ticket_buf = *ticket;
841 irm->id = htonl (r_id);
842 GNUNET_MQ_send (client->mq,
843 env);
844}
574 845
575/**
576 *
577 * Update all ID_TOKEN records for an identity and store them
578 *
579 * @param cls the identity entry
580 * @param zone the identity
581 * @param lbl the name of the record
582 * @param rd_count number of records
583 * @param rd record data
584 */
585static void 846static void
586token_collect (void *cls, 847store_ticket_issue_cont (void *cls,
587 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 848 int32_t success,
588 const char *lbl, 849 const char *emsg)
589 unsigned int rd_count, 850{
590 const struct GNUNET_GNSRECORD_Data *rd) 851 struct TicketIssueHandle *handle = cls;
591{ 852
592 struct EgoEntry *ego_entry = cls; 853 handle->ns_qe = NULL;
593 const struct GNUNET_GNSRECORD_Data *token_record; 854 if (GNUNET_SYSERR == success)
594 const struct GNUNET_GNSRECORD_Data *token_metadata_record;
595 struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
596 struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key;
597
598 //There should be only a single record for a token under a label
599 if (2 != rd_count)
600 { 855 {
601 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 856 cleanup_ticket_issue_handle (handle);
857 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
858 "Unknown Error\n");
859 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
602 return; 860 return;
603 } 861 }
862 send_ticket_result (handle->client,
863 handle->r_id,
864 &handle->ticket,
865 handle->attrs);
866 cleanup_ticket_issue_handle (handle);
867}
604 868
605 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 869
606 { 870
607 token_metadata_record = &rd[0]; 871int
608 token_record = &rd[1]; 872serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
873 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
874 const struct GNUNET_ABE_AbeKey *rp_key,
875 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
876 char **result)
877{
878 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
879 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
880 char *enc_keyinfo;
881 char *serialized_key;
882 char *buf;
883 char *write_ptr;
884 char attrs_str_len;
885 ssize_t size;
886
887 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
888 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
889 struct GNUNET_HashCode new_key_hash;
890 ssize_t enc_size;
891
892 size = GNUNET_ABE_cpabe_serialize_key (rp_key,
893 (void**)&serialized_key);
894 attrs_str_len = 0;
895 for (le = attrs->list_head; NULL != le; le = le->next) {
896 attrs_str_len += strlen (le->claim->name) + 1;
609 } 897 }
610 else 898 buf = GNUNET_malloc (attrs_str_len + size);
611 { 899 write_ptr = buf;
612 token_record = &rd[0]; 900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
613 token_metadata_record = &rd[1]; 901 "Writing attributes\n");
902 for (le = attrs->list_head; NULL != le; le = le->next) {
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904 "%s\n", le->claim->name);
905
906
907 GNUNET_memcpy (write_ptr,
908 le->claim->name,
909 strlen (le->claim->name));
910 write_ptr[strlen (le->claim->name)] = ',';
911 write_ptr += strlen (le->claim->name) + 1;
614 } 912 }
615 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 913 write_ptr--;
616 { 914 write_ptr[0] = '\0'; //replace last , with a 0-terminator
617 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 915 write_ptr++;
618 return; 916 GNUNET_memcpy (write_ptr,
917 serialized_key,
918 size);
919 GNUNET_free (serialized_key);
920 // ECDH keypair E = eG
921 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
922 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
923 &ecdh_pubkey);
924 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
925 // Derived key K = H(eB)
926 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
927 &ticket->audience,
928 &new_key_hash));
929 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
930 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
931 size + attrs_str_len,
932 &skey, &iv,
933 enc_keyinfo);
934 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
935 enc_size);
936 GNUNET_memcpy (*result,
937 &ecdh_pubkey,
938 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
939 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
940 enc_keyinfo,
941 enc_size);
942 GNUNET_free (enc_keyinfo);
943 GNUNET_free (buf);
944 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
945}
946
947
948
949static void
950issue_ticket_after_abe_bootstrap (void *cls,
951 struct GNUNET_ABE_AbeMasterKey *abe_key)
952{
953 struct TicketIssueHandle *ih = cls;
954 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
955 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
956 struct GNUNET_GNSRECORD_Data code_record[1];
957 struct GNUNET_ABE_AbeKey *rp_key;
958 char *code_record_data;
959 char **attrs;
960 char *label;
961 char *policy;
962 int attrs_len;
963 uint32_t i;
964 size_t code_record_len;
965
966 //Create new ABE key for RP
967 attrs_len = 0;
968 for (le = ih->attrs->list_head; NULL != le; le = le->next)
969 attrs_len++;
970 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
971 i = 0;
972 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
973 GNUNET_asprintf (&policy, "%s_%lu",
974 le->claim->name,
975 le->claim->version);
976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
977 "Adding attribute to key: %s\n",
978 policy);
979 attrs[i] = policy;
980 i++;
619 } 981 }
620 if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN) 982 attrs[i] = NULL;
983 rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
984 attrs);
985
986 //TODO review this wireformat
987 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
988 ih->attrs,
989 rp_key,
990 &ecdhe_privkey,
991 &code_record_data);
992 code_record[0].data = code_record_data;
993 code_record[0].data_size = code_record_len;
994 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
995 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
996 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
997
998 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
999 sizeof (uint64_t));
1000 //Publish record
1001 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1002 &ih->identity,
1003 label,
1004 1,
1005 code_record,
1006 &store_ticket_issue_cont,
1007 ih);
1008 //for (; i > 0; i--)
1009 // GNUNET_free (attrs[i-1]);
1010 GNUNET_free (ecdhe_privkey);
1011 GNUNET_free (label);
1012 GNUNET_free (attrs);
1013 GNUNET_free (code_record_data);
1014 GNUNET_ABE_cpabe_delete_key (rp_key,
1015 GNUNET_YES);
1016 GNUNET_ABE_cpabe_delete_master_key (abe_key);
1017}
1018
1019
1020static int
1021check_issue_ticket_message(void *cls,
1022 const struct IssueTicketMessage *im)
1023{
1024 uint16_t size;
1025
1026 size = ntohs (im->header.size);
1027 if (size <= sizeof (struct IssueTicketMessage))
621 { 1028 {
622 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1029 GNUNET_break (0);
623 return; 1030 return GNUNET_SYSERR;
624 } 1031 }
1032 return GNUNET_OK;
1033}
625 1034
626 //Get metadata and decrypt token
627 priv_key = (struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data;
628 ecdhe_privkey = *priv_key;
629 aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&priv_key[1];
630 scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
631 1035
632 token_parse2 (token_record->data, 1036static void
633 &ecdhe_privkey, 1037handle_issue_ticket_message (void *cls,
634 aud_key, 1038 const struct IssueTicketMessage *im)
635 &token); 1039{
1040 struct TicketIssueHandle *ih;
1041 struct IdpClient *idp = cls;
1042 size_t attrs_len;
1043
1044 ih = GNUNET_new (struct TicketIssueHandle);
1045 attrs_len = ntohs (im->attr_len);
1046 ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
1047 ih->r_id = ntohl (im->id);
1048 ih->client = idp;
1049 ih->identity = im->identity;
1050 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1051 &ih->ticket.identity);
1052 ih->ticket.audience = im->rp;
1053 ih->ticket.rnd =
1054 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1055 UINT64_MAX);
1056 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1057 GNUNET_SERVICE_client_continue (idp->client);
636 1058
637 label = GNUNET_strdup (lbl); 1059}
638 rd_exp = token_record->expiration_time;
639 1060
640 GNUNET_SCHEDULER_add_now (&handle_token_update, 1061/**********************************************************
641 ego_entry); 1062 * Revocation
1063 **********************************************************/
1064
1065/**
1066 * Cleanup revoke handle
1067 *
1068 * @param rh the ticket revocation handle
1069 */
1070static void
1071cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
1072{
1073 if (NULL != rh->attrs)
1074 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->attrs);
1075 if (NULL != rh->rvk_attrs)
1076 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->rvk_attrs);
1077 if (NULL != rh->abe_key)
1078 GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
1079 if (NULL != rh->ns_qe)
1080 GNUNET_NAMESTORE_cancel (rh->ns_qe);
1081 if (NULL != rh->ns_it)
1082 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
1083 GNUNET_free (rh);
642} 1084}
643 1085
644 1086
1087/**
1088 * Send revocation result
1089 *
1090 * @param rh ticket revocation handle
1091 * @param success GNUNET_OK if successful result
1092 */
645static void 1093static void
646attribute_collect_error_cb (void *cls) 1094send_revocation_finished (struct TicketRevocationHandle *rh,
1095 uint32_t success)
647{ 1096{
648 struct EgoEntry *ego_entry = cls; 1097 struct GNUNET_MQ_Envelope *env;
1098 struct RevokeTicketResultMessage *trm;
649 1099
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1100 env = GNUNET_MQ_msg (trm,
651 ">>> Updating Attributes failed!\n"); 1101 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
652 ego_entry->attributes_dirty = GNUNET_NO; 1102 trm->id = htonl (rh->r_id);
653 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1103 trm->success = htonl (success);
654 ego_entry); 1104 GNUNET_MQ_send (rh->client->mq,
1105 env);
1106 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1107 rh->client->revocation_list_tail,
1108 rh);
655} 1109}
656 1110
657 1111
1112/**
1113 * Process ticket from database
1114 *
1115 * @param cls struct TicketIterationProcResult
1116 * @param ticket the ticket
1117 * @param attrs the attributes
1118 */
1119static void
1120ticket_reissue_proc (void *cls,
1121 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1122 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
1123
658static void 1124static void
659attribute_collect_finished_cb (void *cls) 1125revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1126
1127
1128static void reissue_next (void *cls)
660{ 1129{
661 struct EgoEntry *ego_entry = cls; 1130 struct TicketRevocationHandle *rh = cls;
1131 revocation_reissue_tickets (rh);
1132}
662 1133
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1134
664 ">>> Updating Attributes finished\n"); 1135static void
665 ego_entry->attributes_dirty = GNUNET_NO; 1136reissue_ticket_cont (void *cls,
666 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1137 int32_t success,
667 ego_entry); 1138 const char *emsg)
1139{
1140 struct TicketRevocationHandle *rh = cls;
1141
1142 rh->ns_qe = NULL;
1143 if (GNUNET_SYSERR == success)
1144 {
1145 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1146 "Unknown Error\n");
1147 send_revocation_finished (rh, GNUNET_SYSERR);
1148 cleanup_revoke_ticket_handle (rh);
1149 return;
1150 }
1151 rh->offset++;
1152 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
668} 1153}
669 1154
670 1155
671/** 1156/**
1157 * Process ticket from database
672 * 1158 *
673 * Collect all ID_ATTR records for an identity and store them 1159 * @param cls struct TicketIterationProcResult
674 * 1160 * @param ticket the ticket
675 * @param cls the identity entry 1161 * @param attrs the attributes
676 * @param zone the identity
677 * @param lbl the name of the record
678 * @param rd_count number of records
679 * @param rd record data
680 *
681 */ 1162 */
682static void 1163static void
683attribute_collect (void *cls, 1164ticket_reissue_proc (void *cls,
684 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1165 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
685 const char *lbl, 1166 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
686 unsigned int rd_count, 1167{
687 const struct GNUNET_GNSRECORD_Data *rd) 1168 struct TicketRevocationHandle *rh = cls;
688{ 1169 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
689 struct EgoEntry *ego_entry = cls; 1170 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover;
690 struct GNUNET_HashCode key; 1171 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
691 struct TokenAttr *attr; 1172 struct GNUNET_GNSRECORD_Data code_record[1];
692 struct TokenAttrValue *val; 1173 struct GNUNET_ABE_AbeKey *rp_key;
693 char *val_str; 1174 char *code_record_data;
694 int i; 1175 char **attr_arr;
695 1176 char *label;
696 if (0 == rd_count) 1177 char *policy;
1178 int attrs_len;
1179 uint32_t i;
1180 int reissue_ticket;
1181 size_t code_record_len;
1182
1183
1184 if (NULL == ticket)
697 { 1185 {
698 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "Iteration done\n");
699 return; 1188 return;
700 } 1189 }
701 GNUNET_CRYPTO_hash (lbl, 1190
702 strlen (lbl), 1191 if (0 == memcmp (&ticket->audience,
703 &key); 1192 &rh->ticket.audience,
704 if (1 == rd_count) 1193 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
705 { 1194 {
706 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 { 1196 "Do not reissue for this identity.!\n");
708 val_str = GNUNET_GNSRECORD_value_to_string (rd->record_type,
709 rd->data,
710 rd->data_size);
711 attr = GNUNET_malloc (sizeof (struct TokenAttr));
712 attr->name = GNUNET_strdup (lbl);
713 val = GNUNET_malloc (sizeof (struct TokenAttrValue));
714 val->value = val_str;
715 GNUNET_CONTAINER_DLL_insert (attr->val_head,
716 attr->val_tail,
717 val);
718 GNUNET_assert (GNUNET_OK ==
719 GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
720 &key,
721 attr,
722 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
723 }
724 1197
725 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1198 rh->offset++;
1199 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
726 return; 1200 return;
727 } 1201 }
728 1202
729 attr = GNUNET_malloc (sizeof (struct TokenAttr)); 1203 /*
730 attr->name = GNUNET_strdup (lbl); 1204 * Check if any attribute of this ticket intersects with a rollover attribute
731 for (i = 0; i < rd_count; i++) 1205 */
1206 reissue_ticket = GNUNET_NO;
1207 for (le = attrs->list_head; NULL != le; le = le->next)
732 { 1208 {
733 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1209 for (le_rollover = rh->rvk_attrs->list_head;
1210 NULL != le_rollover;
1211 le_rollover = le_rollover->next)
734 { 1212 {
735 val_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, 1213 if (0 == strcmp (le_rollover->claim->name,
736 rd[i].data, 1214 le->claim->name))
737 rd[i].data_size); 1215 {
738 val = GNUNET_malloc (sizeof (struct TokenAttrValue)); 1216 reissue_ticket = GNUNET_YES;
739 val->value = val_str; 1217 le->claim->version = le_rollover->claim->version;
740 GNUNET_CONTAINER_DLL_insert (attr->val_head, 1218 }
741 attr->val_tail,
742 val);
743 } 1219 }
744 } 1220 }
745 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
746 &key,
747 attr,
748 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
749 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
750}
751
752/**
753 *
754 * Update identity information for ego. If attribute map is
755 * dirty, first update the attributes.
756 *
757 * @param cls the ego to update
758 */
759static void
760update_identities(void *cls)
761{
762 struct EgoEntry *next_ego = cls;
763 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
764 1221
765 update_task = NULL; 1222 if (GNUNET_NO == reissue_ticket)
766 if (NULL == next_ego)
767 { 1223 {
768 if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
769 min_rel_exp = MIN_WAIT_TIME;
770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
771 ">>> Finished. Rescheduling in %"SCNu64"\n", 1225 "Skipping ticket.\n");
772 min_rel_exp.rel_value_us); 1226
773 ns_it = NULL; 1227 rh->offset++;
774 //finished -> reschedule 1228 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
775 update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, 1229
776 &update_identities, 1230
777 ego_head);
778 min_rel_exp.rel_value_us = 0;
779 return; 1231 return;
780 } 1232 }
781 priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
782 if (GNUNET_YES == next_ego->attributes_dirty)
783 {
784 //Starting over. We must update the Attributes for they might have changed.
785 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
786 priv_key,
787 &attribute_collect_error_cb,
788 next_ego,
789 &attribute_collect,
790 next_ego,
791 &attribute_collect_finished_cb,
792 next_ego);
793 1233
1234 //Create new ABE key for RP
1235 attrs_len = 0;
1236
1237 /* If this is the RP we want to revoke attributes of, the do so */
1238
1239 for (le = attrs->list_head; NULL != le; le = le->next)
1240 attrs_len++;
1241 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1242 i = 0;
1243 for (le = attrs->list_head; NULL != le; le = le->next) {
1244 GNUNET_asprintf (&policy, "%s_%lu",
1245 le->claim->name,
1246 le->claim->version);
1247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1248 "Recreating key with %s\n", policy);
1249 attr_arr[i] = policy;
1250 i++;
794 } 1251 }
795 else 1252 attr_arr[i] = NULL;
1253 rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
1254 attr_arr);
1255
1256 //TODO review this wireformat
1257 code_record_len = serialize_abe_keyinfo2 (ticket,
1258 attrs,
1259 rp_key,
1260 &ecdhe_privkey,
1261 &code_record_data);
1262 code_record[0].data = code_record_data;
1263 code_record[0].data_size = code_record_len;
1264 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1265 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1266 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1267
1268 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1269 sizeof (uint64_t));
1270 //Publish record
1271 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1272 &rh->identity,
1273 label,
1274 1,
1275 code_record,
1276 &reissue_ticket_cont,
1277 rh);
1278 //for (; i > 0; i--)
1279 // GNUNET_free (attr_arr[i-1]);
1280 GNUNET_free (ecdhe_privkey);
1281 GNUNET_free (label);
1282 GNUNET_free (attr_arr);
1283 GNUNET_free (code_record_data);
1284 GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
1285}
1286
1287
1288/* Prototype for below function */
1289static void
1290attr_reenc_cont (void *cls,
1291 int32_t success,
1292 const char *emsg);
1293
1294static void
1295revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1296{
1297 int ret;
1298 /* Done, issue new keys */
1299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1300 "Revocation Phase III: Reissuing Tickets\n");
1301 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1302 &rh->ticket.identity,
1303 GNUNET_NO,
1304 rh->offset,
1305 &ticket_reissue_proc,
1306 rh)))
796 { 1307 {
797 //Ego will be dirty next time 1308 GNUNET_break (0);
798 next_ego->attributes_dirty = GNUNET_YES; 1309 }
799 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, 1310 if (GNUNET_NO == ret)
800 priv_key, 1311 {
801 &token_collect_error_cb, 1312 send_revocation_finished (rh, GNUNET_OK);
802 next_ego, 1313 cleanup_revoke_ticket_handle (rh);
803 &token_collect, 1314 return;
804 next_ego,
805 &token_collect_finished_cb,
806 next_ego);
807 } 1315 }
808} 1316}
809 1317
810
811/** 1318/**
812 * Function called initially to start update task 1319 * Revoke next attribte by reencryption with
1320 * new ABE master
813 */ 1321 */
814static void 1322static void
815init_cont () 1323reenc_next_attribute (struct TicketRevocationHandle *rh)
816{ 1324{
817 GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n"); 1325 struct GNUNET_GNSRECORD_Data rd[1];
818 //Initially iterate all itenties and refresh all tokens 1326 char* buf;
819 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1327 char* enc_buf;
820 ego_head); 1328 size_t enc_size;
1329 char* rd_buf;
1330 size_t buf_size;
1331 char* policy;
1332 uint32_t attr_ver;
1333
1334 if (NULL == rh->attrs->list_head)
1335 {
1336 revocation_reissue_tickets (rh);
1337 return;
1338 }
1339 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1340 buf = GNUNET_malloc (buf_size);
1341 GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1342 buf);
1343 rh->attrs->list_head->claim->version++;
1344 GNUNET_asprintf (&policy, "%s_%lu",
1345 rh->attrs->list_head->claim->name,
1346 rh->attrs->list_head->claim->version);
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1348 "Encrypting with policy %s\n", policy);
1349 /**
1350 * Encrypt the attribute value and store in namestore
1351 */
1352 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1353 buf_size,
1354 policy, //Policy
1355 rh->abe_key,
1356 (void**)&enc_buf);
1357 GNUNET_free (buf);
1358 GNUNET_free (policy);
1359 rd[0].data_size = enc_size + sizeof (uint32_t);
1360 rd_buf = GNUNET_malloc (rd[0].data_size);
1361 attr_ver = htonl (rh->attrs->list_head->claim->version);
1362 GNUNET_memcpy (rd_buf,
1363 &attr_ver,
1364 sizeof (uint32_t));
1365 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1366 enc_buf,
1367 enc_size);
1368 rd[0].data = rd_buf;
1369 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1370 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1371 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1372 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1373 &rh->identity,
1374 rh->attrs->list_head->claim->name,
1375 1,
1376 rd,
1377 &attr_reenc_cont,
1378 rh);
1379 GNUNET_free (enc_buf);
1380 GNUNET_free (rd_buf);
821} 1381}
822 1382
823
824/** 1383/**
825 * Initial ego collection function. 1384 * Namestore callback after revoked attribute
826 * 1385 * is stored
827 * @param cls NULL
828 * @param ego ego
829 * @param ctx context
830 * @param identifier ego name
831 */ 1386 */
832static void 1387static void
833list_ego (void *cls, 1388attr_reenc_cont (void *cls,
834 struct GNUNET_IDENTITY_Ego *ego, 1389 int32_t success,
835 void **ctx, 1390 const char *emsg)
836 const char *identifier)
837{ 1391{
838 struct EgoEntry *new_entry; 1392 struct TicketRevocationHandle *rh = cls;
839 if ((NULL == ego) && (STATE_INIT == state)) 1393 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
1394
1395 if (GNUNET_SYSERR == success)
840 { 1396 {
841 state = STATE_POST_INIT; 1397 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
842 init_cont (); 1398 "Failed to reencrypt attribute %s\n",
1399 emsg);
1400 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
843 return; 1401 return;
844 } 1402 }
845 if (STATE_INIT == state) { 1403 if (NULL == rh->attrs->list_head)
846 new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); 1404 {
847 new_entry->ego = ego; 1405 revocation_reissue_tickets (rh);
848 new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5, 1406 return;
849 GNUNET_NO);
850 new_entry->attributes_dirty = GNUNET_YES;
851 GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
852 } 1407 }
1408 le = rh->attrs->list_head;
1409 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1410 rh->attrs->list_tail,
1411 le);
1412 GNUNET_assert (NULL != rh->rvk_attrs);
1413 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1414 rh->rvk_attrs->list_tail,
1415 le);
1416
1417
1418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1419 "Re-encrypting next attribute\n");
1420 reenc_next_attribute (rh);
853} 1421}
854 1422
855/** 1423
856 * Cleanup task
857 */
858static void 1424static void
859cleanup() 1425process_attributes_to_update (void *cls,
1426 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1427 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
860{ 1428{
861 struct EgoEntry *ego_entry; 1429 struct TicketRevocationHandle *rh = cls;
862 struct EgoEntry *ego_tmp;
863 1430
1431 rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs);
864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
865 "Cleaning up\n"); 1433 "Revocation Phase I: Collecting attributes\n");
866 if (NULL != stats) 1434 /* Reencrypt all attributes with new key */
1435 if (NULL == rh->attrs->list_head)
867 { 1436 {
868 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 1437 /* No attributes to reencrypt */
869 stats = NULL; 1438 send_revocation_finished (rh, GNUNET_OK);
1439 cleanup_revoke_ticket_handle (rh);
1440 return;
1441 } else {
1442 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1443 "Revocation Phase II: Re-encrypting attributes\n");
1444 reenc_next_attribute (rh);
870 } 1445 }
871 1446
872 if (NULL != timeout_task) 1447}
873 GNUNET_SCHEDULER_cancel (timeout_task);
874 if (NULL != update_task)
875 GNUNET_SCHEDULER_cancel (update_task);
876 if (NULL != identity_handle)
877 GNUNET_IDENTITY_disconnect (identity_handle);
878 if (NULL != gns_handle)
879 GNUNET_GNS_disconnect (gns_handle);
880 if (NULL != ns_it)
881 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
882 if (NULL != ns_qe)
883 GNUNET_NAMESTORE_cancel (ns_qe);
884 if (NULL != ns_handle)
885 GNUNET_NAMESTORE_disconnect (ns_handle);
886 if (NULL != token)
887 GNUNET_free (token);
888 if (NULL != label)
889 GNUNET_free (label);
890 1448
891 for (ego_entry = ego_head;
892 NULL != ego_entry;)
893 {
894 ego_tmp = ego_entry;
895 if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
896 {
897 GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
898 &clear_ego_attrs,
899 ego_tmp);
900 1449
901 } 1450
902 GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map); 1451static void
903 ego_entry = ego_entry->next; 1452get_ticket_after_abe_bootstrap (void *cls,
904 GNUNET_free (ego_tmp); 1453 struct GNUNET_ABE_AbeMasterKey *abe_key)
1454{
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1456 "Finished ABE bootstrap\n");
1457 struct TicketRevocationHandle *rh = cls;
1458 rh->abe_key = abe_key;
1459 TKT_database->get_ticket_attributes (TKT_database->cls,
1460 &rh->ticket,
1461 &process_attributes_to_update,
1462 rh);
1463}
1464
1465static int
1466check_revoke_ticket_message(void *cls,
1467 const struct RevokeTicketMessage *im)
1468{
1469 uint16_t size;
1470
1471 size = ntohs (im->header.size);
1472 if (size <= sizeof (struct RevokeTicketMessage))
1473 {
1474 GNUNET_break (0);
1475 return GNUNET_SYSERR;
905 } 1476 }
1477 return GNUNET_OK;
906} 1478}
907 1479
908/**
909 * Shutdown task
910 *
911 * @param cls NULL
912 * @param tc task context
913 */
914static void 1480static void
915do_shutdown (void *cls) 1481handle_revoke_ticket_message (void *cls,
1482 const struct RevokeTicketMessage *rm)
916{ 1483{
917 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1484 struct TicketRevocationHandle *rh;
918 "Shutting down...\n"); 1485 struct IdpClient *idp = cls;
919 cleanup(); 1486 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1487
1488 rh = GNUNET_new (struct TicketRevocationHandle);
1489 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1490 rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1491 rh->ticket = *ticket;
1492 rh->r_id = ntohl (rm->id);
1493 rh->client = idp;
1494 rh->identity = rm->identity;
1495 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1496 &rh->ticket.identity);
1497 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1498 idp->revocation_list_tail,
1499 rh);
1500 bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1501 GNUNET_SERVICE_client_continue (idp->client);
1502
920} 1503}
921 1504
922 1505
923static struct GNUNET_MQ_Envelope* 1506static void
924create_exchange_result_message (const char* token, 1507cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
925 const char* label,
926 uint64_t ticket_nonce,
927 uint64_t id)
928{ 1508{
929 struct GNUNET_MQ_Envelope *env; 1509 if (NULL != handle->key)
930 struct ExchangeResultMessage *erm; 1510 GNUNET_ABE_cpabe_delete_key (handle->key,
931 uint16_t token_len = strlen (token) + 1; 1511 GNUNET_YES);
932 1512 if (NULL != handle->attrs)
933 env = GNUNET_MQ_msg_extra (erm, 1513 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
934 token_len, 1514 GNUNET_free (handle);
935 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
936 erm->ticket_nonce = htonl (ticket_nonce);
937 erm->id = id;
938 GNUNET_memcpy (&erm[1], token, token_len);
939 return env;
940} 1515}
941 1516
942 1517
943static struct GNUNET_MQ_Envelope* 1518
944create_issue_result_message (const char* label, 1519static int
945 const char* ticket, 1520check_consume_ticket_message(void *cls,
946 const char* token, 1521 const struct ConsumeTicketMessage *cm)
947 uint64_t id)
948{ 1522{
949 struct GNUNET_MQ_Envelope *env; 1523 uint16_t size;
950 struct IssueResultMessage *irm;
951 char *tmp_str;
952 size_t len;
953 1524
954 GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token); 1525 size = ntohs (cm->header.size);
955 len = strlen (tmp_str) + 1; 1526 if (size <= sizeof (struct ConsumeTicketMessage))
956 env = GNUNET_MQ_msg_extra (irm, 1527 {
957 len, 1528 GNUNET_break (0);
958 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT); 1529 return GNUNET_SYSERR;
959 irm->id = id; 1530 }
960 GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1); 1531 return GNUNET_OK;
961 GNUNET_free (tmp_str);
962 return env;
963} 1532}
964 1533
965static void 1534static void
966cleanup_issue_handle (struct IssueHandle *handle) 1535process_parallel_lookup2 (void *cls, uint32_t rd_count,
967{ 1536 const struct GNUNET_GNSRECORD_Data *rd)
968 if (NULL != handle->attr_map) 1537{
969 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map); 1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
970 if (NULL != handle->scopes) 1539 "Parallel lookup finished (count=%u)\n", rd_count);
971 GNUNET_free (handle->scopes); 1540 struct ParallelLookup *parallel_lookup = cls;
972 if (NULL != handle->token) 1541 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
973 token_destroy (handle->token); 1542 struct ConsumeTicketResultMessage *crm;
974 if (NULL != handle->ticket) 1543 struct GNUNET_MQ_Envelope *env;
975 ticket_destroy (handle->ticket); 1544 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le;
976 if (NULL != handle->label) 1545 struct GNUNET_TIME_Absolute decrypt_duration;
977 GNUNET_free (handle->label); 1546 char *data;
978 GNUNET_free (handle); 1547 char *data_tmp;
1548 ssize_t attr_len;
1549 size_t attrs_len;
1550
1551 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1552 handle->parallel_lookups_tail,
1553 parallel_lookup);
1554 GNUNET_free (parallel_lookup->label);
1555
1556 GNUNET_STATISTICS_update (stats_handle,
1557 "attribute_lookup_time_total",
1558 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
1559 GNUNET_YES);
1560 GNUNET_STATISTICS_update (stats_handle,
1561 "attribute_lookups_count",
1562 1,
1563 GNUNET_YES);
1564
1565
1566 GNUNET_free (parallel_lookup);
1567 if (1 != rd_count)
1568 GNUNET_break(0);//TODO
1569 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1570 {
1571 decrypt_duration = GNUNET_TIME_absolute_get ();
1572 attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
1573 rd->data_size - sizeof (uint32_t),
1574 handle->key,
1575 (void**)&data);
1576 if (GNUNET_SYSERR != attr_len)
1577 {
1578 GNUNET_STATISTICS_update (stats_handle,
1579 "abe_decrypt_time_total",
1580 GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
1581 GNUNET_YES);
1582 GNUNET_STATISTICS_update (stats_handle,
1583 "abe_decrypt_count",
1584 1,
1585 GNUNET_YES);
1586
1587 attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
1588 attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data,
1589 attr_len);
1590 attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
1591 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1592 handle->attrs->list_tail,
1593 attr_le);
1594 GNUNET_free (data);
1595 }
1596 }
1597 if (NULL != handle->parallel_lookups_head)
1598 return; //Wait for more
1599 /* Else we are done */
1600
1601 /* Store ticket in DB */
1602 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1603 &handle->ticket,
1604 handle->attrs))
1605 {
1606 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1607 "Unable to store ticket after consume\n");
1608 GNUNET_break (0);
1609 }
1610
1611 GNUNET_SCHEDULER_cancel (handle->kill_task);
1612 attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs);
1613 env = GNUNET_MQ_msg_extra (crm,
1614 attrs_len,
1615 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1616 crm->id = htonl (handle->r_id);
1617 crm->attrs_len = htons (attrs_len);
1618 crm->identity = handle->ticket.identity;
1619 data_tmp = (char *) &crm[1];
1620 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs,
1621 data_tmp);
1622 GNUNET_MQ_send (handle->client->mq, env);
1623 cleanup_consume_ticket_handle (handle);
979} 1624}
980 1625
981static void 1626void
982store_token_issue_cont (void *cls, 1627abort_parallel_lookups2 (void *cls)
983 int32_t success,
984 const char *emsg)
985{ 1628{
986 struct IssueHandle *handle = cls; 1629 struct ConsumeTicketHandle *handle = cls;
1630 struct ParallelLookup *lu;
1631 struct ParallelLookup *tmp;
1632 struct AttributeResultMessage *arm;
987 struct GNUNET_MQ_Envelope *env; 1633 struct GNUNET_MQ_Envelope *env;
988 char *ticket_str;
989 char *token_str;
990 1634
991 handle->ns_qe = NULL; 1635 for (lu = handle->parallel_lookups_head;
992 if (GNUNET_SYSERR == success) 1636 NULL != lu;) {
1637 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1638 GNUNET_free (lu->label);
1639 tmp = lu->next;
1640 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1641 handle->parallel_lookups_tail,
1642 lu);
1643 GNUNET_free (lu);
1644 lu = tmp;
1645 }
1646 env = GNUNET_MQ_msg (arm,
1647 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1648 arm->id = htonl (handle->r_id);
1649 arm->attr_len = htons (0);
1650 GNUNET_MQ_send (handle->client->mq, env);
1651
1652}
1653
1654
1655static void
1656process_consume_abe_key (void *cls, uint32_t rd_count,
1657 const struct GNUNET_GNSRECORD_Data *rd)
1658{
1659 struct ConsumeTicketHandle *handle = cls;
1660 struct GNUNET_HashCode new_key_hash;
1661 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1662 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1663 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1664 struct ParallelLookup *parallel_lookup;
1665 size_t size;
1666 char *buf;
1667 char *scope;
1668 char *lookup_query;
1669
1670 handle->lookup_request = NULL;
1671 if (1 != rd_count)
993 { 1672 {
994 cleanup_issue_handle (handle); 1673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
995 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1674 "Number of keys %d != 1.",
996 "Unknown Error\n"); 1675 rd_count);
1676 cleanup_consume_ticket_handle (handle);
997 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1677 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
998 return; 1678 return;
999 } 1679 }
1000 if (GNUNET_OK != ticket_serialize (handle->ticket, 1680
1001 &handle->iss_key, 1681 //Decrypt
1002 &ticket_str)) 1682 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1683
1684 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1685
1686 //Calculate symmetric key from ecdh parameters
1687 GNUNET_assert (GNUNET_OK ==
1688 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1689 ecdh_key,
1690 &new_key_hash));
1691 create_sym_key_from_ecdh (&new_key_hash,
1692 &enc_key,
1693 &enc_iv);
1694 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1695 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1696 &enc_key,
1697 &enc_iv,
1698 buf);
1699
1700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1701 "Decrypted bytes: %zd Expected bytes: %zd\n",
1702 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1703 GNUNET_STATISTICS_update (stats_handle,
1704 "abe_key_lookup_time_total",
1705 GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
1706 GNUNET_YES);
1707 GNUNET_STATISTICS_update (stats_handle,
1708 "abe_key_lookups_count",
1709 1,
1710 GNUNET_YES);
1711 scopes = GNUNET_strdup (buf);
1712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1713 "Scopes %s\n", scopes);
1714 handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1715 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1716 - strlen (scopes) - 1);
1717
1718 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1003 { 1719 {
1004 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1720 GNUNET_asprintf (&lookup_query,
1005 "Error serializing ticket\n"); 1721 "%s.gnu",
1006 cleanup_issue_handle (handle); 1722 scope);
1007 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 return; 1724 "Looking up %s\n", lookup_query);
1725 parallel_lookup = GNUNET_new (struct ParallelLookup);
1726 parallel_lookup->handle = handle;
1727 parallel_lookup->label = GNUNET_strdup (scope);
1728 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
1729 parallel_lookup->lookup_request
1730 = GNUNET_GNS_lookup (gns_handle,
1731 lookup_query,
1732 &handle->ticket.identity,
1733 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1734 GNUNET_GNS_LO_DEFAULT,
1735 &process_parallel_lookup2,
1736 parallel_lookup);
1737 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1738 handle->parallel_lookups_tail,
1739 parallel_lookup);
1740 GNUNET_free (lookup_query);
1009 } 1741 }
1010 if (GNUNET_OK != token_to_string (handle->token, 1742 GNUNET_free (scopes);
1011 &handle->iss_key, 1743 GNUNET_free (buf);
1012 &token_str)) 1744 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1745 &abort_parallel_lookups2,
1746 handle);
1747}
1748
1749
1750static void
1751handle_consume_ticket_message (void *cls,
1752 const struct ConsumeTicketMessage *cm)
1753{
1754 struct ConsumeTicketHandle *ch;
1755 struct IdpClient *idp = cls;
1756 char* lookup_query;
1757 char* rnd_label;
1758
1759 ch = GNUNET_new (struct ConsumeTicketHandle);
1760 ch->r_id = ntohl (cm->id);
1761 ch->client = idp;
1762 ch->identity = cm->identity;
1763 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1764 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1765 &ch->identity_pub);
1766 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1767 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1768 sizeof (uint64_t));
1769 GNUNET_asprintf (&lookup_query,
1770 "%s.gnu",
1771 rnd_label);
1772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1773 "Looking for ABE key under %s\n", lookup_query);
1774 ch->lookup_start_time = GNUNET_TIME_absolute_get ();
1775 ch->lookup_request
1776 = GNUNET_GNS_lookup (gns_handle,
1777 lookup_query,
1778 &ch->ticket.identity,
1779 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1780 GNUNET_GNS_LO_DEFAULT,
1781 &process_consume_abe_key,
1782 ch);
1783 GNUNET_free (rnd_label);
1784 GNUNET_free (lookup_query);
1785 GNUNET_SERVICE_client_continue (idp->client);
1786}
1787
1788static void
1789cleanup_as_handle (struct AttributeStoreHandle *handle)
1790{
1791 if (NULL != handle->claim)
1792 GNUNET_free (handle->claim);
1793 if (NULL != handle->abe_key)
1794 GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
1795 GNUNET_free (handle);
1796}
1797
1798static void
1799attr_store_cont (void *cls,
1800 int32_t success,
1801 const char *emsg)
1802{
1803 struct AttributeStoreHandle *as_handle = cls;
1804 struct GNUNET_MQ_Envelope *env;
1805 struct AttributeStoreResultMessage *acr_msg;
1806
1807 if (GNUNET_SYSERR == success)
1013 { 1808 {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1809 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1015 "Error serializing token\n"); 1810 "Failed to store attribute %s\n",
1016 GNUNET_free (ticket_str); 1811 emsg);
1017 cleanup_issue_handle (handle); 1812 cleanup_as_handle (as_handle);
1018 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1813 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1019 return; 1814 return;
1020 } 1815 }
1021 env = create_issue_result_message (handle->label, 1816
1022 ticket_str, 1817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1023 token_str, 1818 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1024 handle->r_id); 1819 env = GNUNET_MQ_msg (acr_msg,
1025 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client), 1820 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1821 acr_msg->id = htonl (as_handle->r_id);
1822 acr_msg->op_result = htonl (GNUNET_OK);
1823 GNUNET_MQ_send (as_handle->client->mq,
1026 env); 1824 env);
1027 cleanup_issue_handle (handle); 1825 cleanup_as_handle (as_handle);
1028 GNUNET_free (ticket_str);
1029 GNUNET_free (token_str);
1030} 1826}
1031 1827
1032
1033/**
1034 * Build a token and store it
1035 *
1036 * @param cls the IssueHandle
1037 */
1038static void 1828static void
1039sign_and_return_token (void *cls) 1829attr_store_task (void *cls)
1040{ 1830{
1041 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 1831 struct AttributeStoreHandle *as_handle = cls;
1042 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; 1832 struct GNUNET_GNSRECORD_Data rd[1];
1043 struct IssueHandle *handle = cls; 1833 char* buf;
1044 struct GNUNET_GNSRECORD_Data token_record[2]; 1834 char* policy;
1045 char *nonce_str; 1835 char* enc_buf;
1046 char *enc_token_str; 1836 char* rd_buf;
1047 char *token_metadata; 1837 size_t enc_size;
1048 char* write_ptr; 1838 size_t buf_size;
1049 uint64_t time; 1839 uint32_t attr_ver;
1050 uint64_t exp_time; 1840
1051 size_t token_metadata_len; 1841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1052 1842 "Storing attribute\n");
1053 //Remote nonce 1843 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim);
1054 nonce_str = NULL; 1844 buf = GNUNET_malloc (buf_size);
1055 GNUNET_asprintf (&nonce_str, "%lu", handle->nonce); 1845
1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str); 1846 GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim,
1057 1847 buf);
1058 GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key, 1848
1059 &pub_key); 1849 GNUNET_asprintf (&policy,
1060 handle->ticket = ticket_create (handle->nonce, 1850 "%s_%lu",
1061 &pub_key, 1851 as_handle->claim->name,
1062 handle->label, 1852 as_handle->claim->version);
1063 &handle->aud_key); 1853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1064 1854 "Encrypting with policy %s\n", policy);
1065 time = GNUNET_TIME_absolute_get().abs_value_us; 1855 /**
1066 exp_time = time + token_expiration_interval.rel_value_us; 1856 * Encrypt the attribute value and store in namestore
1067 1857 */
1068 token_add_attr_int (handle->token, "nbf", time); 1858 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1069 token_add_attr_int (handle->token, "iat", time); 1859 buf_size,
1070 token_add_attr_int (handle->token, "exp", exp_time); 1860 policy, //Policy
1071 token_add_attr (handle->token, "nonce", nonce_str); 1861 as_handle->abe_key,
1072 1862 (void**)&enc_buf);
1073 //Token in a serialized encrypted format 1863 GNUNET_free (buf);
1074 GNUNET_assert (token_serialize (handle->token, 1864 GNUNET_free (policy);
1075 &handle->iss_key, 1865 rd[0].data_size = enc_size + sizeof (uint32_t);
1076 &ecdhe_privkey, 1866 rd_buf = GNUNET_malloc (rd[0].data_size);
1077 &enc_token_str)); 1867 attr_ver = htonl (as_handle->claim->version);
1078 1868 GNUNET_memcpy (rd_buf,
1079 //Token record E,E_K (Token) 1869 &attr_ver,
1080 token_record[0].data = enc_token_str; 1870 sizeof (uint32_t));
1081 token_record[0].data_size = strlen (enc_token_str) + 1; 1871 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1082 token_record[0].expiration_time = exp_time; 1872 enc_buf,
1083 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; 1873 enc_size);
1084 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE; 1874 rd[0].data = rd_buf;
1085 1875 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1086 1876 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1087 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) 1877 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1088 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) 1878 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1089 + strlen (handle->scopes) + 1; //With 0-Terminator 1879 &as_handle->identity,
1090 token_metadata = GNUNET_malloc (token_metadata_len); 1880 as_handle->claim->name,
1091 write_ptr = token_metadata; 1881 1,
1092 GNUNET_memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); 1882 rd,
1093 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); 1883 &attr_store_cont,
1094 GNUNET_memcpy (write_ptr, &handle->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 1884 as_handle);
1095 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); 1885 GNUNET_free (enc_buf);
1096 GNUNET_memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); //with 0-Terminator; 1886 GNUNET_free (rd_buf);
1097
1098 token_record[1].data = token_metadata;
1099 token_record[1].data_size = token_metadata_len;
1100 token_record[1].expiration_time = exp_time;
1101 token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
1102 token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1103
1104 //Persist token
1105 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1106 &handle->iss_key,
1107 handle->label,
1108 2,
1109 token_record,
1110 &store_token_issue_cont,
1111 handle);
1112 GNUNET_free (ecdhe_privkey);
1113 GNUNET_free (nonce_str);
1114 GNUNET_free (enc_token_str);
1115 GNUNET_free (token_metadata);
1116} 1887}
1117 1888
1118 1889
1119static void 1890static void
1120attr_collect_error (void *cls) 1891store_after_abe_bootstrap (void *cls,
1892 struct GNUNET_ABE_AbeMasterKey *abe_key)
1121{ 1893{
1122 struct IssueHandle *handle = cls; 1894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1895 "Finished ABE bootstrap\n");
1896 struct AttributeStoreHandle *ash = cls;
1897 ash->abe_key = abe_key;
1898 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1899}
1123 1900
1124 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n"); 1901static int
1125 handle->ns_it = NULL; 1902check_attribute_store_message(void *cls,
1126 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); 1903 const struct AttributeStoreMessage *sam)
1904{
1905 uint16_t size;
1906
1907 size = ntohs (sam->header.size);
1908 if (size <= sizeof (struct AttributeStoreMessage))
1909 {
1910 GNUNET_break (0);
1911 return GNUNET_SYSERR;
1912 }
1913 return GNUNET_OK;
1127} 1914}
1128 1915
1129 1916
1130static void 1917static void
1131attr_collect_finished (void *cls) 1918handle_attribute_store_message (void *cls,
1919 const struct AttributeStoreMessage *sam)
1132{ 1920{
1133 struct IssueHandle *handle = cls; 1921 struct AttributeStoreHandle *as_handle;
1922 struct IdpClient *idp = cls;
1923 size_t data_len;
1924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1925 "Received ATTRIBUTE_STORE message\n");
1926
1927 data_len = ntohs (sam->attr_len);
1928
1929 as_handle = GNUNET_new (struct AttributeStoreHandle);
1930 as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1],
1931 data_len);
1932
1933 as_handle->r_id = ntohl (sam->id);
1934 as_handle->identity = sam->identity;
1935 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1936 &as_handle->identity_pkey);
1134 1937
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n"); 1938 GNUNET_SERVICE_client_continue (idp->client);
1136 handle->ns_it = NULL; 1939 as_handle->client = idp;
1137 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); 1940 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
1138} 1941}
1139 1942
1943static void
1944cleanup_iter_handle (struct AttributeIterator *ai)
1945{
1946 if (NULL != ai->abe_key)
1947 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
1948 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1949 ai->client->op_tail,
1950 ai);
1951 GNUNET_free (ai);
1952}
1953
1954static void
1955attr_iter_error (void *cls)
1956{
1957 struct AttributeIterator *ai = cls;
1958 //TODO
1959 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1960 "Failed to iterate over attributes\n");
1961 cleanup_iter_handle (ai);
1962 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1963}
1964
1965static void
1966attr_iter_finished (void *cls)
1967{
1968 struct AttributeIterator *ai = cls;
1969 struct GNUNET_MQ_Envelope *env;
1970 struct AttributeResultMessage *arm;
1971
1972 env = GNUNET_MQ_msg (arm,
1973 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1974 arm->id = htonl (ai->request_id);
1975 arm->attr_len = htons (0);
1976 GNUNET_MQ_send (ai->client->mq, env);
1977 cleanup_iter_handle (ai);
1978}
1140 1979
1141/**
1142 * Collect attributes for token
1143 */
1144static void 1980static void
1145attr_collect (void *cls, 1981attr_iter_cb (void *cls,
1146 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1982 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1147 const char *label, 1983 const char *label,
1148 unsigned int rd_count, 1984 unsigned int rd_count,
1149 const struct GNUNET_GNSRECORD_Data *rd) 1985 const struct GNUNET_GNSRECORD_Data *rd)
1150{ 1986{
1151 struct IssueHandle *handle = cls; 1987 struct AttributeIterator *ai = cls;
1152 int i; 1988 struct AttributeResultMessage *arm;
1153 char* data; 1989 struct GNUNET_ABE_AbeKey *key;
1154 struct GNUNET_HashCode key; 1990 struct GNUNET_MQ_Envelope *env;
1155 1991 ssize_t msg_extra_len;
1156 GNUNET_CRYPTO_hash (label, 1992 char* attr_ser;
1157 strlen (label), 1993 char* attrs[2];
1158 &key); 1994 char* data_tmp;
1159 1995 char* policy;
1160 if (0 == rd_count || 1996 uint32_t attr_ver;
1161 ( (NULL != handle->attr_map) && 1997
1162 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, 1998 if (rd_count != 1)
1163 &key))
1164 )
1165 )
1166 { 1999 {
1167 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2000 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1168 return; 2001 return;
1169 } 2002 }
1170 2003
1171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label); 2004 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1172 2005 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1173 if (1 == rd_count)
1174 {
1175 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1176 {
1177 data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
1178 rd->data,
1179 rd->data_size);
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1181 token_add_attr (handle->token,
1182 label,
1183 data);
1184 GNUNET_free (data);
1185 }
1186 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1187 return; 2006 return;
1188 } 2007 }
2008 attr_ver = ntohl(*((uint32_t*)rd->data));
2009 GNUNET_asprintf (&policy, "%s_%lu",
2010 label, attr_ver);
2011 attrs[0] = policy;
2012 attrs[1] = 0;
2013 key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
2014 attrs);
2015 msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
2016 rd->data_size-sizeof (uint32_t),
2017 key,
2018 (void**)&attr_ser);
2019
2020 GNUNET_ABE_cpabe_delete_key (key,
2021 GNUNET_YES);
2022 //GNUNET_free (policy);
2023 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2024 "Found attribute: %s\n", label);
2025 env = GNUNET_MQ_msg_extra (arm,
2026 msg_extra_len,
2027 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2028 arm->id = htonl (ai->request_id);
2029 arm->attr_len = htons (msg_extra_len);
2030 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2031 &arm->identity);
2032 data_tmp = (char *) &arm[1];
2033 GNUNET_memcpy (data_tmp,
2034 attr_ser,
2035 msg_extra_len);
2036 GNUNET_MQ_send (ai->client->mq, env);
2037 GNUNET_free (attr_ser);
2038 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2039 ai->abe_key = NULL;
2040}
1189 2041
1190 i = 0;
1191 for (; i < rd_count; i++)
1192 {
1193 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1194 {
1195 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
1196 rd[i].data,
1197 rd[i].data_size);
1198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1199 token_add_attr (handle->token, label, data);
1200 GNUNET_free (data);
1201 }
1202 }
1203 2042
1204 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2043void
2044iterate_after_abe_bootstrap (void *cls,
2045 struct GNUNET_ABE_AbeMasterKey *abe_key)
2046{
2047 struct AttributeIterator *ai = cls;
2048 ai->abe_key = abe_key;
2049 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2050 &ai->identity,
2051 &attr_iter_error,
2052 ai,
2053 &attr_iter_cb,
2054 ai,
2055 &attr_iter_finished,
2056 ai);
1205} 2057}
1206 2058
2059void
2060iterate_next_after_abe_bootstrap (void *cls,
2061 struct GNUNET_ABE_AbeMasterKey *abe_key)
2062{
2063 struct AttributeIterator *ai = cls;
2064 ai->abe_key = abe_key;
2065 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2066}
2067
2068
2069
1207static void 2070static void
1208cleanup_exchange_handle (struct ExchangeHandle *handle) 2071handle_iteration_start (void *cls,
2072 const struct AttributeIterationStartMessage *ais_msg)
1209{ 2073{
1210 if (NULL != handle->ticket) 2074 struct IdpClient *idp = cls;
1211 ticket_destroy (handle->ticket); 2075 struct AttributeIterator *ai;
1212 if (NULL != handle->token) 2076
1213 token_destroy (handle->token); 2077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1214 GNUNET_free (handle); 2078 "Received ATTRIBUTE_ITERATION_START message\n");
2079 ai = GNUNET_new (struct AttributeIterator);
2080 ai->request_id = ntohl (ais_msg->id);
2081 ai->client = idp;
2082 ai->identity = ais_msg->identity;
2083
2084 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2085 idp->op_tail,
2086 ai);
2087 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2088 GNUNET_SERVICE_client_continue (idp->client);
1215} 2089}
1216 2090
2091
1217static void 2092static void
1218process_lookup_result (void *cls, uint32_t rd_count, 2093handle_iteration_stop (void *cls,
1219 const struct GNUNET_GNSRECORD_Data *rd) 2094 const struct AttributeIterationStopMessage *ais_msg)
1220{ 2095{
1221 struct ExchangeHandle *handle = cls; 2096 struct IdpClient *idp = cls;
1222 struct GNUNET_MQ_Envelope *env; 2097 struct AttributeIterator *ai;
1223 char* token_str; 2098 uint32_t rid;
1224 char* record_str;
1225 2099
1226 handle->lookup_request = NULL; 2100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1227 if (2 != rd_count) 2101 "Received `%s' message\n",
2102 "ATTRIBUTE_ITERATION_STOP");
2103 rid = ntohl (ais_msg->id);
2104 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2105 if (ai->request_id == rid)
2106 break;
2107 if (NULL == ai)
1228 { 2108 {
1229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2109 GNUNET_break (0);
1230 "Number of tokens %d != 2.", 2110 GNUNET_SERVICE_client_drop (idp->client);
1231 rd_count);
1232 cleanup_exchange_handle (handle);
1233 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1234 return; 2111 return;
1235 } 2112 }
1236 2113 GNUNET_CONTAINER_DLL_remove (idp->op_head,
1237 record_str = 2114 idp->op_tail,
1238 GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN, 2115 ai);
1239 rd->data, 2116 GNUNET_free (ai);
1240 rd->data_size); 2117 GNUNET_SERVICE_client_continue (idp->client);
1241
1242 //Decrypt and parse
1243 GNUNET_assert (GNUNET_OK == token_parse (record_str,
1244 &handle->aud_privkey,
1245 &handle->token));
1246
1247 //Readable
1248 GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
1249 &handle->aud_privkey,
1250 &token_str));
1251
1252 env = create_exchange_result_message (token_str,
1253 handle->label,
1254 handle->ticket->payload->nonce,
1255 handle->r_id);
1256 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
1257 env);
1258 cleanup_exchange_handle (handle);
1259 GNUNET_free (record_str);
1260 GNUNET_free (token_str);
1261} 2118}
1262 2119
1263/** 2120
1264 * Checks a exchange message 2121static void
1265 * 2122handle_iteration_next (void *cls,
1266 * @param cls client sending the message 2123 const struct AttributeIterationNextMessage *ais_msg)
1267 * @param xm message of type `struct ExchangeMessage`
1268 * @return #GNUNET_OK if @a xm is well-formed
1269 */
1270static int
1271check_exchange_message (void *cls,
1272 const struct ExchangeMessage *xm)
1273{ 2124{
1274 uint16_t size; 2125 struct IdpClient *idp = cls;
2126 struct AttributeIterator *ai;
2127 uint32_t rid;
1275 2128
1276 size = ntohs (xm->header.size); 2129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1277 if (size <= sizeof (struct ExchangeMessage)) 2130 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2131 rid = ntohl (ais_msg->id);
2132 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2133 if (ai->request_id == rid)
2134 break;
2135 if (NULL == ai)
1278 { 2136 {
1279 GNUNET_break (0); 2137 GNUNET_break (0);
1280 return GNUNET_SYSERR; 2138 GNUNET_SERVICE_client_drop (idp->client);
2139 return;
1281 } 2140 }
1282 return GNUNET_OK; 2141 bootstrap_abe (&ai->identity,
2142 &iterate_next_after_abe_bootstrap,
2143 ai,
2144 GNUNET_NO);
2145 GNUNET_SERVICE_client_continue (idp->client);
1283} 2146}
1284 2147
1285/** 2148/**
1286 * 2149 * Ticket iteration processor result
1287 * Handler for exchange message
1288 *
1289 * @param cls unused
1290 * @param client who sent the message
1291 * @param message the message
1292 */ 2150 */
1293static void 2151enum ZoneIterationResult
1294handle_exchange_message (void *cls,
1295 const struct ExchangeMessage *xm)
1296{ 2152{
1297 struct ExchangeHandle *xchange_handle; 2153 /**
1298 struct GNUNET_SERVICE_Client *client = cls; 2154 * Iteration start.
1299 const char *ticket; 2155 */
1300 char *lookup_query; 2156 IT_START = 0,
1301 2157
1302 ticket = (const char *) &xm[1]; 2158 /**
1303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2159 * Found tickets,
1304 "Received EXCHANGE of `%s' from client\n", 2160 * Continue to iterate with next iteration_next call
1305 ticket); 2161 */
1306 xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle)); 2162 IT_SUCCESS_MORE_AVAILABLE = 1,
1307 xchange_handle->aud_privkey = xm->aud_privkey;
1308 xchange_handle->r_id = xm->id;
1309 if (GNUNET_SYSERR == ticket_parse (ticket,
1310 &xchange_handle->aud_privkey,
1311 &xchange_handle->ticket))
1312 {
1313 GNUNET_free (xchange_handle);
1314 GNUNET_SERVICE_client_drop (client);
1315 return;
1316 }
1317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for token under %s\n",
1318 xchange_handle->ticket->payload->label);
1319 GNUNET_asprintf (&lookup_query,
1320 "%s.gnu",
1321 xchange_handle->ticket->payload->label);
1322 GNUNET_SERVICE_client_continue (client);
1323 xchange_handle->client = client;
1324 xchange_handle->lookup_request
1325 = GNUNET_GNS_lookup (gns_handle,
1326 lookup_query,
1327 &xchange_handle->ticket->payload->identity_key,
1328 GNUNET_GNSRECORD_TYPE_ID_TOKEN,
1329 GNUNET_GNS_LO_LOCAL_MASTER,
1330 &process_lookup_result,
1331 xchange_handle);
1332 GNUNET_free (lookup_query);
1333 2163
1334} 2164 /**
2165 * Iteration complete
2166 */
2167 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2168};
1335 2169
1336 2170
1337static void 2171/**
1338find_existing_token_error (void *cls) 2172 * Context for ticket iteration
2173 */
2174struct TicketIterationProcResult
1339{ 2175{
1340 struct IssueHandle *handle = cls; 2176 /**
1341 cleanup_issue_handle (handle); 2177 * The ticket iteration handle
1342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error looking for existing token\n"); 2178 */
1343 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 2179 struct TicketIteration *ti;
1344}
1345 2180
2181 /**
2182 * Iteration result: iteration done?
2183 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2184 * we got one for now and have sent it to the client
2185 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2186 * #IT_START: if we are still trying to find a result.
2187 */
2188 int res_iteration_finished;
2189
2190};
1346 2191
1347static void 2192static void
1348find_existing_token_finished (void *cls) 2193cleanup_ticket_iter_handle (struct TicketIteration *ti)
1349{ 2194{
1350 struct IssueHandle *handle = cls; 2195 GNUNET_free (ti);
1351 uint64_t rnd_key;
1352
1353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1354 ">>> No existing token found\n");
1355 rnd_key =
1356 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1357 UINT64_MAX);
1358 GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
1359 sizeof (uint64_t),
1360 &handle->label);
1361 handle->ns_it = NULL;
1362 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1363 &handle->iss_key,
1364 &attr_collect_error,
1365 handle,
1366 &attr_collect,
1367 handle,
1368 &attr_collect_finished,
1369 handle);
1370} 2196}
1371 2197
1372
1373/** 2198/**
2199 * Process ticket from database
1374 * 2200 *
1375 * Look for existing token 2201 * @param cls struct TicketIterationProcResult
1376 * 2202 * @param ticket the ticket
1377 * @param cls the identity entry 2203 * @param attrs the attributes
1378 * @param zone the identity
1379 * @param lbl the name of the record
1380 * @param rd_count number of records
1381 * @param rd record data
1382 *
1383 */ 2204 */
1384static void 2205static void
1385find_existing_token (void *cls, 2206ticket_iterate_proc (void *cls,
1386 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 2207 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1387 const char *lbl, 2208 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
1388 unsigned int rd_count, 2209{
1389 const struct GNUNET_GNSRECORD_Data *rd) 2210 struct TicketIterationProcResult *proc = cls;
1390{
1391 struct IssueHandle *handle = cls;
1392 const struct GNUNET_GNSRECORD_Data *token_metadata_record;
1393 struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
1394 struct GNUNET_HashCode key;
1395 int scope_count_token;
1396 char *scope;
1397 char *tmp_scopes;
1398 2211
1399 //There should be only a single record for a token under a label 2212 if (NULL == ticket)
1400 if (2 != rd_count)
1401 { 2213 {
1402 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2215 "Iteration done\n");
2216 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1403 return; 2217 return;
1404 } 2218 }
2219 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2220 send_ticket_result (proc->ti->client,
2221 proc->ti->r_id,
2222 ticket,
2223 attrs);
1405 2224
1406 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 2225}
1407 {
1408 token_metadata_record = &rd[0];
1409 }
1410 else
1411 {
1412 token_metadata_record = &rd[1];
1413 }
1414 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
1415 {
1416 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1417 return;
1418 }
1419 ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
1420 aud_key =
1421 (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
1422 tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1423 2226
1424 if (0 != memcmp (aud_key, &handle->aud_key, 2227/**
1425 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) 2228 * Perform ticket iteration step
1426 { 2229 *
1427 char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key, 2230 * @param ti ticket iterator to process
1428 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 2231 */
1429 //Audience does not match! 2232static void
1430 char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA, 2233run_ticket_iteration_round (struct TicketIteration *ti)
1431 token_metadata_record->data, 2234{
1432 token_metadata_record->data_size); 2235 struct TicketIterationProcResult proc;
1433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2236 struct GNUNET_MQ_Envelope *env;
1434 "Token does not match audience %s vs %s. Moving on\n", 2237 struct TicketResultMessage *trm;
1435 tmp2, 2238 int ret;
1436 tmp);
1437 GNUNET_free (tmp_scopes);
1438 GNUNET_free (tmp2);
1439 GNUNET_free (tmp);
1440 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1441 return;
1442 }
1443 2239
1444 scope = strtok (tmp_scopes, ","); 2240 memset (&proc, 0, sizeof (proc));
1445 scope_count_token = 0; 2241 proc.ti = ti;
1446 while (NULL != scope) 2242 proc.res_iteration_finished = IT_START;
2243 while (IT_START == proc.res_iteration_finished)
1447 { 2244 {
1448 GNUNET_CRYPTO_hash (scope, 2245 if (GNUNET_SYSERR ==
1449 strlen (scope), 2246 (ret = TKT_database->iterate_tickets (TKT_database->cls,
1450 &key); 2247 &ti->identity,
1451 2248 ti->is_audience,
1452 if ((NULL != handle->attr_map) && 2249 ti->offset,
1453 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key))) 2250 &ticket_iterate_proc,
2251 &proc)))
1454 { 2252 {
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2253 GNUNET_break (0);
1456 "Issued token does not include `%s'. Moving on\n", scope); 2254 break;
1457 GNUNET_free (tmp_scopes);
1458 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1459 return;
1460 } 2255 }
1461 scope_count_token++; 2256 if (GNUNET_NO == ret)
1462 scope = strtok (NULL, ","); 2257 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2258 ti->offset++;
1463 } 2259 }
1464 GNUNET_free (tmp_scopes); 2260 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1465 //All scopes in token are also in request. Now
1466 //Check length
1467 if ((NULL != handle->attr_map) &&
1468 (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == scope_count_token))
1469 { 2261 {
1470 //We have an existing token 2262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1471 handle->label = GNUNET_strdup (lbl); 2263 "More results available\n");
1472 handle->ns_it = NULL; 2264 return; /* more later */
1473 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1474 &handle->iss_key,
1475 &attr_collect_error,
1476 handle,
1477 &attr_collect,
1478 handle,
1479 &attr_collect_finished,
1480 handle);
1481
1482 return;
1483 } 2265 }
1484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2266 /* send empty response to indicate end of list */
1485 "Nuber of attributes in token do not match request\n"); 2267 env = GNUNET_MQ_msg (trm,
1486 //No luck 2268 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
1487 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2269 trm->id = htonl (ti->r_id);
2270 GNUNET_MQ_send (ti->client->mq,
2271 env);
2272 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2273 ti->client->ticket_iter_tail,
2274 ti);
2275 cleanup_ticket_iter_handle (ti);
1488} 2276}
1489 2277
1490/** 2278static void
1491 * Checks an issue message 2279handle_ticket_iteration_start (void *cls,
1492 * 2280 const struct TicketIterationStartMessage *tis_msg)
1493 * @param cls client sending the message
1494 * @param im message of type `struct IssueMessage`
1495 * @return #GNUNET_OK if @a im is well-formed
1496 */
1497static int
1498check_issue_message(void *cls,
1499 const struct IssueMessage *im)
1500{ 2281{
1501 uint16_t size; 2282 struct IdpClient *client = cls;
2283 struct TicketIteration *ti;
1502 2284
1503 size = ntohs (im->header.size); 2285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1504 if (size <= sizeof (struct IssueMessage)) 2286 "Received TICKET_ITERATION_START message\n");
1505 { 2287 ti = GNUNET_new (struct TicketIteration);
1506 GNUNET_break (0); 2288 ti->r_id = ntohl (tis_msg->id);
1507 return GNUNET_SYSERR; 2289 ti->offset = 0;
1508 } 2290 ti->client = client;
1509 scopes = (char *) &im[1]; 2291 ti->identity = tis_msg->identity;
1510 if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1]) 2292 ti->is_audience = ntohl (tis_msg->is_audience);
2293
2294 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2295 client->ticket_iter_tail,
2296 ti);
2297 run_ticket_iteration_round (ti);
2298 GNUNET_SERVICE_client_continue (client->client);
2299}
2300
2301
2302static void
2303handle_ticket_iteration_stop (void *cls,
2304 const struct TicketIterationStopMessage *tis_msg)
2305{
2306 struct IdpClient *client = cls;
2307 struct TicketIteration *ti;
2308 uint32_t rid;
2309
2310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2311 "Received `%s' message\n",
2312 "TICKET_ITERATION_STOP");
2313 rid = ntohl (tis_msg->id);
2314 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2315 if (ti->r_id == rid)
2316 break;
2317 if (NULL == ti)
1511 { 2318 {
1512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1513 "Malformed scopes received!\n");
1514 GNUNET_break (0); 2319 GNUNET_break (0);
1515 return GNUNET_SYSERR; 2320 GNUNET_SERVICE_client_drop (client->client);
2321 return;
1516 } 2322 }
1517 return GNUNET_OK; 2323 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2324 client->ticket_iter_tail,
2325 ti);
2326 cleanup_ticket_iter_handle (ti);
2327 GNUNET_SERVICE_client_continue (client->client);
1518} 2328}
1519 2329
1520/** 2330
1521 *
1522 * Handler for issue message
1523 *
1524 * @param cls unused
1525 * @param client who sent the message
1526 * @param message the message
1527 */
1528static void 2331static void
1529handle_issue_message (void *cls, 2332handle_ticket_iteration_next (void *cls,
1530 const struct IssueMessage *im) 2333 const struct TicketIterationNextMessage *tis_msg)
1531{ 2334{
1532 const char *scopes; 2335 struct IdpClient *client = cls;
1533 char *scopes_tmp; 2336 struct TicketIteration *ti;
1534 char *scope; 2337 uint32_t rid;
1535 struct GNUNET_HashCode key;
1536 struct IssueHandle *issue_handle;
1537 struct GNUNET_SERVICE_Client *client = cls;
1538
1539 scopes = (const char *) &im[1];
1540 issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
1541 issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
1542 GNUNET_NO);
1543 scopes_tmp = GNUNET_strdup (scopes);
1544 2338
1545 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) 2339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2340 "Received TICKET_ITERATION_NEXT message\n");
2341 rid = ntohl (tis_msg->id);
2342 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2343 if (ti->r_id == rid)
2344 break;
2345 if (NULL == ti)
1546 { 2346 {
1547 GNUNET_CRYPTO_hash (scope, 2347 GNUNET_break (0);
1548 strlen (scope), 2348 GNUNET_SERVICE_client_drop (client->client);
1549 &key); 2349 return;
1550 GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1551 &key,
1552 scope,
1553 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1554 } 2350 }
1555 GNUNET_free (scopes_tmp); 2351 run_ticket_iteration_round (ti);
1556 issue_handle->r_id = im->id; 2352 GNUNET_SERVICE_client_continue (client->client);
1557 issue_handle->aud_key = im->aud_key;
1558 issue_handle->iss_key = im->iss_key;
1559 GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
1560 &issue_handle->iss_pkey);
1561 issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
1562 issue_handle->nonce = ntohl (im->nonce);
1563 GNUNET_SERVICE_client_continue (client);
1564 issue_handle->client = client;
1565 issue_handle->scopes = GNUNET_strdup (scopes);
1566 issue_handle->token = token_create (&issue_handle->iss_pkey,
1567 &issue_handle->aud_key);
1568
1569 issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1570 &im->iss_key,
1571 &find_existing_token_error,
1572 issue_handle,
1573 &find_existing_token,
1574 issue_handle,
1575 &find_existing_token_finished,
1576 issue_handle);
1577} 2353}
1578 2354
1579 2355
2356
2357
1580/** 2358/**
1581 * Main function that will be run 2359 * Main function that will be run
1582 * 2360 *
1583 * @param cls closure 2361 * @param cls closure
1584 * @param args remaining command-line arguments 2362 * @param c the configuration used
1585 * @param cfgfile name of the configuration file used (for saving, can be NULL) 2363 * @param server the service handle
1586 * @param c configuration
1587 */ 2364 */
1588static void 2365static void
1589run (void *cls, 2366run (void *cls,
1590 const struct GNUNET_CONFIGURATION_Handle *c, 2367 const struct GNUNET_CONFIGURATION_Handle *c,
1591 struct GNUNET_SERVICE_Handle *server) 2368 struct GNUNET_SERVICE_Handle *server)
1592{ 2369{
2370 char *database;
1593 cfg = c; 2371 cfg = c;
1594 2372
1595 stats = GNUNET_STATISTICS_create ("identity-provider", cfg); 2373 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
@@ -1606,10 +2384,38 @@ run (void *cls,
1606 { 2384 {
1607 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); 2385 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1608 } 2386 }
1609 2387 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2388 if (NULL == credential_handle)
2389 {
2390 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2391 }
1610 identity_handle = GNUNET_IDENTITY_connect (cfg, 2392 identity_handle = GNUNET_IDENTITY_connect (cfg,
1611 &list_ego, 2393 NULL,
1612 NULL); 2394 NULL);
2395 stats_handle = GNUNET_STATISTICS_create ("identity-provider",
2396 cfg);
2397 /* Loading DB plugin */
2398 if (GNUNET_OK !=
2399 GNUNET_CONFIGURATION_get_value_string (cfg,
2400 "identity-provider",
2401 "database",
2402 &database))
2403 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2404 "No database backend configured\n");
2405 GNUNET_asprintf (&db_lib_name,
2406 "libgnunet_plugin_identity_provider_%s",
2407 database);
2408 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2409 (void *) cfg);
2410 GNUNET_free (database);
2411 if (NULL == TKT_database)
2412 {
2413 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2414 "Could not load database backend `%s'\n",
2415 db_lib_name);
2416 GNUNET_SCHEDULER_shutdown ();
2417 return;
2418 }
1613 2419
1614 if (GNUNET_OK == 2420 if (GNUNET_OK ==
1615 GNUNET_CONFIGURATION_get_value_time (cfg, 2421 GNUNET_CONFIGURATION_get_value_time (cfg,
@@ -1640,9 +2446,39 @@ client_disconnect_cb (void *cls,
1640 struct GNUNET_SERVICE_Client *client, 2446 struct GNUNET_SERVICE_Client *client,
1641 void *app_ctx) 2447 void *app_ctx)
1642{ 2448{
2449 struct IdpClient *idp = app_ctx;
2450 struct AttributeIterator *ai;
2451 struct TicketIteration *ti;
2452 struct TicketRevocationHandle *rh;
2453
2454 //TODO other operations
2455
1643 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1644 "Client %p disconnected\n", 2457 "Client %p disconnected\n",
1645 client); 2458 client);
2459
2460 while (NULL != (ai = idp->op_head))
2461 {
2462 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2463 idp->op_tail,
2464 ai);
2465 GNUNET_free (ai);
2466 }
2467 while (NULL != (rh = idp->revocation_list_head))
2468 {
2469 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2470 idp->revocation_list_tail,
2471 rh);
2472 cleanup_revoke_ticket_handle (rh);
2473 }
2474 while (NULL != (ti = idp->ticket_iter_head))
2475 {
2476 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2477 idp->ticket_iter_tail,
2478 ti);
2479 cleanup_ticket_iter_handle (ti);
2480 }
2481 GNUNET_free (idp);
1646} 2482}
1647 2483
1648 2484
@@ -1659,10 +2495,14 @@ client_connect_cb (void *cls,
1659 struct GNUNET_SERVICE_Client *client, 2495 struct GNUNET_SERVICE_Client *client,
1660 struct GNUNET_MQ_Handle *mq) 2496 struct GNUNET_MQ_Handle *mq)
1661{ 2497{
2498 struct IdpClient *idp;
1662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1663 "Client %p connected\n", 2500 "Client %p connected\n",
1664 client); 2501 client);
1665 return client; 2502 idp = GNUNET_new (struct IdpClient);
2503 idp->client = client;
2504 idp->mq = mq;
2505 return idp;
1666} 2506}
1667 2507
1668 2508
@@ -1677,13 +2517,45 @@ GNUNET_SERVICE_MAIN
1677 &client_connect_cb, 2517 &client_connect_cb,
1678 &client_disconnect_cb, 2518 &client_disconnect_cb,
1679 NULL, 2519 NULL,
1680 GNUNET_MQ_hd_var_size (issue_message, 2520 GNUNET_MQ_hd_var_size (attribute_store_message,
1681 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE, 2521 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
1682 struct IssueMessage, 2522 struct AttributeStoreMessage,
2523 NULL),
2524 GNUNET_MQ_hd_fixed_size (iteration_start,
2525 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2526 struct AttributeIterationStartMessage,
2527 NULL),
2528 GNUNET_MQ_hd_fixed_size (iteration_next,
2529 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2530 struct AttributeIterationNextMessage,
2531 NULL),
2532 GNUNET_MQ_hd_fixed_size (iteration_stop,
2533 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2534 struct AttributeIterationStopMessage,
2535 NULL),
2536 GNUNET_MQ_hd_var_size (issue_ticket_message,
2537 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2538 struct IssueTicketMessage,
2539 NULL),
2540 GNUNET_MQ_hd_var_size (consume_ticket_message,
2541 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2542 struct ConsumeTicketMessage,
1683 NULL), 2543 NULL),
1684 GNUNET_MQ_hd_var_size (exchange_message, 2544 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1685 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE, 2545 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
1686 struct ExchangeMessage, 2546 struct TicketIterationStartMessage,
2547 NULL),
2548 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2549 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2550 struct TicketIterationNextMessage,
2551 NULL),
2552 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2553 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2554 struct TicketIterationStopMessage,
2555 NULL),
2556 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2557 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2558 struct RevokeTicketMessage,
1687 NULL), 2559 NULL),
1688 GNUNET_MQ_handler_end()); 2560 GNUNET_MQ_handler_end());
1689/* end of gnunet-service-identity-provider.c */ 2561/* end of gnunet-service-identity-provider.c */
diff --git a/src/identity-provider/identity-provider.conf b/src/identity-provider/identity-provider.conf
index bac8e69ed..7ee5e50d8 100644
--- a/src/identity-provider/identity-provider.conf
+++ b/src/identity-provider/identity-provider.conf
@@ -10,3 +10,7 @@ UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-identity-provider.sock
10UNIX_MATCH_UID = NO 10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES 11UNIX_MATCH_GID = YES
12TOKEN_EXPIRATION_INTERVAL = 30 m 12TOKEN_EXPIRATION_INTERVAL = 30 m
13DATABASE = sqlite
14
15[identity-provider-sqlite]
16FILENAME = $GNUNET_DATA_HOME/identity-provider/sqlite.db
diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h
index 6fe6102c8..b1fe6e1fd 100644
--- a/src/identity-provider/identity_provider.h
+++ b/src/identity-provider/identity_provider.h
@@ -34,34 +34,157 @@
34GNUNET_NETWORK_STRUCT_BEGIN 34GNUNET_NETWORK_STRUCT_BEGIN
35 35
36/** 36/**
37 * The token 37 * Use to store an identity attribute
38 */ 38 */
39struct GNUNET_IDENTITY_PROVIDER_Token 39struct AttributeStoreMessage
40{ 40{
41 /** 41 /**
42 * The JWT representation of the identity token 42 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
43 */
44 struct GNUNET_MessageHeader header;
45
46 /**
47 * Unique identifier for this request (for key collisions).
43 */ 48 */
44 char *data; 49 uint32_t id GNUNET_PACKED;
50
51 /**
52 * The length of the attribute
53 */
54 uint32_t attr_len GNUNET_PACKED;
55
56 /**
57 * Identity
58 */
59 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
60
61 /* followed by the serialized attribute */
62
45}; 63};
46 64
47/** 65/**
48 * The ticket 66 * Attribute store response message
49 */ 67 */
50struct GNUNET_IDENTITY_PROVIDER_Ticket 68struct AttributeStoreResultMessage
51{ 69{
52 /** 70 /**
53 * The Base64 representation of the ticket 71 * Message header
72 */
73 struct GNUNET_MessageHeader header;
74
75 /**
76 * Unique identifier for this request (for key collisions).
77 */
78 uint32_t id GNUNET_PACKED;
79
80 /**
81 * #GNUNET_SYSERR on failure, #GNUNET_OK on success
82 */
83 int32_t op_result GNUNET_PACKED;
84
85};
86
87/**
88 * Attribute is returned from the idp.
89 */
90struct AttributeResultMessage
91{
92 /**
93 * Message header
94 */
95 struct GNUNET_MessageHeader header;
96
97 /**
98 * Unique identifier for this request (for key collisions).
99 */
100 uint32_t id GNUNET_PACKED;
101
102 /**
103 * Length of serialized attribute data
104 */
105 uint16_t attr_len GNUNET_PACKED;
106
107 /**
108 * always zero (for alignment)
109 */
110 uint16_t reserved GNUNET_PACKED;
111
112 /**
113 * The public key of the identity.
114 */
115 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
116
117 /* followed by:
118 * serialized attribute data
119 */
120};
121
122
123/**
124 * Start a attribute iteration for the given identity
125 */
126struct AttributeIterationStartMessage
127{
128 /**
129 * Message
130 */
131 struct GNUNET_MessageHeader header;
132
133 /**
134 * Unique identifier for this request (for key collisions).
135 */
136 uint32_t id GNUNET_PACKED;
137
138 /**
139 * Identity.
140 */
141 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
142
143};
144
145
146/**
147 * Ask for next result of attribute iteration for the given operation
148 */
149struct AttributeIterationNextMessage
150{
151 /**
152 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT
153 */
154 struct GNUNET_MessageHeader header;
155
156 /**
157 * Unique identifier for this request (for key collisions).
158 */
159 uint32_t id GNUNET_PACKED;
160
161};
162
163
164/**
165 * Stop attribute iteration for the given operation
166 */
167struct AttributeIterationStopMessage
168{
169 /**
170 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP
171 */
172 struct GNUNET_MessageHeader header;
173
174 /**
175 * Unique identifier for this request (for key collisions).
54 */ 176 */
55 char *data; 177 uint32_t id GNUNET_PACKED;
178
56}; 179};
57 180
58/** 181/**
59 * Answer from service to client after issue operation 182 * Start a ticket iteration for the given identity
60 */ 183 */
61struct IssueResultMessage 184struct TicketIterationStartMessage
62{ 185{
63 /** 186 /**
64 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE 187 * Message
65 */ 188 */
66 struct GNUNET_MessageHeader header; 189 struct GNUNET_MessageHeader header;
67 190
@@ -70,18 +193,25 @@ struct IssueResultMessage
70 */ 193 */
71 uint32_t id GNUNET_PACKED; 194 uint32_t id GNUNET_PACKED;
72 195
73 /* followed by 0-terminated label,ticket,token */ 196 /**
197 * Identity.
198 */
199 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
74 200
201 /**
202 * Identity is audience or issuer
203 */
204 uint32_t is_audience GNUNET_PACKED;
75}; 205};
76 206
77 207
78/** 208/**
79 * Ticket exchange message. 209 * Ask for next result of ticket iteration for the given operation
80 */ 210 */
81struct ExchangeResultMessage 211struct TicketIterationNextMessage
82{ 212{
83 /** 213 /**
84 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE 214 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT
85 */ 215 */
86 struct GNUNET_MessageHeader header; 216 struct GNUNET_MessageHeader header;
87 217
@@ -90,25 +220,35 @@ struct ExchangeResultMessage
90 */ 220 */
91 uint32_t id GNUNET_PACKED; 221 uint32_t id GNUNET_PACKED;
92 222
223};
224
225
226/**
227 * Stop ticket iteration for the given operation
228 */
229struct TicketIterationStopMessage
230{
93 /** 231 /**
94 * Nonce found in ticket. NBO 232 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP
95 * 0 on error.
96 */ 233 */
97 uint64_t ticket_nonce GNUNET_PACKED; 234 struct GNUNET_MessageHeader header;
98 235
99 /* followed by 0-terminated token */ 236 /**
237 * Unique identifier for this request (for key collisions).
238 */
239 uint32_t id GNUNET_PACKED;
100 240
101}; 241};
102 242
103 243
104 244
105/** 245/**
106 * Client requests IdP to issue token. 246 * Ticket issue message
107 */ 247 */
108struct IssueMessage 248struct IssueTicketMessage
109{ 249{
110 /** 250 /**
111 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT 251 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET
112 */ 252 */
113 struct GNUNET_MessageHeader header; 253 struct GNUNET_MessageHeader header;
114 254
@@ -117,40 +257,98 @@ struct IssueMessage
117 */ 257 */
118 uint32_t id GNUNET_PACKED; 258 uint32_t id GNUNET_PACKED;
119 259
260 /**
261 * Identity.
262 */
263 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
120 264
121 /** 265 /**
122 * Issuer identity private key 266 * Requesting party.
123 */ 267 */
124 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key; 268 struct GNUNET_CRYPTO_EcdsaPublicKey rp;
125 269
126 /** 270 /**
127 * Audience public key 271 * length of serialized attribute list
128 */ 272 */
129 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 273 uint32_t attr_len GNUNET_PACKED;
130 274
275 //Followed by a serialized attribute list
276};
277
278/**
279 * Ticket revoke message
280 */
281struct RevokeTicketMessage
282{
131 /** 283 /**
132 * Nonce 284 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET
133 */ 285 */
134 uint64_t nonce; 286 struct GNUNET_MessageHeader header;
135 287
136 /** 288 /**
137 * Expiration of token in NBO. 289 * Unique identifier for this request (for key collisions).
138 */ 290 */
139 struct GNUNET_TIME_AbsoluteNBO expiration; 291 uint32_t id GNUNET_PACKED;
140 292
293 /**
294 * Identity.
295 */
296 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
141 297
142 /* followed by 0-terminated comma-separated scope list */ 298 /**
299 * length of serialized attribute list
300 */
301 uint32_t attrs_len GNUNET_PACKED;
143 302
303 //Followed by a ticket and serialized attribute list
304};
305
306/**
307 * Ticket revoke message
308 */
309struct RevokeTicketResultMessage
310{
311 /**
312 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
313 */
314 struct GNUNET_MessageHeader header;
315
316 /**
317 * Unique identifier for this request (for key collisions).
318 */
319 uint32_t id GNUNET_PACKED;
320
321 /**
322 * Revocation result
323 */
324 uint32_t success GNUNET_PACKED;
144}; 325};
145 326
146 327
147/** 328/**
148 * Use to exchange a ticket for a token 329 * Ticket result message
149 */ 330 */
150struct ExchangeMessage 331struct TicketResultMessage
151{ 332{
152 /** 333 /**
153 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT 334 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
335 */
336 struct GNUNET_MessageHeader header;
337
338 /**
339 * Unique identifier for this request (for key collisions).
340 */
341 uint32_t id GNUNET_PACKED;
342
343};
344
345/**
346 * Ticket consume message
347 */
348struct ConsumeTicketMessage
349{
350 /**
351 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET
154 */ 352 */
155 struct GNUNET_MessageHeader header; 353 struct GNUNET_MessageHeader header;
156 354
@@ -160,15 +358,50 @@ struct ExchangeMessage
160 uint32_t id GNUNET_PACKED; 358 uint32_t id GNUNET_PACKED;
161 359
162 /** 360 /**
163 * Audience identity private key 361 * Identity.
362 */
363 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
364
365 //Followed by a serialized ticket
366};
367
368/**
369 * Attribute list is returned from the idp.
370 */
371struct ConsumeTicketResultMessage
372{
373 /**
374 * Message header
375 */
376 struct GNUNET_MessageHeader header;
377
378 /**
379 * Unique identifier for this request (for key collisions).
380 */
381 uint32_t id GNUNET_PACKED;
382
383 /**
384 * Length of serialized attribute data
164 */ 385 */
165 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey; 386 uint16_t attrs_len GNUNET_PACKED;
166 387
167 /* followed by 0-terminated ticket string */ 388 /**
389 * always zero (for alignment)
390 */
391 uint16_t reserved GNUNET_PACKED;
168 392
393 /**
394 * The public key of the identity.
395 */
396 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
397
398 /* followed by:
399 * serialized attributes data
400 */
169}; 401};
170 402
171 403
404
172GNUNET_NETWORK_STRUCT_END 405GNUNET_NETWORK_STRUCT_END
173 406
174#endif 407#endif
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c
index 845d1f753..d0ece80fe 100644
--- a/src/identity-provider/identity_provider_api.c
+++ b/src/identity-provider/identity_provider_api.c
@@ -29,12 +29,12 @@
29#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "gnunet_mq_lib.h" 30#include "gnunet_mq_lib.h"
31#include "gnunet_identity_provider_service.h" 31#include "gnunet_identity_provider_service.h"
32#include "gnunet_identity_attribute_lib.h"
32#include "identity_provider.h" 33#include "identity_provider.h"
33 34
34#define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) 35#define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__)
35 36
36 37
37
38/** 38/**
39 * Handle for an operation with the service. 39 * Handle for an operation with the service.
40 */ 40 */
@@ -63,16 +63,24 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
63 const struct GNUNET_MessageHeader *msg; 63 const struct GNUNET_MessageHeader *msg;
64 64
65 /** 65 /**
66 * Continuation to invoke with the result of the transmission; @e cb 66 * Continuation to invoke after attribute store call
67 * will be NULL in this case. 67 */
68 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb;
69
70 /**
71 * Attribute result callback
72 */
73 GNUNET_IDENTITY_PROVIDER_AttributeResult ar_cb;
74
75 /**
76 * Revocation result callback
68 */ 77 */
69 GNUNET_IDENTITY_PROVIDER_ExchangeCallback ex_cb; 78 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus rvk_cb;
70 79
71 /** 80 /**
72 * Continuation to invoke with the result of the transmission for 81 * Ticket result callback
73 * 'issue' operations (@e cont will be NULL in this case).
74 */ 82 */
75 GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb; 83 GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
76 84
77 /** 85 /**
78 * Envelope with the message for this queue entry. 86 * Envelope with the message for this queue entry.
@@ -91,6 +99,140 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
91 99
92}; 100};
93 101
102/**
103 * Handle for a ticket iterator operation
104 */
105struct GNUNET_IDENTITY_PROVIDER_TicketIterator
106{
107
108 /**
109 * Kept in a DLL.
110 */
111 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *next;
112
113 /**
114 * Kept in a DLL.
115 */
116 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *prev;
117
118 /**
119 * Main handle to access the idp.
120 */
121 struct GNUNET_IDENTITY_PROVIDER_Handle *h;
122
123 /**
124 * Function to call on completion.
125 */
126 GNUNET_SCHEDULER_TaskCallback finish_cb;
127
128 /**
129 * Closure for @e error_cb.
130 */
131 void *finish_cb_cls;
132
133 /**
134 * The continuation to call with the results
135 */
136 GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
137
138 /**
139 * Closure for @e tr_cb.
140 */
141 void *cls;
142
143 /**
144 * Function to call on errors.
145 */
146 GNUNET_SCHEDULER_TaskCallback error_cb;
147
148 /**
149 * Closure for @e error_cb.
150 */
151 void *error_cb_cls;
152
153 /**
154 * Envelope of the message to send to the service, if not yet
155 * sent.
156 */
157 struct GNUNET_MQ_Envelope *env;
158
159 /**
160 * The operation id this zone iteration operation has
161 */
162 uint32_t r_id;
163
164};
165
166
167/**
168 * Handle for a attribute iterator operation
169 */
170struct GNUNET_IDENTITY_PROVIDER_AttributeIterator
171{
172
173 /**
174 * Kept in a DLL.
175 */
176 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next;
177
178 /**
179 * Kept in a DLL.
180 */
181 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev;
182
183 /**
184 * Main handle to access the idp.
185 */
186 struct GNUNET_IDENTITY_PROVIDER_Handle *h;
187
188 /**
189 * Function to call on completion.
190 */
191 GNUNET_SCHEDULER_TaskCallback finish_cb;
192
193 /**
194 * Closure for @e error_cb.
195 */
196 void *finish_cb_cls;
197
198 /**
199 * The continuation to call with the results
200 */
201 GNUNET_IDENTITY_PROVIDER_AttributeResult proc;
202
203 /**
204 * Closure for @e proc.
205 */
206 void *proc_cls;
207
208 /**
209 * Function to call on errors.
210 */
211 GNUNET_SCHEDULER_TaskCallback error_cb;
212
213 /**
214 * Closure for @e error_cb.
215 */
216 void *error_cb_cls;
217
218 /**
219 * Envelope of the message to send to the service, if not yet
220 * sent.
221 */
222 struct GNUNET_MQ_Envelope *env;
223
224 /**
225 * Private key of the zone.
226 */
227 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
228
229 /**
230 * The operation id this zone iteration operation has
231 */
232 uint32_t r_id;
233
234};
235
94 236
95/** 237/**
96 * Handle for the service. 238 * Handle for the service.
@@ -123,6 +265,27 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
123 struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail; 265 struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail;
124 266
125 /** 267 /**
268 * Head of active iterations
269 */
270 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head;
271
272 /**
273 * Tail of active iterations
274 */
275 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail;
276
277 /**
278 * Head of active iterations
279 */
280 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_head;
281
282 /**
283 * Tail of active iterations
284 */
285 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_tail;
286
287
288 /**
126 * Currently pending transmission request, or NULL for none. 289 * Currently pending transmission request, or NULL for none.
127 */ 290 */
128 struct GNUNET_CLIENT_TransmitHandle *th; 291 struct GNUNET_CLIENT_TransmitHandle *th;
@@ -154,14 +317,13 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
154 317
155}; 318};
156 319
157
158/** 320/**
159 * Try again to connect to the service. 321 * Try again to connect to the service.
160 * 322 *
161 * @param cls handle to the service. 323 * @param h handle to the identity provider service.
162 */ 324 */
163static void 325static void
164reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle); 326reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
165 327
166/** 328/**
167 * Reconnect 329 * Reconnect
@@ -181,7 +343,7 @@ reconnect_task (void *cls)
181/** 343/**
182 * Disconnect from service and then reconnect. 344 * Disconnect from service and then reconnect.
183 * 345 *
184 * @param handle our handle 346 * @param handle our service
185 */ 347 */
186static void 348static void
187force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle) 349force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
@@ -197,6 +359,26 @@ force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
197} 359}
198 360
199/** 361/**
362 * Free @a it.
363 *
364 * @param it entry to free
365 */
366static void
367free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
368{
369 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
370
371 GNUNET_CONTAINER_DLL_remove (h->it_head,
372 h->it_tail,
373 it);
374 if (NULL != it->env)
375 GNUNET_MQ_discard (it->env);
376 GNUNET_free (it);
377}
378
379
380
381/**
200 * Generic error handler, called with the appropriate error code and 382 * Generic error handler, called with the appropriate error code and
201 * the same closure specified at the creation of the message queue. 383 * the same closure specified at the creation of the message queue.
202 * Not every message queue implementation supports an error handler. 384 * Not every message queue implementation supports an error handler.
@@ -213,22 +395,68 @@ mq_error_handler (void *cls,
213} 395}
214 396
215/** 397/**
216 * Check validity of message received from the service 398 * Handle an incoming message of type
399 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
400 *
401 * @param cls
402 * @param msg the message we received
403 */
404static void
405handle_attribute_store_response (void *cls,
406 const struct AttributeStoreResultMessage *msg)
407{
408 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
409 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
410 uint32_t r_id = ntohl (msg->id);
411 int res;
412 const char *emsg;
413
414 for (op = h->op_head; NULL != op; op = op->next)
415 if (op->r_id == r_id)
416 break;
417 if (NULL == op)
418 return;
419
420 res = ntohl (msg->op_result);
421 LOG (GNUNET_ERROR_TYPE_DEBUG,
422 "Received ATTRIBUTE_STORE_RESPONSE with result %d\n",
423 res);
424
425 /* TODO: add actual error message to response... */
426 if (GNUNET_SYSERR == res)
427 emsg = _("failed to store record\n");
428 else
429 emsg = NULL;
430 if (NULL != op->as_cb)
431 op->as_cb (op->cls,
432 res,
433 emsg);
434 GNUNET_CONTAINER_DLL_remove (h->op_head,
435 h->op_tail,
436 op);
437 GNUNET_free (op);
438
439}
440
441
442/**
443 * Handle an incoming message of type
444 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
217 * 445 *
218 * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` 446 * @param cls
219 * @param result_msg the incoming message 447 * @param msg the message we received
448 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
220 */ 449 */
221static int 450static int
222check_exchange_result (void *cls, 451check_consume_ticket_result (void *cls,
223 const struct ExchangeResultMessage *erm) 452 const struct ConsumeTicketResultMessage *msg)
224{ 453{
225 char *str; 454 size_t msg_len;
226 size_t size = ntohs (erm->header.size) - sizeof (*erm); 455 size_t attrs_len;
227
228 456
229 str = (char *) &erm[1]; 457 msg_len = ntohs (msg->header.size);
230 if ( (size > sizeof (struct ExchangeResultMessage)) && 458 attrs_len = ntohs (msg->attrs_len);
231 ('\0' != str[size - sizeof (struct ExchangeResultMessage) - 1]) ) 459 if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len)
232 { 460 {
233 GNUNET_break (0); 461 GNUNET_break (0);
234 return GNUNET_SYSERR; 462 return GNUNET_SYSERR;
@@ -238,20 +466,85 @@ check_exchange_result (void *cls,
238 466
239 467
240/** 468/**
241 * Check validity of message received from the service 469 * Handle an incoming message of type
470 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
471 *
472 * @param cls
473 * @param msg the message we received
474 */
475static void
476handle_consume_ticket_result (void *cls,
477 const struct ConsumeTicketResultMessage *msg)
478{
479 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
480 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
481 size_t attrs_len;
482 uint32_t r_id = ntohl (msg->id);
483
484 attrs_len = ntohs (msg->attrs_len);
485 LOG (GNUNET_ERROR_TYPE_DEBUG,
486 "Processing attribute result.\n");
487
488
489 for (op = h->op_head; NULL != op; op = op->next)
490 if (op->r_id == r_id)
491 break;
492 if (NULL == op)
493 return;
494
495 {
496 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
497 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
498 attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1],
499 attrs_len);
500 if (NULL != op->ar_cb)
501 {
502 if (NULL == attrs)
503 {
504 op->ar_cb (op->cls,
505 &msg->identity,
506 NULL);
507 }
508 else
509 {
510 for (le = attrs->list_head; NULL != le; le = le->next)
511 op->ar_cb (op->cls,
512 &msg->identity,
513 le->claim);
514 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
515 }
516 }
517 op->ar_cb (op->cls,
518 NULL,
519 NULL);
520 GNUNET_CONTAINER_DLL_remove (h->op_head,
521 h->op_tail,
522 op);
523 GNUNET_free (op);
524 return;
525 }
526 GNUNET_assert (0);
527}
528
529
530/**
531 * Handle an incoming message of type
532 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
242 * 533 *
243 * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` 534 * @param cls
244 * @param result_msg the incoming message 535 * @param msg the message we received
536 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
245 */ 537 */
246static int 538static int
247check_result (void *cls, 539check_attribute_result (void *cls,
248 const struct IssueResultMessage *irm) 540 const struct AttributeResultMessage *msg)
249{ 541{
250 char *str; 542 size_t msg_len;
251 size_t size = ntohs (irm->header.size) - sizeof (*irm); 543 size_t attr_len;
252 str = (char*) &irm[1]; 544
253 if ( (size > sizeof (struct IssueResultMessage)) && 545 msg_len = ntohs (msg->header.size);
254 ('\0' != str[size - sizeof (struct IssueResultMessage) - 1]) ) 546 attr_len = ntohs (msg->attr_len);
547 if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
255 { 548 {
256 GNUNET_break (0); 549 GNUNET_break (0);
257 return GNUNET_SYSERR; 550 return GNUNET_SYSERR;
@@ -259,119 +552,254 @@ check_result (void *cls,
259 return GNUNET_OK; 552 return GNUNET_OK;
260} 553}
261 554
555
262/** 556/**
263 * Handler for messages received from the GNS service 557 * Handle an incoming message of type
558 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
264 * 559 *
265 * @param cls the `struct GNUNET_GNS_Handle *` 560 * @param cls
266 * @param loookup_msg the incoming message 561 * @param msg the message we received
267 */ 562 */
268static void 563static void
269handle_exchange_result (void *cls, 564handle_attribute_result (void *cls,
270 const struct ExchangeResultMessage *erm) 565 const struct AttributeResultMessage *msg)
271{ 566{
272 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; 567 static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
568 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
569 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
273 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 570 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
274 struct GNUNET_IDENTITY_PROVIDER_Token token; 571 size_t attr_len;
275 uint64_t ticket_nonce; 572 uint32_t r_id = ntohl (msg->id);
276 uint32_t r_id = ntohl (erm->id); 573
277 char *str; 574 attr_len = ntohs (msg->attr_len);
278 575 LOG (GNUNET_ERROR_TYPE_DEBUG,
279 for (op = handle->op_head; NULL != op; op = op->next) 576 "Processing attribute result.\n");
577
578
579 for (it = h->it_head; NULL != it; it = it->next)
580 if (it->r_id == r_id)
581 break;
582 for (op = h->op_head; NULL != op; op = op->next)
280 if (op->r_id == r_id) 583 if (op->r_id == r_id)
281 break; 584 break;
282 if (NULL == op) 585 if ((NULL == it) && (NULL == op))
283 return; 586 return;
284 str = GNUNET_strdup ((char*)&erm[1]);
285 op = handle->op_head;
286 GNUNET_CONTAINER_DLL_remove (handle->op_head,
287 handle->op_tail,
288 op);
289 token.data = str;
290 ticket_nonce = ntohl (erm->ticket_nonce);
291 if (NULL != op->ex_cb)
292 op->ex_cb (op->cls, &token, ticket_nonce);
293 GNUNET_free (str);
294 GNUNET_free (op);
295 587
588 if ( (0 == (memcmp (&msg->identity,
589 &identity_dummy,
590 sizeof (identity_dummy)))) )
591 {
592 if ((NULL == it) && (NULL == op))
593 {
594 GNUNET_break (0);
595 force_reconnect (h);
596 return;
597 }
598 if (NULL != it)
599 {
600 if (NULL != it->finish_cb)
601 it->finish_cb (it->finish_cb_cls);
602 free_it (it);
603 }
604 if (NULL != op)
605 {
606 if (NULL != op->ar_cb)
607 op->ar_cb (op->cls,
608 NULL,
609 NULL);
610 GNUNET_CONTAINER_DLL_remove (h->op_head,
611 h->op_tail,
612 op);
613 GNUNET_free (op);
614
615 }
616 return;
617 }
618
619 {
620 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
621 attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1],
622 attr_len);
623 if (NULL != it)
624 {
625 if (NULL != it->proc)
626 it->proc (it->proc_cls,
627 &msg->identity,
628 attr);
629 } else if (NULL != op)
630 {
631 if (NULL != op->ar_cb)
632 op->ar_cb (op->cls,
633 &msg->identity,
634 attr);
635
636 }
637 GNUNET_free (attr);
638 return;
639 }
640 GNUNET_assert (0);
641}
642
643/**
644 * Handle an incoming message of type
645 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
646 *
647 * @param cls
648 * @param msg the message we received
649 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
650 */
651static int
652check_ticket_result (void *cls,
653 const struct TicketResultMessage *msg)
654{
655 size_t msg_len;
656
657 msg_len = ntohs (msg->header.size);
658 if (msg_len < sizeof (struct TicketResultMessage))
659 {
660 GNUNET_break (0);
661 return GNUNET_SYSERR;
662 }
663 return GNUNET_OK;
296} 664}
297 665
666
667
298/** 668/**
299 * Handler for messages received from the GNS service 669 * Handle an incoming message of type
670 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
300 * 671 *
301 * @param cls the `struct GNUNET_GNS_Handle *` 672 * @param cls
302 * @param loookup_msg the incoming message 673 * @param msg the message we received
303 */ 674 */
304static void 675static void
305handle_result (void *cls, 676handle_ticket_result (void *cls,
306 const struct IssueResultMessage *irm) 677 const struct TicketResultMessage *msg)
307{ 678{
308 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; 679 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
309 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 680 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
310 struct GNUNET_IDENTITY_PROVIDER_Token token; 681 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
311 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; 682 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
312 uint32_t r_id = ntohl (irm->id); 683 uint32_t r_id = ntohl (msg->id);
313 char *str; 684 size_t msg_len;
314 char *label_str;
315 char *ticket_str;
316 char *token_str;
317 685
318 for (op = handle->op_head; NULL != op; op = op->next) 686 for (op = handle->op_head; NULL != op; op = op->next)
319 if (op->r_id == r_id) 687 if (op->r_id == r_id)
320 break; 688 break;
321 if (NULL == op) 689 for (it = handle->ticket_it_head; NULL != it; it = it->next)
690 if (it->r_id == r_id)
691 break;
692 if ((NULL == op) && (NULL == it))
322 return; 693 return;
323 str = GNUNET_strdup ((char*)&irm[1]); 694 msg_len = ntohs (msg->header.size);
324 label_str = strtok (str, ","); 695 if (NULL != op)
325
326 if (NULL == label_str)
327 { 696 {
328 GNUNET_free (str); 697 GNUNET_CONTAINER_DLL_remove (handle->op_head,
329 GNUNET_break (0); 698 handle->op_tail,
699 op);
700 if (msg_len == sizeof (struct TicketResultMessage))
701 {
702 if (NULL != op->tr_cb)
703 op->tr_cb (op->cls, NULL);
704 } else {
705 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
706 if (NULL != op->tr_cb)
707 op->tr_cb (op->cls, ticket);
708 }
709 GNUNET_free (op);
330 return; 710 return;
331 } 711 } else if (NULL != it) {
332 ticket_str = strtok (NULL, ","); 712 if (msg_len == sizeof (struct TicketResultMessage))
333 if (NULL == ticket_str) 713 {
334 { 714 if (NULL != it->tr_cb)
335 GNUNET_free (str); 715 GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
336 GNUNET_break (0); 716 handle->ticket_it_tail,
717 it);
718 it->finish_cb (it->finish_cb_cls);
719 GNUNET_free (it);
720 } else {
721 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
722 if (NULL != it->tr_cb)
723 it->tr_cb (it->cls, ticket);
724 }
337 return; 725 return;
338 } 726 }
339 token_str = strtok (NULL, ","); 727 GNUNET_break (0);
340 if (NULL == token_str) 728}
729
730/**
731 * Handle an incoming message of type
732 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
733 *
734 * @param cls
735 * @param msg the message we received
736 */
737static void
738handle_revoke_ticket_result (void *cls,
739 const struct RevokeTicketResultMessage *msg)
740{
741 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
742 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
743 uint32_t r_id = ntohl (msg->id);
744 int32_t success;
745
746 LOG (GNUNET_ERROR_TYPE_DEBUG,
747 "Processing revocation result.\n");
748
749
750 for (op = h->op_head; NULL != op; op = op->next)
751 if (op->r_id == r_id)
752 break;
753 if (NULL == op)
754 return;
755 success = ntohl (msg->success);
341 { 756 {
342 GNUNET_free (str); 757 if (NULL != op->rvk_cb)
343 GNUNET_break (0); 758 {
759 op->rvk_cb (op->cls,
760 success,
761 NULL);
762 }
763 GNUNET_CONTAINER_DLL_remove (h->op_head,
764 h->op_tail,
765 op);
766 GNUNET_free (op);
344 return; 767 return;
345 } 768 }
346 GNUNET_CONTAINER_DLL_remove (handle->op_head, 769 GNUNET_assert (0);
347 handle->op_tail,
348 op);
349 ticket.data = ticket_str;
350 token.data = token_str;
351 if (NULL != op->iss_cb)
352 op->iss_cb (op->cls, label_str, &ticket, &token);
353 GNUNET_free (str);
354 GNUNET_free (op);
355
356} 770}
357 771
772
773
358/** 774/**
359 * Try again to connect to the service. 775 * Try again to connect to the service.
360 * 776 *
361 * @param cls handle to the identity provider service. 777 * @param h handle to the identity provider service.
362 */ 778 */
363static void 779static void
364reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) 780reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
365{ 781{
366 struct GNUNET_MQ_MessageHandler handlers[] = { 782 struct GNUNET_MQ_MessageHandler handlers[] = {
367 GNUNET_MQ_hd_var_size (result, 783 GNUNET_MQ_hd_fixed_size (attribute_store_response,
368 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT, 784 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE,
369 struct IssueResultMessage, 785 struct AttributeStoreResultMessage,
786 h),
787 GNUNET_MQ_hd_var_size (attribute_result,
788 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT,
789 struct AttributeResultMessage,
370 h), 790 h),
371 GNUNET_MQ_hd_var_size (exchange_result, 791 GNUNET_MQ_hd_var_size (ticket_result,
372 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT, 792 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT,
373 struct ExchangeResultMessage, 793 struct TicketResultMessage,
374 h), 794 h),
795 GNUNET_MQ_hd_var_size (consume_ticket_result,
796 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT,
797 struct ConsumeTicketResultMessage,
798 h),
799 GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
800 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT,
801 struct RevokeTicketResultMessage,
802 h),
375 GNUNET_MQ_handler_end () 803 GNUNET_MQ_handler_end ()
376 }; 804 };
377 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 805 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
@@ -417,111 +845,6 @@ GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
417 845
418 846
419/** 847/**
420 * Issue an identity token
421 *
422 * @param id identity service to query
423 * @param service_name for which service is an identity wanted
424 * @param cb function to call with the result (will only be called once)
425 * @param cb_cls closure for @a cb
426 * @return handle to abort the operation
427 */
428struct GNUNET_IDENTITY_PROVIDER_Operation *
429GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
430 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
431 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
432 const char* scopes,
433 struct GNUNET_TIME_Absolute expiration,
434 uint64_t nonce,
435 GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
436 void *cb_cls)
437{
438 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
439 struct IssueMessage *im;
440 size_t slen;
441
442 slen = strlen (scopes) + 1;
443 if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct IssueMessage))
444 {
445 GNUNET_break (0);
446 return NULL;
447 }
448 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
449 op->h = id;
450 op->iss_cb = cb;
451 op->cls = cb_cls;
452 op->r_id = id->r_id_gen++;
453 op->env = GNUNET_MQ_msg_extra (im,
454 slen,
455 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE);
456 im->id = op->r_id;
457 im->iss_key = *iss_key;
458 im->aud_key = *aud_key;
459 im->nonce = htonl (nonce);
460 im->expiration = GNUNET_TIME_absolute_hton (expiration);
461 GNUNET_memcpy (&im[1], scopes, slen);
462 GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
463 id->op_tail,
464 op);
465 if (NULL != id->mq)
466 GNUNET_MQ_send_copy (id->mq,
467 op->env);
468 return op;
469}
470
471
472/**
473 * Exchange a token ticket for a token
474 *
475 * @param id identity provider service
476 * @param ticket ticket to exchange
477 * @param cont function to call once the operation finished
478 * @param cont_cls closure for @a cont
479 * @return handle to abort the operation
480 */
481struct GNUNET_IDENTITY_PROVIDER_Operation *
482GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
483 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
484 const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey,
485 GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
486 void *cont_cls)
487{
488 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
489 struct ExchangeMessage *em;
490 size_t slen;
491 char *ticket_str;
492
493 ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
494
495 slen = strlen (ticket_str) + 1;
496 if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct ExchangeMessage))
497 {
498 GNUNET_free (ticket_str);
499 GNUNET_break (0);
500 return NULL;
501 }
502 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
503 op->h = id;
504 op->ex_cb = cont;
505 op->cls = cont_cls;
506 op->r_id = id->r_id_gen++;
507 op->env = GNUNET_MQ_msg_extra (em,
508 slen,
509 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE);
510 em->aud_privkey = *aud_privkey;
511 em->id = htonl (op->r_id);
512 GNUNET_memcpy (&em[1], ticket_str, slen);
513 GNUNET_free (ticket_str);
514 GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
515 id->op_tail,
516 op);
517 if (NULL != id->mq)
518 GNUNET_MQ_send_copy (id->mq,
519 op->env);
520 return op;
521}
522
523
524/**
525 * Cancel an operation. Note that the operation MAY still 848 * Cancel an operation. Note that the operation MAY still
526 * be executed; this merely cancels the continuation; if the request 849 * be executed; this merely cancels the continuation; if the request
527 * was already transmitted, the service may still choose to complete 850 * was already transmitted, the service may still choose to complete
@@ -566,80 +889,482 @@ GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
566} 889}
567 890
568/** 891/**
569 * Convenience API 892 * Store an attribute. If the attribute is already present,
893 * it is replaced with the new attribute.
894 *
895 * @param h handle to the identity provider
896 * @param pkey private key of the identity
897 * @param attr the attribute value
898 * @param cont continuation to call when done
899 * @param cont_cls closure for @a cont
900 * @return handle to abort the request
570 */ 901 */
902struct GNUNET_IDENTITY_PROVIDER_Operation *
903GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
904 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
905 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
906 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
907 void *cont_cls)
908{
909 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
910 struct AttributeStoreMessage *sam;
911 size_t attr_len;
912
913 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
914 op->h = h;
915 op->as_cb = cont;
916 op->cls = cont_cls;
917 op->r_id = h->r_id_gen++;
918 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
919 h->op_tail,
920 op);
921 attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr);
922 op->env = GNUNET_MQ_msg_extra (sam,
923 attr_len,
924 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE);
925 sam->identity = *pkey;
926 sam->id = htonl (op->r_id);
927
928 GNUNET_IDENTITY_ATTRIBUTE_serialize (attr,
929 (char*)&sam[1]);
930
931 sam->attr_len = htons (attr_len);
932 if (NULL != h->mq)
933 GNUNET_MQ_send_copy (h->mq,
934 op->env);
935 return op;
936
937}
938
939
940/**
941 * List all attributes for a local identity.
942 * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
943 * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
944 * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
945 * immediately, and then again after
946 * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
947 *
948 * On error (disconnect), @a error_cb will be invoked.
949 * On normal completion, @a finish_cb proc will be
950 * invoked.
951 *
952 * @param h handle to the idp
953 * @param identity identity to access
954 * @param error_cb function to call on error (i.e. disconnect),
955 * the handle is afterwards invalid
956 * @param error_cb_cls closure for @a error_cb
957 * @param proc function to call on each attribute; it
958 * will be called repeatedly with a value (if available)
959 * @param proc_cls closure for @a proc
960 * @param finish_cb function to call on completion
961 * the handle is afterwards invalid
962 * @param finish_cb_cls closure for @a finish_cb
963 * @return an iterator handle to use for iteration
964 */
965struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
966GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
967 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
968 GNUNET_SCHEDULER_TaskCallback error_cb,
969 void *error_cb_cls,
970 GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
971 void *proc_cls,
972 GNUNET_SCHEDULER_TaskCallback finish_cb,
973 void *finish_cb_cls)
974{
975 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
976 struct GNUNET_MQ_Envelope *env;
977 struct AttributeIterationStartMessage *msg;
978 uint32_t rid;
979
980 rid = h->r_id_gen++;
981 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator);
982 it->h = h;
983 it->error_cb = error_cb;
984 it->error_cb_cls = error_cb_cls;
985 it->finish_cb = finish_cb;
986 it->finish_cb_cls = finish_cb_cls;
987 it->proc = proc;
988 it->proc_cls = proc_cls;
989 it->r_id = rid;
990 it->identity = *identity;
991 GNUNET_CONTAINER_DLL_insert_tail (h->it_head,
992 h->it_tail,
993 it);
994 env = GNUNET_MQ_msg (msg,
995 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START);
996 msg->id = htonl (rid);
997 msg->identity = *identity;
998 if (NULL == h->mq)
999 it->env = env;
1000 else
1001 GNUNET_MQ_send (h->mq,
1002 env);
1003 return it;
1004}
571 1005
572 1006
573/** 1007/**
574 * Destroy token 1008 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
1009 * for the next record.
575 * 1010 *
576 * @param token the token 1011 * @param it the iterator
577 */ 1012 */
578void 1013void
579GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token) 1014GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
1015{
1016 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
1017 struct AttributeIterationNextMessage *msg;
1018 struct GNUNET_MQ_Envelope *env;
1019
1020 env = GNUNET_MQ_msg (msg,
1021 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT);
1022 msg->id = htonl (it->r_id);
1023 GNUNET_MQ_send (h->mq,
1024 env);
1025}
1026
1027
1028/**
1029 * Stops iteration and releases the idp handle for further calls. Must
1030 * be called on any iteration that has not yet completed prior to calling
1031 * #GNUNET_IDENTITY_PROVIDER_disconnect.
1032 *
1033 * @param it the iterator
1034 */
1035void
1036GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
1037{
1038 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
1039 struct GNUNET_MQ_Envelope *env;
1040 struct AttributeIterationStopMessage *msg;
1041
1042 if (NULL != h->mq)
1043 {
1044 env = GNUNET_MQ_msg (msg,
1045 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP);
1046 msg->id = htonl (it->r_id);
1047 GNUNET_MQ_send (h->mq,
1048 env);
1049 }
1050 free_it (it);
1051}
1052
1053
1054/** TODO
1055 * Issues a ticket to another identity. The identity may use
1056 * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
1057 * and retrieve the attributes specified in the AttributeList.
1058 *
1059 * @param h the identity provider to use
1060 * @param iss the issuing identity
1061 * @param rp the subject of the ticket (the relying party)
1062 * @param attrs the attributes that the relying party is given access to
1063 * @param cb the callback
1064 * @param cb_cls the callback closure
1065 * @return handle to abort the operation
1066 */
1067struct GNUNET_IDENTITY_PROVIDER_Operation *
1068GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1069 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
1070 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
1071 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
1072 GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
1073 void *cb_cls)
1074{
1075 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
1076 struct IssueTicketMessage *tim;
1077 size_t attr_len;
1078
1079 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1080 op->h = h;
1081 op->tr_cb = cb;
1082 op->cls = cb_cls;
1083 op->r_id = h->r_id_gen++;
1084 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1085 h->op_tail,
1086 op);
1087 attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
1088 op->env = GNUNET_MQ_msg_extra (tim,
1089 attr_len,
1090 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET);
1091 tim->identity = *iss;
1092 tim->rp = *rp;
1093 tim->id = htonl (op->r_id);
1094
1095 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
1096 (char*)&tim[1]);
1097
1098 tim->attr_len = htons (attr_len);
1099 if (NULL != h->mq)
1100 GNUNET_MQ_send_copy (h->mq,
1101 op->env);
1102 return op;
1103}
1104
1105/**
1106 * Consumes an issued ticket. The ticket is persisted
1107 * and used to retrieve identity information from the issuer
1108 *
1109 * @param h the identity provider to use
1110 * @param identity the identity that is the subject of the issued ticket (the relying party)
1111 * @param ticket the issued ticket to consume
1112 * @param cb the callback to call
1113 * @param cb_cls the callback closure
1114 * @return handle to abort the operation
1115 */
1116struct GNUNET_IDENTITY_PROVIDER_Operation *
1117GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1118 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1119 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1120 GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
1121 void *cb_cls)
580{ 1122{
581 GNUNET_assert (NULL != token); 1123 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
582 if (NULL != token->data) 1124 struct ConsumeTicketMessage *ctm;
583 GNUNET_free (token->data); 1125
584 GNUNET_free (token); 1126 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1127 op->h = h;
1128 op->ar_cb = cb;
1129 op->cls = cb_cls;
1130 op->r_id = h->r_id_gen++;
1131 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1132 h->op_tail,
1133 op);
1134 op->env = GNUNET_MQ_msg_extra (ctm,
1135 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket),
1136 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET);
1137 ctm->identity = *identity;
1138 ctm->id = htonl (op->r_id);
1139
1140 GNUNET_memcpy ((char*)&ctm[1],
1141 ticket,
1142 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket));
1143
1144 if (NULL != h->mq)
1145 GNUNET_MQ_send_copy (h->mq,
1146 op->env);
1147 return op;
1148
585} 1149}
586 1150
1151
587/** 1152/**
588 * Returns string representation of token. A JSON-Web-Token. 1153 * Lists all tickets that have been issued to remote
1154 * identites (relying parties)
589 * 1155 *
590 * @param token the token 1156 * @param h the identity provider to use
591 * @return The JWT (must be freed) 1157 * @param identity the issuing identity
1158 * @param error_cb function to call on error (i.e. disconnect),
1159 * the handle is afterwards invalid
1160 * @param error_cb_cls closure for @a error_cb
1161 * @param proc function to call on each ticket; it
1162 * will be called repeatedly with a value (if available)
1163 * @param proc_cls closure for @a proc
1164 * @param finish_cb function to call on completion
1165 * the handle is afterwards invalid
1166 * @param finish_cb_cls closure for @a finish_cb
1167 * @return an iterator handle to use for iteration
592 */ 1168 */
593char * 1169struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
594GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token) 1170GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1171 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1172 GNUNET_SCHEDULER_TaskCallback error_cb,
1173 void *error_cb_cls,
1174 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
1175 void *proc_cls,
1176 GNUNET_SCHEDULER_TaskCallback finish_cb,
1177 void *finish_cb_cls)
595{ 1178{
596 return GNUNET_strdup (token->data); 1179 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
1180 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
1181 struct GNUNET_MQ_Envelope *env;
1182 struct TicketIterationStartMessage *msg;
1183 uint32_t rid;
1184
1185 GNUNET_CRYPTO_ecdsa_key_get_public (identity,
1186 &identity_pub);
1187 rid = h->r_id_gen++;
1188 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
1189 it->h = h;
1190 it->error_cb = error_cb;
1191 it->error_cb_cls = error_cb_cls;
1192 it->finish_cb = finish_cb;
1193 it->finish_cb_cls = finish_cb_cls;
1194 it->tr_cb = proc;
1195 it->cls = proc_cls;
1196 it->r_id = rid;
1197 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
1198 h->ticket_it_tail,
1199 it);
1200 env = GNUNET_MQ_msg (msg,
1201 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
1202 msg->id = htonl (rid);
1203 msg->identity = identity_pub;
1204 msg->is_audience = htonl (GNUNET_NO);
1205 if (NULL == h->mq)
1206 it->env = env;
1207 else
1208 GNUNET_MQ_send (h->mq,
1209 env);
1210 return it;
1211
597} 1212}
598 1213
1214
599/** 1215/**
600 * Returns string representation of ticket. Base64-Encoded 1216 * Lists all tickets that have been issued to remote
1217 * identites (relying parties)
601 * 1218 *
602 * @param ticket the ticket 1219 * @param h the identity provider to use
603 * @return the Base64-Encoded ticket 1220 * @param identity the issuing identity
1221 * @param error_cb function to call on error (i.e. disconnect),
1222 * the handle is afterwards invalid
1223 * @param error_cb_cls closure for @a error_cb
1224 * @param proc function to call on each ticket; it
1225 * will be called repeatedly with a value (if available)
1226 * @param proc_cls closure for @a proc
1227 * @param finish_cb function to call on completion
1228 * the handle is afterwards invalid
1229 * @param finish_cb_cls closure for @a finish_cb
1230 * @return an iterator handle to use for iteration
604 */ 1231 */
605char * 1232struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
606GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) 1233GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1234 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1235 GNUNET_SCHEDULER_TaskCallback error_cb,
1236 void *error_cb_cls,
1237 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
1238 void *proc_cls,
1239 GNUNET_SCHEDULER_TaskCallback finish_cb,
1240 void *finish_cb_cls)
607{ 1241{
608 return GNUNET_strdup (ticket->data); 1242 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
1243 struct GNUNET_MQ_Envelope *env;
1244 struct TicketIterationStartMessage *msg;
1245 uint32_t rid;
1246
1247 rid = h->r_id_gen++;
1248 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
1249 it->h = h;
1250 it->error_cb = error_cb;
1251 it->error_cb_cls = error_cb_cls;
1252 it->finish_cb = finish_cb;
1253 it->finish_cb_cls = finish_cb_cls;
1254 it->tr_cb = proc;
1255 it->cls = proc_cls;
1256 it->r_id = rid;
1257 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
1258 h->ticket_it_tail,
1259 it);
1260 env = GNUNET_MQ_msg (msg,
1261 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
1262 msg->id = htonl (rid);
1263 msg->identity = *identity;
1264 msg->is_audience = htonl (GNUNET_YES);
1265 if (NULL == h->mq)
1266 it->env = env;
1267 else
1268 GNUNET_MQ_send (h->mq,
1269 env);
1270 return it;
1271
1272
609} 1273}
610 1274
611/** 1275/**
612 * Created a ticket from a string (Base64 encoded ticket) 1276 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
1277 * for the next record.
613 * 1278 *
614 * @param input Base64 encoded ticket 1279 * @param it the iterator
615 * @param ticket pointer where the ticket is stored
616 * @return GNUNET_OK
617 */ 1280 */
618int 1281void
619GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, 1282GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
620 struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket)
621{ 1283{
622 *ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); 1284 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
623 (*ticket)->data = GNUNET_strdup (input); 1285 struct TicketIterationNextMessage *msg;
624 return GNUNET_OK; 1286 struct GNUNET_MQ_Envelope *env;
1287
1288 env = GNUNET_MQ_msg (msg,
1289 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT);
1290 msg->id = htonl (it->r_id);
1291 GNUNET_MQ_send (h->mq,
1292 env);
625} 1293}
626 1294
627 1295
628/** 1296/**
629 * Destroys a ticket 1297 * Stops iteration and releases the idp handle for further calls. Must
1298 * be called on any iteration that has not yet completed prior to calling
1299 * #GNUNET_IDENTITY_PROVIDER_disconnect.
630 * 1300 *
631 * @param ticket the ticket to destroy 1301 * @param it the iterator
632 */ 1302 */
633void 1303void
634GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) 1304GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
635{ 1305{
636 GNUNET_assert (NULL != ticket); 1306 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
637 if (NULL != ticket->data) 1307 struct GNUNET_MQ_Envelope *env;
638 GNUNET_free (ticket->data); 1308 struct TicketIterationStopMessage *msg;
639 GNUNET_free (ticket); 1309
1310 if (NULL != h->mq)
1311 {
1312 env = GNUNET_MQ_msg (msg,
1313 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP);
1314 msg->id = htonl (it->r_id);
1315 GNUNET_MQ_send (h->mq,
1316 env);
1317 }
1318 GNUNET_free (it);
640} 1319}
641 1320
1321/**
1322 * Revoked an issued ticket. The relying party will be unable to retrieve
1323 * updated attributes.
1324 *
1325 * @param h the identity provider to use
1326 * @param identity the issuing identity
1327 * @param ticket the ticket to revoke
1328 * @param cb the callback
1329 * @param cb_cls the callback closure
1330 * @return handle to abort the operation
1331 */
1332struct GNUNET_IDENTITY_PROVIDER_Operation *
1333GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1334 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1335 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1336 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
1337 void *cb_cls)
1338{
1339 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
1340 struct GNUNET_MQ_Envelope *env;
1341 struct RevokeTicketMessage *msg;
1342 uint32_t rid;
642 1343
1344 rid = h->r_id_gen++;
1345 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1346 op->h = h;
1347 op->rvk_cb = cb;
1348 op->cls = cb_cls;
1349 op->r_id = rid;
1350 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1351 h->op_tail,
1352 op);
1353 env = GNUNET_MQ_msg_extra (msg,
1354 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
1355 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET);
1356 msg->id = htonl (rid);
1357 msg->identity = *identity;
1358 memcpy (&msg[1],
1359 ticket,
1360 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
1361 if (NULL == h->mq)
1362 op->env = env;
1363 else
1364 GNUNET_MQ_send (h->mq,
1365 env);
1366 return op;
1367}
643 1368
644 1369
645 1370
diff --git a/src/identity-provider/identity_token.c b/src/identity-provider/identity_token.c
deleted file mode 100644
index 31249840b..000000000
--- a/src/identity-provider/identity_token.c
+++ /dev/null
@@ -1,964 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 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 identity-provider/identity_token.c
23 * @brief helper library to manage identity tokens
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_signatures.h"
29#include "identity_token.h"
30#include <jansson.h>
31#include <inttypes.h>
32
33#define JWT_ALG "alg"
34
35#define JWT_ALG_VALUE "ED512"
36
37#define JWT_TYP "typ"
38
39#define JWT_TYP_VALUE "jwt"
40
41/**
42 * Crypto helper functions
43 */
44
45static int
46create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
47 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
48 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
49{
50 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
51
52 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
53 &new_key_hash_str);
54 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
55 static const char ctx_key[] = "gnuid-aes-ctx-key";
56 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
57 new_key_hash, sizeof (struct GNUNET_HashCode),
58 ctx_key, strlen (ctx_key),
59 NULL, 0);
60 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
61 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
62 new_key_hash, sizeof (struct GNUNET_HashCode),
63 ctx_iv, strlen (ctx_iv),
64 NULL, 0);
65 return GNUNET_OK;
66}
67
68
69
70/**
71 * Decrypts data part from a token code
72 */
73static int
74decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
75 const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key,
76 const char *cyphertext,
77 size_t cyphertext_len,
78 char **result_str)
79{
80 struct GNUNET_HashCode new_key_hash;
81 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
82 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
83
84 char *str_buf = GNUNET_malloc (cyphertext_len);
85 size_t str_size;
86
87 //Calculate symmetric key from ecdh parameters
88 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (priv_key,
89 ecdh_key,
90 &new_key_hash));
91
92 create_sym_key_from_ecdh (&new_key_hash,
93 &enc_key,
94 &enc_iv);
95
96 str_size = GNUNET_CRYPTO_symmetric_decrypt (cyphertext,
97 cyphertext_len,
98 &enc_key,
99 &enc_iv,
100 str_buf);
101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
102 "Decrypted bytes: %zd Expected bytes: %zd\n",
103 str_size,
104 cyphertext_len);
105 if (-1 == str_size)
106 {
107 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
108 GNUNET_free (str_buf);
109 return GNUNET_SYSERR;
110 }
111 *result_str = GNUNET_malloc (str_size+1);
112 GNUNET_memcpy (*result_str, str_buf, str_size);
113 (*result_str)[str_size] = '\0';
114 GNUNET_free (str_buf);
115 return GNUNET_OK;
116
117}
118
119/**
120 * Decrypt string using pubkey and ECDHE
121*/
122static int
123decrypt_str_ecdhe2 (const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey,
124 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
125 const char *ciphertext,
126 size_t ciphertext_len,
127 char **plaintext)
128{
129 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
130 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
131 struct GNUNET_HashCode new_key_hash;
132
133 //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
134 *plaintext = GNUNET_malloc (ciphertext_len);
135
136 // Derived key K = H(eB)
137 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (ecdh_privkey,
138 aud_key,
139 &new_key_hash));
140 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
141 GNUNET_CRYPTO_symmetric_decrypt (ciphertext,
142 ciphertext_len,
143 &skey, &iv,
144 *plaintext);
145 return GNUNET_OK;
146}
147
148
149/**
150 * Encrypt string using pubkey and ECDHE
151 * Returns ECDHE pubkey to be used for decryption
152 */
153static int
154encrypt_str_ecdhe (const char *plaintext,
155 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
156 char **cyphertext,
157 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
158 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey)
159{
160 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
161 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
162 struct GNUNET_HashCode new_key_hash;
163 ssize_t enc_size;
164
165 // ECDH keypair E = eG
166 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
167 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
168 ecdh_pubkey);
169
170 //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
171 *cyphertext = GNUNET_malloc (strlen (plaintext));
172
173 // Derived key K = H(eB)
174 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
175 pub_key,
176 &new_key_hash));
177 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting string %s\n (len=%zd)",
179 plaintext,
180 strlen (plaintext));
181 enc_size = GNUNET_CRYPTO_symmetric_encrypt (plaintext,
182 strlen (plaintext),
183 &skey, &iv,
184 *cyphertext);
185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted (len=%zd)", enc_size);
186 return GNUNET_OK;
187}
188
189
190/**
191 * Identity Token API
192 */
193
194
195/**
196 * Create an Identity Token
197 *
198 * @param type the JSON API resource type
199 * @param id the JSON API resource id
200 * @return a new JSON API resource or NULL on error.
201 */
202struct IdentityToken*
203token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey* iss,
204 const struct GNUNET_CRYPTO_EcdsaPublicKey* aud)
205{
206 struct IdentityToken *token;
207 char* audience;
208 char* issuer;
209
210 issuer = GNUNET_STRINGS_data_to_string_alloc (iss,
211 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
212 audience = GNUNET_STRINGS_data_to_string_alloc (aud,
213 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
214
215 token = GNUNET_malloc (sizeof (struct IdentityToken));
216 token_add_attr (token, "iss", issuer);
217 token_add_attr (token, "aud", audience);
218 token_add_attr (token, "sub", issuer);
219 token->aud_key = *aud;
220 GNUNET_free (issuer);
221 GNUNET_free (audience);
222 return token;
223}
224
225void
226token_destroy (struct IdentityToken *token)
227{
228 struct TokenAttr *attr;
229 struct TokenAttr *tmp_attr;
230 struct TokenAttrValue *val;
231 struct TokenAttrValue *tmp_val;
232
233 for (attr = token->attr_head; NULL != attr;)
234 {
235 tmp_attr = attr->next;
236 GNUNET_CONTAINER_DLL_remove (token->attr_head,
237 token->attr_tail,
238 attr);
239 for (val = attr->val_head; NULL != val;)
240 {
241 tmp_val = val->next;
242 GNUNET_CONTAINER_DLL_remove (attr->val_head,
243 attr->val_tail,
244 val);
245 if (NULL != val->value)
246 GNUNET_free (val->value);
247 GNUNET_free (val);
248 val = tmp_val;
249 }
250 GNUNET_free (attr->name);
251 GNUNET_free (attr);
252 attr = tmp_attr;
253 }
254
255
256 GNUNET_free (token);
257}
258
259void
260token_add_attr (struct IdentityToken *token,
261 const char* key,
262 const char* value)
263{
264 struct TokenAttr *attr;
265 struct TokenAttrValue *new_val;
266 GNUNET_assert (NULL != token);
267
268 new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
269 new_val->value = GNUNET_strdup (value);
270 for (attr = token->attr_head; NULL != attr; attr = attr->next)
271 {
272 if (0 == strcmp (key, attr->name))
273 break;
274 }
275
276 if (NULL == attr)
277 {
278 attr = GNUNET_malloc (sizeof (struct TokenAttr));
279 attr->name = GNUNET_strdup (key);
280 GNUNET_CONTAINER_DLL_insert (token->attr_head,
281 token->attr_tail,
282 attr);
283 }
284
285 GNUNET_CONTAINER_DLL_insert (attr->val_head,
286 attr->val_tail,
287 new_val);
288}
289
290void
291token_add_attr_int (struct IdentityToken *token,
292 const char* key,
293 uint64_t value)
294{
295 struct TokenAttr *attr;
296 struct TokenAttrValue *new_val;
297 GNUNET_assert (NULL != token);
298
299 new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
300 new_val->int_value = value;
301 for (attr = token->attr_head; NULL != attr; attr = attr->next)
302 {
303 if (0 == strcmp (key, attr->name))
304 break;
305 }
306
307 if (NULL == attr)
308 {
309 attr = GNUNET_malloc (sizeof (struct TokenAttr));
310 attr->name = GNUNET_strdup (key);
311 GNUNET_CONTAINER_DLL_insert (token->attr_head,
312 token->attr_tail,
313 attr);
314 }
315
316 GNUNET_CONTAINER_DLL_insert (attr->val_head,
317 attr->val_tail,
318 new_val);
319}
320
321static void
322parse_json_payload(const char* payload_base64,
323 struct IdentityToken *token)
324{
325 const char *key;
326 const json_t *value;
327 const json_t *arr_value;
328 char *payload;
329 int idx;
330 json_t *payload_json;
331 json_error_t err_json;
332
333 GNUNET_STRINGS_base64_decode (payload_base64,
334 strlen (payload_base64),
335 &payload);
336 //TODO signature and aud key
337 payload_json = json_loads (payload, JSON_DECODE_ANY, &err_json);
338
339 json_object_foreach (payload_json, key, value)
340 {
341 if (json_is_array (value))
342 {
343 json_array_foreach (value, idx, arr_value)
344 {
345 if (json_is_integer (arr_value))
346 token_add_attr_int (token, key,
347 json_integer_value (arr_value));
348 else
349 token_add_attr (token,
350 key,
351 json_string_value (arr_value));
352 }
353 } else {
354 if (json_is_integer (value))
355 token_add_attr_int (token, key,
356 json_integer_value (value));
357 else
358 token_add_attr (token, key, json_string_value (value));
359 }
360 }
361
362 json_decref (payload_json);
363 GNUNET_free (payload);
364}
365
366int
367token_parse2 (const char* raw_data,
368 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
369 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
370 struct IdentityToken **result)
371{
372 char *enc_token_str;
373 char *tmp_buf;
374 char *token_str;
375 char *enc_token;
376 char *payload_base64;
377 size_t enc_token_len;
378
379 GNUNET_asprintf (&tmp_buf, "%s", raw_data);
380 strtok (tmp_buf, ",");
381 enc_token_str = strtok (NULL, ",");
382
383 enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
384 strlen (enc_token_str),
385 &enc_token);
386 if (GNUNET_OK != decrypt_str_ecdhe2 (priv_key,
387 aud_key,
388 enc_token,
389 enc_token_len,
390 &token_str))
391 {
392 GNUNET_free (tmp_buf);
393 GNUNET_free (enc_token);
394 return GNUNET_SYSERR;
395 }
396
397 GNUNET_assert (NULL != strtok (token_str, "."));
398 payload_base64 = strtok (NULL, ".");
399
400 *result = GNUNET_malloc (sizeof (struct IdentityToken));
401 parse_json_payload (payload_base64, *result);
402
403 (*result)->aud_key = *aud_key;
404 GNUNET_free (enc_token);
405 GNUNET_free (token_str);
406 GNUNET_free (tmp_buf);
407 return GNUNET_OK;
408}
409
410int
411token_parse (const char* raw_data,
412 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
413 struct IdentityToken **result)
414{
415 char *ecdh_pubkey_str;
416 char *enc_token_str;
417 char *tmp_buf;
418 char *token_str;
419 char *enc_token;
420 char *payload_base64;
421 size_t enc_token_len;
422 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
423
424 GNUNET_asprintf (&tmp_buf, "%s", raw_data);
425 ecdh_pubkey_str = strtok (tmp_buf, ",");
426 enc_token_str = strtok (NULL, ",");
427
428 GNUNET_assert (NULL != ecdh_pubkey_str);
429 GNUNET_assert (NULL != enc_token_str);
430
431 GNUNET_STRINGS_string_to_data (ecdh_pubkey_str,
432 strlen (ecdh_pubkey_str),
433 &ecdh_pubkey,
434 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
435 enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
436 strlen (enc_token_str),
437 &enc_token);
438 if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
439 &ecdh_pubkey,
440 enc_token,
441 enc_token_len,
442 &token_str))
443 {
444 GNUNET_free (tmp_buf);
445 GNUNET_free (enc_token);
446 return GNUNET_SYSERR;
447 }
448
449 GNUNET_assert (NULL != strtok (token_str, "."));
450 payload_base64 = strtok (NULL, ".");
451
452 *result = GNUNET_malloc (sizeof (struct IdentityToken));
453 parse_json_payload (payload_base64, *result);
454
455 GNUNET_free (enc_token);
456 GNUNET_free (token_str);
457 GNUNET_free (tmp_buf);
458 return GNUNET_OK;
459}
460
461static char*
462create_json_payload (const struct IdentityToken *token)
463{
464 struct TokenAttr *attr;
465 struct TokenAttrValue *val;
466 json_t *root;
467 char *json_str;
468
469 root = json_object();
470 for (attr = token->attr_head; NULL != attr; attr = attr->next)
471 {
472 for (val = attr->val_head; NULL != val; val = val->next)
473 {
474 if (NULL != val->value)
475 {
476 json_object_set_new (root,
477 attr->name,
478 json_string (val->value));
479 } else {
480 json_object_set_new (root,
481 attr->name,
482 json_integer (val->int_value));
483 }
484 }
485 }
486 json_str = json_dumps (root, JSON_INDENT(1));
487 json_decref (root);
488 return json_str;
489}
490
491static char*
492create_json_header(void)
493{
494 json_t *root;
495 char *json_str;
496
497 root = json_object ();
498 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
499 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
500
501 json_str = json_dumps (root, JSON_INDENT(1));
502 json_decref (root);
503 return json_str;
504}
505
506int
507token_to_string (const struct IdentityToken *token,
508 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
509 char **result)
510{
511 char *payload_str;
512 char *header_str;
513 char *payload_base64;
514 char *header_base64;
515 char *padding;
516 char *signature_target;
517 char *signature_str;
518 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
519 header_str = create_json_header();
520 GNUNET_STRINGS_base64_encode (header_str,
521 strlen (header_str),
522 &header_base64);
523 //Remove GNUNET padding of base64
524 padding = strtok(header_base64, "=");
525 while (NULL != padding)
526 padding = strtok(NULL, "=");
527
528 payload_str = create_json_payload (token);
529 GNUNET_STRINGS_base64_encode (payload_str,
530 strlen (payload_str),
531 &payload_base64);
532
533 //Remove GNUNET padding of base64
534 padding = strtok(payload_base64, "=");
535 while (NULL != padding)
536 padding = strtok(NULL, "=");
537
538 GNUNET_asprintf (&signature_target, "%s,%s", header_base64, payload_base64);
539 purpose =
540 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
541 strlen (signature_target));
542 purpose->size =
543 htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
544 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
545 GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
546 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
547 purpose,
548 (struct GNUNET_CRYPTO_EcdsaSignature *)&token->signature))
549 {
550 GNUNET_free (signature_target);
551 GNUNET_free (payload_str);
552 GNUNET_free (payload_base64);
553 GNUNET_free (header_base64);
554 GNUNET_free (purpose);
555 return GNUNET_SYSERR;
556 }
557
558 GNUNET_STRINGS_base64_encode ((const char*)&token->signature,
559 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
560 &signature_str);
561 GNUNET_asprintf (result, "%s.%s.%s",
562 header_base64, payload_base64, signature_str);
563 GNUNET_free (signature_target);
564 GNUNET_free (payload_str);
565 GNUNET_free (header_str);
566 GNUNET_free (signature_str);
567 GNUNET_free (payload_base64);
568 GNUNET_free (header_base64);
569 GNUNET_free (purpose);
570 return GNUNET_OK;
571}
572
573int
574token_serialize (const struct IdentityToken *token,
575 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
576 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
577 char **result)
578{
579 char *token_str;
580 char *enc_token;
581 char *dh_key_str;
582 char *enc_token_base64;
583 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
584
585 GNUNET_assert (GNUNET_OK == token_to_string (token,
586 priv_key,
587 &token_str));
588
589 GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (token_str,
590 &token->aud_key,
591 &enc_token,
592 ecdh_privkey,
593 &ecdh_pubkey));
594 GNUNET_STRINGS_base64_encode (enc_token,
595 strlen (token_str),
596 &enc_token_base64);
597 dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ecdh_pubkey,
598 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
599 GNUNET_asprintf (result, "%s,%s", dh_key_str, enc_token_base64);
600 GNUNET_free (dh_key_str);
601 GNUNET_free (enc_token_base64);
602 GNUNET_free (enc_token);
603 GNUNET_free (token_str);
604 return GNUNET_OK;
605}
606
607struct TokenTicketPayload*
608ticket_payload_create (uint64_t nonce,
609 const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
610 const char* lbl_str)
611{
612 struct TokenTicketPayload* payload;
613
614 payload = GNUNET_malloc (sizeof (struct TokenTicketPayload));
615 payload->nonce = nonce;
616 payload->identity_key = *identity_pkey;
617 GNUNET_asprintf (&payload->label, lbl_str, strlen (lbl_str));
618 return payload;
619}
620
621void
622ticket_payload_destroy (struct TokenTicketPayload* payload)
623{
624 if (NULL != payload->label)
625 GNUNET_free (payload->label);
626 GNUNET_free (payload);
627}
628
629void
630ticket_payload_serialize (struct TokenTicketPayload *payload,
631 char **result)
632{
633 char* identity_key_str;
634
635 identity_key_str = GNUNET_STRINGS_data_to_string_alloc (&payload->identity_key,
636 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
637
638 GNUNET_asprintf (result,
639 "{\"nonce\": \"%"SCNu64"\",\"identity\": \"%s\",\"label\": \"%s\"}",
640 payload->nonce, identity_key_str, payload->label);
641 GNUNET_free (identity_key_str);
642
643}
644
645
646/**
647 * Create the token code
648 * The data is encrypted with a share ECDH derived secret using B (aud_key)
649 * and e (ecdh_privkey)
650 * The ticket also contains E (ecdh_pubkey) and a signature over the
651 * data and E
652 */
653struct TokenTicket*
654ticket_create (uint64_t nonce,
655 const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
656 const char* lbl_str,
657 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key)
658{
659 struct TokenTicket *ticket;
660 struct TokenTicketPayload *code_payload;
661
662 ticket = GNUNET_malloc (sizeof (struct TokenTicket));
663 code_payload = ticket_payload_create (nonce,
664 identity_pkey,
665 lbl_str);
666 ticket->aud_key = *aud_key;
667 ticket->payload = code_payload;
668
669
670 return ticket;
671}
672
673void
674ticket_destroy (struct TokenTicket *ticket)
675{
676 ticket_payload_destroy (ticket->payload);
677 GNUNET_free (ticket);
678}
679
680int
681ticket_serialize (struct TokenTicket *ticket,
682 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
683 char **result)
684{
685 char *code_payload_str;
686 char *enc_ticket_payload;
687 char *ticket_payload_str;
688 char *ticket_sig_str;
689 char *ticket_str;
690 char *dh_key_str;
691 char *write_ptr;
692 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
693
694 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
695
696 ticket_payload_serialize (ticket->payload,
697 &code_payload_str);
698
699 GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (code_payload_str,
700 &ticket->aud_key,
701 &enc_ticket_payload,
702 &ecdhe_privkey,
703 &ticket->ecdh_pubkey));
704
705 GNUNET_free (ecdhe_privkey);
706
707 purpose =
708 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
709 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
710 strlen (code_payload_str)); // E_K (code_str)
711 purpose->size =
712 htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
713 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
714 strlen (code_payload_str));
715 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
716 write_ptr = (char*) &purpose[1];
717 GNUNET_memcpy (write_ptr,
718 &ticket->ecdh_pubkey,
719 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
720 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
721 GNUNET_memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
722 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
723 purpose,
724 &ticket->signature));
725 GNUNET_STRINGS_base64_encode (enc_ticket_payload,
726 strlen (code_payload_str),
727 &ticket_payload_str);
728 ticket_sig_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->signature,
729 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
730
731 dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->ecdh_pubkey,
732 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
733 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
734 GNUNET_asprintf (&ticket_str, "{\"data\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
735 ticket_payload_str, dh_key_str, ticket_sig_str);
736 GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
737 GNUNET_free (dh_key_str);
738 GNUNET_free (purpose);
739 GNUNET_free (ticket_str);
740 GNUNET_free (ticket_sig_str);
741 GNUNET_free (code_payload_str);
742 GNUNET_free (enc_ticket_payload);
743 GNUNET_free (ticket_payload_str);
744 return GNUNET_OK;
745}
746
747int
748ticket_payload_parse(const char *raw_data,
749 ssize_t data_len,
750 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
751 const struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe_pkey,
752 struct TokenTicketPayload **result)
753{
754 const char* label_str;
755 const char* nonce_str;
756 const char* identity_key_str;
757
758 json_t *root;
759 json_t *label_json;
760 json_t *identity_json;
761 json_t *nonce_json;
762 json_error_t err_json;
763 char* data_str;
764 uint64_t nonce;
765 struct GNUNET_CRYPTO_EcdsaPublicKey id_pkey;
766
767 if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
768 ecdhe_pkey,
769 raw_data,
770 data_len,
771 &data_str))
772 {
773 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Data decryption failed\n");
774 return GNUNET_SYSERR;
775 }
776
777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data: %s\n", data_str);
778 root = json_loads (data_str, JSON_DECODE_ANY, &err_json);
779 if (!root)
780 {
781 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
782 "Error parsing data: %s\n", err_json.text);
783 GNUNET_free (data_str);
784 return GNUNET_SYSERR;
785 }
786
787 identity_json = json_object_get (root, "identity");
788 if (!json_is_string (identity_json))
789 {
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
791 "Error parsing data: %s\n", err_json.text);
792 json_decref (root);
793 GNUNET_free (data_str);
794 return GNUNET_SYSERR;
795 }
796 identity_key_str = json_string_value (identity_json);
797 GNUNET_STRINGS_string_to_data (identity_key_str,
798 strlen (identity_key_str),
799 &id_pkey,
800 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
801
802
803 label_json = json_object_get (root, "label");
804 if (!json_is_string (label_json))
805 {
806 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
807 "Error parsing data: %s\n", err_json.text);
808 json_decref (root);
809 GNUNET_free (data_str);
810 return GNUNET_SYSERR;
811 }
812
813 label_str = json_string_value (label_json);
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found label: %s\n", label_str);
815
816 nonce_json = json_object_get (root, "nonce");
817 if (!json_is_string (label_json))
818 {
819 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
820 "Error parsing data: %s\n", err_json.text);
821 json_decref (root);
822 GNUNET_free (data_str);
823 return GNUNET_SYSERR;
824 }
825
826 nonce_str = json_string_value (nonce_json);
827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found nonce: %s\n", nonce_str);
828
829 GNUNET_assert (0 != sscanf (nonce_str, "%"SCNu64, &nonce));
830
831 *result = ticket_payload_create (nonce,
832 (const struct GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
833 label_str);
834 GNUNET_free (data_str);
835 json_decref (root);
836 return GNUNET_OK;
837
838}
839
840int
841ticket_parse (const char *raw_data,
842 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
843 struct TokenTicket **result)
844{
845 const char* enc_data_str;
846 const char* ecdh_enc_str;
847 const char* signature_enc_str;
848
849 json_t *root;
850 json_t *signature_json;
851 json_t *ecdh_json;
852 json_t *enc_data_json;
853 json_error_t err_json;
854 char* enc_data;
855 char* ticket_decoded;
856 char* write_ptr;
857 size_t enc_data_len;
858 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
859 struct TokenTicket *ticket;
860 struct TokenTicketPayload *ticket_payload;
861
862 ticket_decoded = NULL;
863 GNUNET_STRINGS_base64_decode (raw_data, strlen (raw_data), &ticket_decoded);
864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket: %s\n", ticket_decoded);
865 root = json_loads (ticket_decoded, JSON_DECODE_ANY, &err_json);
866 if (!root)
867 {
868 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
869 "%s\n", err_json.text);
870 return GNUNET_SYSERR;
871 }
872
873 signature_json = json_object_get (root, "signature");
874 ecdh_json = json_object_get (root, "ecdh");
875 enc_data_json = json_object_get (root, "data");
876
877 signature_enc_str = json_string_value (signature_json);
878 ecdh_enc_str = json_string_value (ecdh_json);
879 enc_data_str = json_string_value (enc_data_json);
880
881 ticket = GNUNET_malloc (sizeof (struct TokenTicket));
882
883 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ecdh_enc_str,
884 strlen (ecdh_enc_str),
885 &ticket->ecdh_pubkey,
886 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)))
887 {
888 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in data\n", ecdh_enc_str);
889 json_decref (root);
890 GNUNET_free (ticket);
891 return GNUNET_SYSERR;
892 }
893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s for data decryption\n", ecdh_enc_str);
894 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
895 strlen (signature_enc_str),
896 &ticket->signature,
897 sizeof (struct GNUNET_CRYPTO_EcdsaSignature)))
898 {
899 json_decref (root);
900 GNUNET_free (ticket_decoded);
901 GNUNET_free (ticket);
902 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in data\n");
903 return GNUNET_SYSERR;
904 }
905
906 enc_data_len = GNUNET_STRINGS_base64_decode (enc_data_str,
907 strlen (enc_data_str),
908 &enc_data);
909
910
911 if (GNUNET_OK != ticket_payload_parse (enc_data,
912 enc_data_len,
913 priv_key,
914 (const struct GNUNET_CRYPTO_EcdhePublicKey*)&ticket->ecdh_pubkey,
915 &ticket_payload))
916 {
917 json_decref (root);
918 GNUNET_free (enc_data);
919 GNUNET_free (ticket_decoded);
920 GNUNET_free (ticket);
921 return GNUNET_SYSERR;
922 }
923
924 ticket->payload = ticket_payload;
925 purpose =
926 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
927 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
928 enc_data_len); // E_K (code_str)
929 purpose->size =
930 htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
931 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
932 enc_data_len);
933 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
934 write_ptr = (char*) &purpose[1];
935 GNUNET_memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
936 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
937 GNUNET_memcpy (write_ptr, enc_data, enc_data_len);
938
939 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET,
940 purpose,
941 &ticket->signature,
942 &ticket_payload->identity_key))
943 {
944 ticket_destroy (ticket);
945 GNUNET_free (ticket_decoded);
946 json_decref (root);
947 GNUNET_free (purpose);
948 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
949 "Error verifying signature for ticket\n");
950 return GNUNET_SYSERR;
951 }
952 *result = ticket;
953 GNUNET_free (purpose);
954
955 GNUNET_free (enc_data);
956 GNUNET_free (ticket_decoded);
957 json_decref (root);
958 return GNUNET_OK;
959
960}
961
962
963
964/* end of identity_token.c */
diff --git a/src/identity-provider/identity_token.h b/src/identity-provider/identity_token.h
deleted file mode 100644
index 7ded6662e..000000000
--- a/src/identity-provider/identity_token.h
+++ /dev/null
@@ -1,346 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 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 identity-provider/identity_token.h
23 * @brief GNUnet Identity Provider library
24 *
25 */
26#ifndef IDENTITY_TOKEN_H
27#define IDENTITY_TOKEN_H
28
29#include "gnunet_crypto_lib.h"
30#include <jansson.h>
31
32struct IdentityToken
33{
34 /**
35 * DLL
36 */
37 struct TokenAttr *attr_head;
38
39 /**
40 * DLL
41 */
42 struct TokenAttr *attr_tail;
43
44 /**
45 * Token Signature
46 */
47 struct GNUNET_CRYPTO_EcdsaSignature signature;
48
49 /**
50 * Audience Pubkey
51 */
52 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
53};
54
55struct TokenAttr
56{
57 /**
58 * DLL
59 */
60 struct TokenAttr *next;
61
62 /**
63 * DLL
64 */
65 struct TokenAttr *prev;
66
67 /**
68 * Attribute name
69 */
70 char *name;
71
72 /**
73 * Attribute value DLL
74 */
75 struct TokenAttrValue *val_head;
76
77 /**
78 * Attribute value DLL
79 */
80 struct TokenAttrValue *val_tail;
81
82};
83
84struct TokenAttrValue
85{
86 /**
87 * DLL
88 */
89 struct TokenAttrValue *next;
90
91 /**
92 * DLL
93 */
94 struct TokenAttrValue *prev;
95
96 /**
97 * Attribute value
98 */
99 char *value;
100
101 /**
102 * Attribute int value
103 * used if NULL == value
104 */
105 uint64_t int_value;
106};
107
108struct TokenTicketPayload
109{
110 /**
111 * Nonce
112 */
113 uint64_t nonce;
114
115 /**
116 * Label
117 */
118 char *label;
119
120 /**
121 * Issuing Identity
122 */
123 struct GNUNET_CRYPTO_EcdsaPublicKey identity_key;
124};
125
126
127struct TokenTicket
128{
129 /**
130 * Meta info
131 */
132 struct TokenTicketPayload *payload;
133
134 /**
135 * ECDH Pubkey
136 */
137 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
138
139 /**
140 * Signature
141 */
142 struct GNUNET_CRYPTO_EcdsaSignature signature;
143
144 /**
145 * Target identity
146 */
147 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
148};
149
150
151
152/**
153 * Create an identity token
154 *
155 * @param iss the issuer string for the token
156 * @param aud the audience of the token
157 *
158 * @return a new token
159 */
160struct IdentityToken*
161token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *iss,
162 const struct GNUNET_CRYPTO_EcdsaPublicKey* aud);
163
164/**
165 * Destroy an identity token
166 *
167 * @param token the token to destroy
168 */
169void
170token_destroy (struct IdentityToken*token);
171
172/**
173 * Add a new key value pair to the token
174 *
175 * @param token the token to modify
176 * @param key the key
177 * @param value the value
178 */
179void
180token_add_attr (struct IdentityToken *token,
181 const char* key,
182 const char* value);
183
184/**
185 * Add a new key value pair to the token
186 *
187 * @param token the token to modify
188 * @param key the key
189 * @param value the value
190 */
191void
192token_add_attr_int (struct IdentityToken *token,
193 const char* key,
194 uint64_t value);
195
196
197
198/**
199 * Add a value to a TokenAttribute
200 *
201 * @param attr the token attribute
202 * @param value value to add
203 */
204 void
205 token_attr_add_value (const struct TokenAttr *attr,
206 const char *value);
207
208/**
209 * Add a new key value pair to the token with the value as json
210 *
211 * @param the token to modify
212 * @param key the key
213 * @param value the value
214 *
215 */
216 void
217 token_add_json (const struct IdentityToken *token,
218 const char* key,
219 json_t* value);
220
221/**
222 * Serialize a token. The token will be signed and base64 according to the
223 * JWT format. The signature is base32-encoded ECDSA.
224 * The resulting JWT is encrypted using
225 * ECDHE for the audience and Base64
226 * encoded in result. The audience requires the ECDHE public key P
227 * to decrypt the token T. The key P is included in the result and prepended
228 * before the token
229 *
230 * @param token the token to serialize
231 * @param priv_key the private key used to sign the token
232 * @param ecdhe_privkey the ECDHE private key used to encrypt the token
233 * @param result P,Base64(E(T))
234 *
235 * @return GNUNET_OK on success
236 */
237 int
238 token_serialize (const struct IdentityToken*token,
239 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
240 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
241 char **result);
242
243/**
244 * Parses the serialized token and returns a token
245 *
246 * @param data the serialized token
247 * @param priv_key the private key of the audience
248 * @param result the token
249 *
250 * @return GNUNET_OK on success
251 */
252 int
253 token_parse (const char* data,
254 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
255 struct IdentityToken **result);
256
257/**
258 * Parses the serialized token and returns a token
259 * This variant is intended for the party that issued the token and also
260 * wants to decrypt the serialized token.
261 *
262 * @param data the serialized token
263 * @param priv_key the private (!) ECDHE key
264 * @param aud_key the identity of the audience
265 * @param result the token
266 *
267 * @return GNUNET_OK on success
268 */
269int
270token_parse2 (const char* data,
271 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
272 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
273 struct IdentityToken **result);
274
275
276/**
277 *
278 * Returns a JWT-string representation of the token
279 *
280 * @param token the token
281 * @param priv_key the private key used to sign the JWT
282 * @param result the JWT
283 *
284 * @return GNUNET_OK on success
285 */
286 int
287 token_to_string (const struct IdentityToken *token,
288 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
289 char **result);
290
291/**
292 *
293 * Creates a ticket that can be exchanged by the audience for
294 * the token. The token must be placed under the label
295 *
296 * @param nonce nonce provided by the audience that requested the ticket
297 * @param iss_pkey the issuer pubkey used to sign the ticket
298 * @param label the label encoded in the ticket
299 * @param aud_ley the audience pubkey used to encrypt the ticket payload
300 *
301 * @return the ticket
302 */
303struct TokenTicket*
304ticket_create (uint64_t nonce,
305 const struct GNUNET_CRYPTO_EcdsaPublicKey* iss_pkey,
306 const char* lbl_str,
307 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key);
308
309/**
310 * Serialize a ticket. Returns the Base64 representation of the ticket.
311 * Format: Base64( { payload: E(Payload), ecdhe: K, signature: signature } )
312 *
313 * @param ticket the ticket to serialize
314 * @param priv_key the issuer private key to sign the ticket payload
315 * @param result the serialized ticket
316 *
317 * @return GNUNET_OK on success
318 */
319 int
320 ticket_serialize (struct TokenTicket *ticket,
321 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
322 char **result);
323
324/**
325 * Destroys a ticket
326 *
327 * @param the ticket to destroy
328 */
329void
330ticket_destroy (struct TokenTicket *ticket);
331
332/**
333 * Parses a serialized ticket
334 *
335 * @param data the serialized ticket
336 * @param priv_key the audience private key
337 * @param ticket the ticket
338 *
339 * @return GNUNET_OK on success
340 */
341int
342ticket_parse (const char* raw_data,
343 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
344 struct TokenTicket **ticket);
345
346#endif
diff --git a/src/identity-provider/jwt.c b/src/identity-provider/jwt.c
new file mode 100644
index 000000000..2f1e3240b
--- /dev/null
+++ b/src/identity-provider/jwt.c
@@ -0,0 +1,180 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 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 identity-provider/jwt.c
23 * @brief helper library for JSON-Web-Tokens
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_signatures.h"
29#include "gnunet_identity_attribute_lib.h"
30#include <jansson.h>
31
32
33#define JWT_ALG "alg"
34
35/*TODO is this the correct way to define new algs? */
36#define JWT_ALG_VALUE "ED512"
37
38#define JWT_TYP "typ"
39
40#define JWT_TYP_VALUE "jwt"
41
42static char*
43create_jwt_header(void)
44{
45 json_t *root;
46 char *json_str;
47
48 root = json_object ();
49 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
50 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
51
52 json_str = json_dumps (root, JSON_INDENT(1));
53 json_decref (root);
54 return json_str;
55}
56
57/**
58 * Create a JWT from attributes
59 *
60 * @param sub_key the public of the subject
61 * @param attrs the attribute list
62 * @param priv_key the key used to sign the JWT
63 * @return a new base64-encoded JWT string.
64 */
65char*
66jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
67 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
68 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key)
69{
70 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
71 struct GNUNET_CRYPTO_EcdsaPublicKey iss_key;
72 struct GNUNET_CRYPTO_EcdsaSignature signature;
73 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
74 char* audience;
75 char* issuer;
76 char* header;
77 char* padding;
78 char* body_str;
79 char* result;
80 char* header_base64;
81 char* body_base64;
82 char* signature_target;
83 char* signature_base64;
84 char* attr_val_str;
85 json_t* body;
86
87 GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &iss_key);
88 /* TODO maybe we should use a local identity here */
89 issuer = GNUNET_STRINGS_data_to_string_alloc (&iss_key,
90 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
91 audience = GNUNET_STRINGS_data_to_string_alloc (sub_key,
92 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
93 header = create_jwt_header ();
94 body = json_object ();
95 /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */
96 json_object_set_new (body,
97 "iss", json_string (issuer));
98 json_object_set_new (body,
99 "sub", json_string (issuer));
100 /* TODO what should be in here exactly? */
101 json_object_set_new (body,
102 "aud", json_string (audience));
103 for (le = attrs->list_head; NULL != le; le = le->next)
104 {
105 /**
106 * TODO here we should have a function that
107 * calls the Attribute plugins to create a
108 * json representation for its value
109 */
110 attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type,
111 le->claim->data,
112 le->claim->data_size);
113 json_object_set_new (body,
114 le->claim->name,
115 json_string (attr_val_str));
116 GNUNET_free (attr_val_str);
117 }
118 body_str = json_dumps (body, JSON_INDENT(0));
119 json_decref (body);
120
121 GNUNET_STRINGS_base64_encode (header,
122 strlen (header),
123 &header_base64);
124 //Remove GNUNET padding of base64
125 padding = strtok(header_base64, "=");
126 while (NULL != padding)
127 padding = strtok(NULL, "=");
128
129 GNUNET_STRINGS_base64_encode (body_str,
130 strlen (body_str),
131 &body_base64);
132
133 //Remove GNUNET padding of base64
134 padding = strtok(body_base64, "=");
135 while (NULL != padding)
136 padding = strtok(NULL, "=");
137
138 GNUNET_free (issuer);
139 GNUNET_free (audience);
140
141 /**
142 * TODO
143 * Creating the JWT signature. This might not be
144 * standards compliant, check.
145 */
146 GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64);
147
148 purpose =
149 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
150 strlen (signature_target));
151 purpose->size =
152 htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
153 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
154 GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
155 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
156 purpose,
157 (struct GNUNET_CRYPTO_EcdsaSignature *)&signature))
158 {
159 GNUNET_free (signature_target);
160 GNUNET_free (body_str);
161 GNUNET_free (body_base64);
162 GNUNET_free (header_base64);
163 GNUNET_free (purpose);
164 return NULL;
165 }
166 GNUNET_STRINGS_base64_encode ((const char*)&signature,
167 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
168 &signature_base64);
169 GNUNET_asprintf (&result, "%s.%s.%s",
170 header_base64, body_base64, signature_base64);
171
172 GNUNET_free (signature_target);
173 GNUNET_free (header);
174 GNUNET_free (body_str);
175 GNUNET_free (signature_base64);
176 GNUNET_free (body_base64);
177 GNUNET_free (header_base64);
178 GNUNET_free (purpose);
179 return result;
180}
diff --git a/src/identity/plugin_gnsrecord_identity.c b/src/identity-provider/plugin_gnsrecord_identity_provider.c
index c26c04074..6ed0b0852 100644
--- a/src/identity/plugin_gnsrecord_identity.c
+++ b/src/identity-provider/plugin_gnsrecord_identity_provider.c
@@ -19,9 +19,9 @@
19*/ 19*/
20 20
21/** 21/**
22 * @file identity/plugin_gnsrecord_identity.c 22 * @file identity-provider/plugin_gnsrecord_identity_provider.c
23 * @brief gnsrecord plugin to provide the API for identity records 23 * @brief gnsrecord plugin to provide the API for identity records
24 * @author Christian Grothoff 24 * @author Martin Schanzenbach
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
@@ -54,9 +54,13 @@ value_to_string (void *cls,
54 switch (type) 54 switch (type)
55 { 55 {
56 case GNUNET_GNSRECORD_TYPE_ID_ATTR: 56 case GNUNET_GNSRECORD_TYPE_ID_ATTR:
57 case GNUNET_GNSRECORD_TYPE_ID_TOKEN: 57 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
58 case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED
58 return GNUNET_strndup (data, data_size); 59 return GNUNET_strndup (data, data_size);
59 case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: 60 case GNUNET_GNSRECORD_TYPE_ABE_KEY:
61 case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
62 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
63 case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED
60 ecdhe_privkey = data; 64 ecdhe_privkey = data;
61 audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); 65 audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
62 scopes = (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 66 scopes = (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
@@ -106,12 +110,22 @@ string_to_value (void *cls,
106 switch (type) 110 switch (type)
107 { 111 {
108 case GNUNET_GNSRECORD_TYPE_ID_ATTR: 112 case GNUNET_GNSRECORD_TYPE_ID_ATTR:
113 return GNUNET_STRINGS_string_to_data (s,
114 strlen (s),
115 *data,
116 *data_size);
109 case GNUNET_GNSRECORD_TYPE_ID_TOKEN: 117 case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
110 *data = GNUNET_strdup (s); 118 *data = GNUNET_strdup (s);
111 *data_size = strlen (s); 119 *data_size = strlen (s);
112 return GNUNET_OK; 120 return GNUNET_OK;
121 case GNUNET_GNSRECORD_TYPE_ABE_KEY:
122 case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
123 return GNUNET_STRINGS_string_to_data (s,
124 strlen (s),
125 *data,
126 *data_size);
113 case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: 127 case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
114 tmp_tok = GNUNET_strdup (s); 128 tmp_tok = GNUNET_strdup (s);
115 ecdhe_str = strtok (tmp_tok, ";"); 129 ecdhe_str = strtok (tmp_tok, ";");
116 if (NULL == ecdhe_str) 130 if (NULL == ecdhe_str)
117 { 131 {
@@ -160,15 +174,17 @@ string_to_value (void *cls,
160 * Mapping of record type numbers to human-readable 174 * Mapping of record type numbers to human-readable
161 * record type names. 175 * record type names.
162 */ 176 */
163 static struct { 177static struct {
164 const char *name; 178 const char *name;
165 uint32_t number; 179 uint32_t number;
166 } name_map[] = { 180} name_map[] = {
167 { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR }, 181 { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
168 { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN }, 182 { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
169 { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA }, 183 { "ABE_KEY", GNUNET_GNSRECORD_TYPE_ABE_KEY },
170 { NULL, UINT32_MAX } 184 { "ABE_MASTER", GNUNET_GNSRECORD_TYPE_ABE_MASTER },
171 }; 185 { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
186 { NULL, UINT32_MAX }
187};
172 188
173 189
174/** 190/**
@@ -220,7 +236,7 @@ number_to_typename (void *cls,
220 * @return the exported block API 236 * @return the exported block API
221 */ 237 */
222void * 238void *
223libgnunet_plugin_gnsrecord_identity_init (void *cls) 239libgnunet_plugin_gnsrecord_identity_provider_init (void *cls)
224{ 240{
225 struct GNUNET_GNSRECORD_PluginFunctions *api; 241 struct GNUNET_GNSRECORD_PluginFunctions *api;
226 242
@@ -240,7 +256,7 @@ libgnunet_plugin_gnsrecord_identity_init (void *cls)
240 * @return NULL 256 * @return NULL
241 */ 257 */
242void * 258void *
243libgnunet_plugin_gnsrecord_identity_done (void *cls) 259libgnunet_plugin_gnsrecord_identity_provider_done (void *cls)
244{ 260{
245 struct GNUNET_GNSRECORD_PluginFunctions *api = cls; 261 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
246 262
diff --git a/src/identity-provider/plugin_identity_provider_sqlite.c b/src/identity-provider/plugin_identity_provider_sqlite.c
new file mode 100644
index 000000000..0071528b9
--- /dev/null
+++ b/src/identity-provider/plugin_identity_provider_sqlite.c
@@ -0,0 +1,736 @@
1 /*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2017 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 identity-provider/plugin_identity_provider_sqlite.c
23 * @brief sqlite-based idp backend
24 * @author Martin Schanzenbach
25 */
26
27#include "platform.h"
28#include "gnunet_identity_provider_service.h"
29#include "gnunet_identity_provider_plugin.h"
30#include "gnunet_identity_attribute_lib.h"
31#include "gnunet_sq_lib.h"
32#include <sqlite3.h>
33
34/**
35 * After how many ms "busy" should a DB operation fail for good? A
36 * low value makes sure that we are more responsive to requests
37 * (especially PUTs). A high value guarantees a higher success rate
38 * (SELECTs in iterate can take several seconds despite LIMIT=1).
39 *
40 * The default value of 1s should ensure that users do not experience
41 * huge latencies while at the same time allowing operations to
42 * succeed with reasonable probability.
43 */
44#define BUSY_TIMEOUT_MS 1000
45
46
47/**
48 * Log an error message at log-level 'level' that indicates
49 * a failure of the command 'cmd' on file 'filename'
50 * with the message given by strerror(errno).
51 */
52#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "identity-provider", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
53
54#define LOG(kind,...) GNUNET_log_from (kind, "identity-provider-sqlite", __VA_ARGS__)
55
56
57/**
58 * Context for all functions in this plugin.
59 */
60struct Plugin
61{
62
63 const struct GNUNET_CONFIGURATION_Handle *cfg;
64
65 /**
66 * Database filename.
67 */
68 char *fn;
69
70 /**
71 * Native SQLite database handle.
72 */
73 sqlite3 *dbh;
74
75 /**
76 * Precompiled SQL to store ticket.
77 */
78 sqlite3_stmt *store_ticket;
79
80 /**
81 * Precompiled SQL to delete existing ticket.
82 */
83 sqlite3_stmt *delete_ticket;
84
85 /**
86 * Precompiled SQL to iterate tickets.
87 */
88 sqlite3_stmt *iterate_tickets;
89
90 /**
91 * Precompiled SQL to get ticket attributes.
92 */
93 sqlite3_stmt *get_ticket_attrs;
94
95 /**
96 * Precompiled SQL to iterate tickets by audience.
97 */
98 sqlite3_stmt *iterate_tickets_by_audience;
99};
100
101
102/**
103 * @brief Prepare a SQL statement
104 *
105 * @param dbh handle to the database
106 * @param zSql SQL statement, UTF-8 encoded
107 * @param ppStmt set to the prepared statement
108 * @return 0 on success
109 */
110static int
111sq_prepare (sqlite3 *dbh,
112 const char *zSql,
113 sqlite3_stmt **ppStmt)
114{
115 char *dummy;
116 int result;
117
118 result =
119 sqlite3_prepare_v2 (dbh,
120 zSql,
121 strlen (zSql),
122 ppStmt,
123 (const char **) &dummy);
124 LOG (GNUNET_ERROR_TYPE_DEBUG,
125 "Prepared `%s' / %p: %d\n",
126 zSql,
127 *ppStmt,
128 result);
129 return result;
130}
131
132/**
133 * Create our database indices.
134 *
135 * @param dbh handle to the database
136 */
137static void
138create_indices (sqlite3 * dbh)
139{
140 /* create indices */
141 if ( (SQLITE_OK !=
142 sqlite3_exec (dbh,
143 "CREATE INDEX IF NOT EXISTS identity_reverse ON identity001tickets (identity,audience)",
144 NULL, NULL, NULL)) ||
145 (SQLITE_OK !=
146 sqlite3_exec (dbh,
147 "CREATE INDEX IF NOT EXISTS it_iter ON identity001tickets (rnd)",
148 NULL, NULL, NULL)) )
149 LOG (GNUNET_ERROR_TYPE_ERROR,
150 "Failed to create indices: %s\n",
151 sqlite3_errmsg (dbh));
152}
153
154
155
156#if 0
157#define CHECK(a) GNUNET_break(a)
158#define ENULL NULL
159#else
160#define ENULL &e
161#define ENULL_DEFINED 1
162#define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
163#endif
164
165
166/**
167 * Initialize the database connections and associated
168 * data structures (create tables and indices
169 * as needed as well).
170 *
171 * @param plugin the plugin context (state for this module)
172 * @return #GNUNET_OK on success
173 */
174static int
175database_setup (struct Plugin *plugin)
176{
177 sqlite3_stmt *stmt;
178 char *afsdir;
179#if ENULL_DEFINED
180 char *e;
181#endif
182
183 if (GNUNET_OK !=
184 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
185 "identity-provider-sqlite",
186 "FILENAME",
187 &afsdir))
188 {
189 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
190 "identity-provider-sqlite",
191 "FILENAME");
192 return GNUNET_SYSERR;
193 }
194 if (GNUNET_OK !=
195 GNUNET_DISK_file_test (afsdir))
196 {
197 if (GNUNET_OK !=
198 GNUNET_DISK_directory_create_for_file (afsdir))
199 {
200 GNUNET_break (0);
201 GNUNET_free (afsdir);
202 return GNUNET_SYSERR;
203 }
204 }
205 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
206 plugin->fn = afsdir;
207
208 /* Open database and precompile statements */
209 if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
210 {
211 LOG (GNUNET_ERROR_TYPE_ERROR,
212 _("Unable to initialize SQLite: %s.\n"),
213 sqlite3_errmsg (plugin->dbh));
214 return GNUNET_SYSERR;
215 }
216 CHECK (SQLITE_OK ==
217 sqlite3_exec (plugin->dbh,
218 "PRAGMA temp_store=MEMORY", NULL, NULL,
219 ENULL));
220 CHECK (SQLITE_OK ==
221 sqlite3_exec (plugin->dbh,
222 "PRAGMA synchronous=NORMAL", NULL, NULL,
223 ENULL));
224 CHECK (SQLITE_OK ==
225 sqlite3_exec (plugin->dbh,
226 "PRAGMA legacy_file_format=OFF", NULL, NULL,
227 ENULL));
228 CHECK (SQLITE_OK ==
229 sqlite3_exec (plugin->dbh,
230 "PRAGMA auto_vacuum=INCREMENTAL", NULL,
231 NULL, ENULL));
232 CHECK (SQLITE_OK ==
233 sqlite3_exec (plugin->dbh,
234 "PRAGMA encoding=\"UTF-8\"", NULL,
235 NULL, ENULL));
236 CHECK (SQLITE_OK ==
237 sqlite3_exec (plugin->dbh,
238 "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
239 ENULL));
240 CHECK (SQLITE_OK ==
241 sqlite3_exec (plugin->dbh,
242 "PRAGMA page_size=4092", NULL, NULL,
243 ENULL));
244
245 CHECK (SQLITE_OK ==
246 sqlite3_busy_timeout (plugin->dbh,
247 BUSY_TIMEOUT_MS));
248
249
250 /* Create table */
251 CHECK (SQLITE_OK ==
252 sq_prepare (plugin->dbh,
253 "SELECT 1 FROM sqlite_master WHERE tbl_name = 'identity001tickets'",
254 &stmt));
255 if ((sqlite3_step (stmt) == SQLITE_DONE) &&
256 (sqlite3_exec
257 (plugin->dbh,
258 "CREATE TABLE identity001tickets ("
259 " identity BLOB NOT NULL DEFAULT '',"
260 " audience BLOB NOT NULL DEFAULT '',"
261 " rnd INT8 NOT NULL DEFAULT '',"
262 " attributes BLOB NOT NULL DEFAULT ''"
263 ")",
264 NULL, NULL, NULL) != SQLITE_OK))
265 {
266 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR,
267 "sqlite3_exec");
268 sqlite3_finalize (stmt);
269 return GNUNET_SYSERR;
270 }
271 sqlite3_finalize (stmt);
272
273 create_indices (plugin->dbh);
274
275 if ( (SQLITE_OK !=
276 sq_prepare (plugin->dbh,
277 "INSERT INTO identity001tickets (identity, audience, rnd, attributes)"
278 " VALUES (?, ?, ?, ?)",
279 &plugin->store_ticket)) ||
280 (SQLITE_OK !=
281 sq_prepare (plugin->dbh,
282 "DELETE FROM identity001tickets WHERE identity=? AND rnd=?",
283 &plugin->delete_ticket)) ||
284 (SQLITE_OK !=
285 sq_prepare (plugin->dbh,
286 "SELECT identity,audience,rnd,attributes"
287 " FROM identity001tickets WHERE identity=? AND rnd=?",
288 &plugin->get_ticket_attrs)) ||
289 (SQLITE_OK !=
290 sq_prepare (plugin->dbh,
291 "SELECT identity,audience,rnd,attributes"
292 " FROM identity001tickets WHERE identity=?"
293 " ORDER BY rnd LIMIT 1 OFFSET ?",
294 &plugin->iterate_tickets)) ||
295 (SQLITE_OK !=
296 sq_prepare (plugin->dbh,
297 "SELECT identity,audience,rnd,attributes"
298 " FROM identity001tickets WHERE audience=?"
299 " ORDER BY rnd LIMIT 1 OFFSET ?",
300 &plugin->iterate_tickets_by_audience)) )
301 {
302 LOG_SQLITE (plugin,
303 GNUNET_ERROR_TYPE_ERROR,
304 "precompiling");
305 return GNUNET_SYSERR;
306 }
307 return GNUNET_OK;
308}
309
310
311/**
312 * Shutdown database connection and associate data
313 * structures.
314 * @param plugin the plugin context (state for this module)
315 */
316static void
317database_shutdown (struct Plugin *plugin)
318{
319 int result;
320 sqlite3_stmt *stmt;
321
322 if (NULL != plugin->store_ticket)
323 sqlite3_finalize (plugin->store_ticket);
324 if (NULL != plugin->delete_ticket)
325 sqlite3_finalize (plugin->delete_ticket);
326 if (NULL != plugin->iterate_tickets)
327 sqlite3_finalize (plugin->iterate_tickets);
328 if (NULL != plugin->iterate_tickets_by_audience)
329 sqlite3_finalize (plugin->iterate_tickets_by_audience);
330 if (NULL != plugin->get_ticket_attrs)
331 sqlite3_finalize (plugin->get_ticket_attrs);
332 result = sqlite3_close (plugin->dbh);
333 if (result == SQLITE_BUSY)
334 {
335 LOG (GNUNET_ERROR_TYPE_WARNING,
336 _("Tried to close sqlite without finalizing all prepared statements.\n"));
337 stmt = sqlite3_next_stmt (plugin->dbh,
338 NULL);
339 while (NULL != stmt)
340 {
341 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
342 "sqlite",
343 "Closing statement %p\n",
344 stmt);
345 result = sqlite3_finalize (stmt);
346 if (result != SQLITE_OK)
347 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
348 "sqlite",
349 "Failed to close statement %p: %d\n",
350 stmt,
351 result);
352 stmt = sqlite3_next_stmt (plugin->dbh,
353 NULL);
354 }
355 result = sqlite3_close (plugin->dbh);
356 }
357 if (SQLITE_OK != result)
358 LOG_SQLITE (plugin,
359 GNUNET_ERROR_TYPE_ERROR,
360 "sqlite3_close");
361
362 GNUNET_free_non_null (plugin->fn);
363}
364
365
366/**
367 * Store a ticket in the database.
368 *
369 * @param cls closure (internal context for the plugin)
370 * @param ticket the ticket to persist
371 * @param attrs the attributes associated with the ticket
372 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
373 */
374static int
375identity_provider_sqlite_store_ticket (void *cls,
376 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
377 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
378{
379 struct Plugin *plugin = cls;
380 size_t attrs_len;
381 char *attrs_ser;
382 int n;
383
384 {
385 /* First delete duplicates */
386 struct GNUNET_SQ_QueryParam dparams[] = {
387 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
388 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
389 GNUNET_SQ_query_param_end
390 };
391 if (GNUNET_OK !=
392 GNUNET_SQ_bind (plugin->delete_ticket,
393 dparams))
394 {
395 LOG_SQLITE (plugin,
396 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
397 "sqlite3_bind_XXXX");
398 GNUNET_SQ_reset (plugin->dbh,
399 plugin->delete_ticket);
400 return GNUNET_SYSERR;
401 }
402 n = sqlite3_step (plugin->delete_ticket);
403 GNUNET_SQ_reset (plugin->dbh,
404 plugin->delete_ticket);
405
406 attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
407 attrs_ser = GNUNET_malloc (attrs_len);
408 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
409 attrs_ser);
410 struct GNUNET_SQ_QueryParam sparams[] = {
411 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
412 GNUNET_SQ_query_param_auto_from_type (&ticket->audience),
413 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
414 GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len),
415 GNUNET_SQ_query_param_end
416 };
417
418 if (GNUNET_OK !=
419 GNUNET_SQ_bind (plugin->store_ticket,
420 sparams))
421 {
422 LOG_SQLITE (plugin,
423 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
424 "sqlite3_bind_XXXX");
425 GNUNET_SQ_reset (plugin->dbh,
426 plugin->store_ticket);
427 return GNUNET_SYSERR;
428 }
429 n = sqlite3_step (plugin->store_ticket);
430 GNUNET_SQ_reset (plugin->dbh,
431 plugin->store_ticket);
432 GNUNET_free (attrs_ser);
433 }
434 switch (n)
435 {
436 case SQLITE_DONE:
437 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
438 "sqlite",
439 "Ticket stored\n");
440 return GNUNET_OK;
441 case SQLITE_BUSY:
442 LOG_SQLITE (plugin,
443 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
444 "sqlite3_step");
445 return GNUNET_NO;
446 default:
447 LOG_SQLITE (plugin,
448 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
449 "sqlite3_step");
450 return GNUNET_SYSERR;
451 }
452}
453
454
455/**
456 * Store a ticket in the database.
457 *
458 * @param cls closure (internal context for the plugin)
459 * @param ticket the ticket to delete
460 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
461 */
462static int
463identity_provider_sqlite_delete_ticket (void *cls,
464 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
465{
466 struct Plugin *plugin = cls;
467 int n;
468
469 {
470 struct GNUNET_SQ_QueryParam sparams[] = {
471 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
472 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
473 GNUNET_SQ_query_param_end
474 };
475
476 if (GNUNET_OK !=
477 GNUNET_SQ_bind (plugin->delete_ticket,
478 sparams))
479 {
480 LOG_SQLITE (plugin,
481 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
482 "sqlite3_bind_XXXX");
483 GNUNET_SQ_reset (plugin->dbh,
484 plugin->store_ticket);
485 return GNUNET_SYSERR;
486 }
487 n = sqlite3_step (plugin->delete_ticket);
488 GNUNET_SQ_reset (plugin->dbh,
489 plugin->delete_ticket);
490 }
491 switch (n)
492 {
493 case SQLITE_DONE:
494 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
495 "sqlite",
496 "Ticket deleted\n");
497 return GNUNET_OK;
498 case SQLITE_BUSY:
499 LOG_SQLITE (plugin,
500 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
501 "sqlite3_step");
502 return GNUNET_NO;
503 default:
504 LOG_SQLITE (plugin,
505 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
506 "sqlite3_step");
507 return GNUNET_SYSERR;
508 }
509}
510
511
512/**
513 * The given 'sqlite' statement has been prepared to be run.
514 * It will return a record which should be given to the iterator.
515 * Runs the statement and parses the returned record.
516 *
517 * @param plugin plugin context
518 * @param stmt to run (and then clean up)
519 * @param iter iterator to call with the result
520 * @param iter_cls closure for @a iter
521 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
522 */
523static int
524get_ticket_and_call_iterator (struct Plugin *plugin,
525 sqlite3_stmt *stmt,
526 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
527 void *iter_cls)
528{
529 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
530 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
531 int ret;
532 int sret;
533 size_t attrs_len;
534 char *attrs_ser;
535
536 ret = GNUNET_NO;
537 if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
538 {
539 struct GNUNET_SQ_ResultSpec rs[] = {
540 GNUNET_SQ_result_spec_auto_from_type (&ticket.identity),
541 GNUNET_SQ_result_spec_auto_from_type (&ticket.audience),
542 GNUNET_SQ_result_spec_uint64 (&ticket.rnd),
543 GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser,
544 &attrs_len),
545 GNUNET_SQ_result_spec_end
546
547 };
548 ret = GNUNET_SQ_extract_result (stmt,
549 rs);
550 if (GNUNET_OK != ret)
551 {
552 GNUNET_break (0);
553 ret = GNUNET_SYSERR;
554 }
555 else
556 {
557 attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (attrs_ser,
558 attrs_len);
559 if (NULL != iter)
560 iter (iter_cls,
561 &ticket,
562 attrs);
563 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
564 ret = GNUNET_YES;
565 }
566 GNUNET_SQ_cleanup_result (rs);
567 }
568 else
569 {
570 if (SQLITE_DONE != sret)
571 LOG_SQLITE (plugin,
572 GNUNET_ERROR_TYPE_ERROR,
573 "sqlite_step");
574 }
575 GNUNET_SQ_reset (plugin->dbh,
576 stmt);
577 return ret;
578}
579
580
581/**
582 * Lookup tickets in the datastore.
583 *
584 * @param cls closure (internal context for the plugin)
585 * @param ticket the ticket to retrieve attributes for
586 * @param iter function to call with the result
587 * @param iter_cls closure for @a iter
588 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
589 */
590static int
591identity_provider_sqlite_ticket_get_attrs (void *cls,
592 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
593 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
594 void *iter_cls)
595{
596 struct Plugin *plugin = cls;
597 struct GNUNET_SQ_QueryParam params[] = {
598 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
599 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
600 GNUNET_SQ_query_param_end
601 };
602
603 if (GNUNET_OK !=
604 GNUNET_SQ_bind (plugin->get_ticket_attrs,
605 params))
606 {
607 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
608 "sqlite3_bind_XXXX");
609 GNUNET_SQ_reset (plugin->dbh,
610 plugin->get_ticket_attrs);
611 return GNUNET_SYSERR;
612 }
613 return get_ticket_and_call_iterator (plugin,
614 plugin->get_ticket_attrs,
615 iter,
616 iter_cls);
617}
618
619
620/**
621 * Iterate over the results for a particular key and zone in the
622 * datastore. Will return at most one result to the iterator.
623 *
624 * @param cls closure (internal context for the plugin)
625 * @param identity the issuing identity or audience (depending on audience switch)
626 * @param audience GNUNET_YES if identity is audience
627 * @param offset offset in the list of all matching records
628 * @param iter function to call with the result
629 * @param iter_cls closure for @a iter
630 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
631 */
632static int
633identity_provider_sqlite_iterate_tickets (void *cls,
634 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
635 int audience,
636 uint64_t offset,
637 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
638 void *iter_cls)
639{
640 struct Plugin *plugin = cls;
641 sqlite3_stmt *stmt;
642 int err;
643
644 if (NULL == identity)
645 {
646 GNUNET_break (0);
647 return GNUNET_SYSERR;
648 }
649 struct GNUNET_SQ_QueryParam params[] = {
650 GNUNET_SQ_query_param_auto_from_type (identity),
651 GNUNET_SQ_query_param_uint64 (&offset),
652 GNUNET_SQ_query_param_end
653 };
654 if (GNUNET_YES == audience)
655 {
656 stmt = plugin->iterate_tickets_by_audience;
657 err = GNUNET_SQ_bind (stmt,
658 params);
659 }
660 else
661 {
662 stmt = plugin->iterate_tickets;
663 err = GNUNET_SQ_bind (stmt,
664 params);
665 }
666 if (GNUNET_OK != err)
667 {
668 LOG_SQLITE (plugin,
669 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
670 "sqlite3_bind_XXXX");
671 GNUNET_SQ_reset (plugin->dbh,
672 stmt);
673 return GNUNET_SYSERR;
674 }
675 return get_ticket_and_call_iterator (plugin,
676 stmt,
677 iter,
678 iter_cls);
679}
680
681
682/**
683 * Entry point for the plugin.
684 *
685 * @param cls the "struct GNUNET_IDENTITY_PROVIDER_PluginEnvironment*"
686 * @return NULL on error, otherwise the plugin context
687 */
688void *
689libgnunet_plugin_identity_provider_sqlite_init (void *cls)
690{
691 static struct Plugin plugin;
692 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
693 struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api;
694
695 if (NULL != plugin.cfg)
696 return NULL; /* can only initialize once! */
697 memset (&plugin, 0, sizeof (struct Plugin));
698 plugin.cfg = cfg;
699 if (GNUNET_OK != database_setup (&plugin))
700 {
701 database_shutdown (&plugin);
702 return NULL;
703 }
704 api = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_PluginFunctions);
705 api->cls = &plugin;
706 api->store_ticket = &identity_provider_sqlite_store_ticket;
707 api->delete_ticket = &identity_provider_sqlite_delete_ticket;
708 api->iterate_tickets = &identity_provider_sqlite_iterate_tickets;
709 api->get_ticket_attributes = &identity_provider_sqlite_ticket_get_attrs;
710 LOG (GNUNET_ERROR_TYPE_INFO,
711 _("Sqlite database running\n"));
712 return api;
713}
714
715
716/**
717 * Exit point from the plugin.
718 *
719 * @param cls the plugin context (as returned by "init")
720 * @return always NULL
721 */
722void *
723libgnunet_plugin_identity_provider_sqlite_done (void *cls)
724{
725 struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api = cls;
726 struct Plugin *plugin = api->cls;
727
728 database_shutdown (plugin);
729 plugin->cfg = NULL;
730 GNUNET_free (api);
731 LOG (GNUNET_ERROR_TYPE_DEBUG,
732 "sqlite plugin is finished\n");
733 return NULL;
734}
735
736/* end of plugin_identity_provider_sqlite.c */
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c
index 907b28ba9..6eb856435 100644
--- a/src/identity-provider/plugin_rest_identity_provider.c
+++ b/src/identity-provider/plugin_rest_identity_provider.c
@@ -37,6 +37,7 @@
37#include <jansson.h> 37#include <jansson.h>
38#include <inttypes.h> 38#include <inttypes.h>
39#include "gnunet_signatures.h" 39#include "gnunet_signatures.h"
40#include "gnunet_identity_attribute_lib.h"
40#include "gnunet_identity_provider_service.h" 41#include "gnunet_identity_provider_service.h"
41 42
42/** 43/**
@@ -45,39 +46,40 @@
45#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp" 46#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp"
46 47
47/** 48/**
48 * Issue namespace 49 * Attribute namespace
49 */ 50 */
50#define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/idp/issue" 51#define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes"
51 52
52/** 53/**
53 * Check namespace TODO 54 * Ticket namespace
54 */ 55 */
55#define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/idp/check" 56#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets"
56 57
57/** 58/**
58 * Token namespace 59 * Revoke namespace
59 */ 60 */
60#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token" 61#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke"
61 62
62/** 63/**
63 * The parameter name in which the ticket must be provided 64 * Revoke namespace
64 */ 65 */
65#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket" 66#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume"
66 67
67/** 68/**
68 * The parameter name in which the expected nonce must be provided 69 * Attribute key
69 */ 70 */
70#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce" 71#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute"
71 72
72/** 73/**
73 * The parameter name in which the ticket must be provided 74 * Ticket key
74 */ 75 */
75#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token" 76#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
77
76 78
77/** 79/**
78 * The URL parameter name in which the nonce must be provided 80 * Value key
79 */ 81 */
80#define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce" 82#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value"
81 83
82/** 84/**
83 * State while collecting all egos 85 * State while collecting all egos
@@ -89,41 +91,6 @@
89 */ 91 */
90#define ID_REST_STATE_POST_INIT 1 92#define ID_REST_STATE_POST_INIT 1
91 93
92/**
93 * Resource type
94 */
95#define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
96
97/**
98 * URL parameter to create a GNUid token for a specific audience
99 */
100#define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
101
102/**
103 * URL parameter to create a GNUid token for a specific issuer (EGO)
104 */
105#define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
106
107/**
108 * Attributes passed to issue request
109 */
110#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
111
112/**
113 * Token expiration string
114 */
115#define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
116
117/**
118 * Error messages
119 */
120#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
121#define GNUNET_REST_ERROR_NO_DATA "No data"
122
123/**
124 * GNUid token lifetime
125 */
126#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
127 94
128/** 95/**
129 * The configuration handle 96 * The configuration handle
@@ -198,11 +165,6 @@ struct RequestHandle
198 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 165 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
199 166
200 /** 167 /**
201 * Handle to the rest connection
202 */
203 struct GNUNET_REST_RequestHandle *conndata_handle;
204
205 /**
206 * The processing state 168 * The processing state
207 */ 169 */
208 int state; 170 int state;
@@ -213,6 +175,12 @@ struct RequestHandle
213 struct GNUNET_IDENTITY_Handle *identity_handle; 175 struct GNUNET_IDENTITY_Handle *identity_handle;
214 176
215 /** 177 /**
178 * Rest connection
179 */
180 struct GNUNET_REST_RequestHandle *rest_handle;
181
182
183 /**
216 * IDENTITY Operation 184 * IDENTITY Operation
217 */ 185 */
218 struct GNUNET_IDENTITY_Operation *op; 186 struct GNUNET_IDENTITY_Operation *op;
@@ -228,19 +196,14 @@ struct RequestHandle
228 struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; 196 struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
229 197
230 /** 198 /**
231 * Handle to NS service 199 * Attribute iterator
232 */
233 struct GNUNET_NAMESTORE_Handle *ns_handle;
234
235 /**
236 * NS iterator
237 */ 200 */
238 struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 201 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
239 202
240 /** 203 /**
241 * NS Handle 204 * Ticket iterator
242 */ 205 */
243 struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 206 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
244 207
245 /** 208 /**
246 * Desired timeout for the lookup (default is no timeout). 209 * Desired timeout for the lookup (default is no timeout).
@@ -285,6 +248,7 @@ struct RequestHandle
285}; 248};
286 249
287 250
251
288/** 252/**
289 * Cleanup lookup handle 253 * Cleanup lookup handle
290 * @param handle Handle to clean up 254 * @param handle Handle to clean up
@@ -302,14 +266,12 @@ cleanup_handle (struct RequestHandle *handle)
302 GNUNET_SCHEDULER_cancel (handle->timeout_task); 266 GNUNET_SCHEDULER_cancel (handle->timeout_task);
303 if (NULL != handle->identity_handle) 267 if (NULL != handle->identity_handle)
304 GNUNET_IDENTITY_disconnect (handle->identity_handle); 268 GNUNET_IDENTITY_disconnect (handle->identity_handle);
269 if (NULL != handle->attr_it)
270 GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it);
271 if (NULL != handle->ticket_it)
272 GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it);
305 if (NULL != handle->idp) 273 if (NULL != handle->idp)
306 GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp); 274 GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
307 if (NULL != handle->ns_it)
308 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
309 if (NULL != handle->ns_qe)
310 GNUNET_NAMESTORE_cancel (handle->ns_qe);
311 if (NULL != handle->ns_handle)
312 GNUNET_NAMESTORE_disconnect (handle->ns_handle);
313 if (NULL != handle->url) 275 if (NULL != handle->url)
314 GNUNET_free (handle->url); 276 GNUNET_free (handle->url);
315 if (NULL != handle->emsg) 277 if (NULL != handle->emsg)
@@ -326,6 +288,12 @@ cleanup_handle (struct RequestHandle *handle)
326 GNUNET_free (handle); 288 GNUNET_free (handle);
327} 289}
328 290
291static void
292cleanup_handle_delayed (void *cls)
293{
294 cleanup_handle (cls);
295}
296
329 297
330/** 298/**
331 * Task run on error, sends error message. Cleans up everything. 299 * Task run on error, sends error message. Cleans up everything.
@@ -363,622 +331,663 @@ do_timeout (void *cls)
363} 331}
364 332
365 333
366/**
367 * Task run on shutdown. Cleans up everything.
368 *
369 * @param cls unused
370 */
371static void 334static void
372do_cleanup_handle_delayed (void *cls) 335collect_error_cb (void *cls)
373{ 336{
374 struct RequestHandle *handle = cls; 337 struct RequestHandle *handle = cls;
375 338
376 cleanup_handle (handle); 339 do_error (handle);
377} 340}
378 341
379
380/**
381 * Get a ticket for identity
382 * @param cls the handle
383 * @param ticket the ticket returned from the idp
384 */
385static void 342static void
386token_creat_cont (void *cls, 343finished_cont (void *cls,
387 const char *label, 344 int32_t success,
388 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, 345 const char *emsg)
389 const struct GNUNET_IDENTITY_PROVIDER_Token *token)
390{ 346{
391 struct GNUNET_JSONAPI_Resource *json_resource;
392 struct RequestHandle *handle = cls; 347 struct RequestHandle *handle = cls;
393 struct MHD_Response *resp; 348 struct MHD_Response *resp;
394 json_t *ticket_json;
395 json_t *token_json;
396 char *ticket_str;
397 char *token_str;
398 char *result_str;
399 349
400 if (NULL == ticket) 350 resp = GNUNET_REST_create_response (emsg);
351 if (GNUNET_OK != success)
401 { 352 {
402 handle->emsg = GNUNET_strdup ("Error in token issue");
403 GNUNET_SCHEDULER_add_now (&do_error, handle); 353 GNUNET_SCHEDULER_add_now (&do_error, handle);
404 return; 354 return;
405 } 355 }
356 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
357 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
358}
406 359
407 handle->resp_object = GNUNET_JSONAPI_document_new (); 360
408 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 361/**
409 label); 362 * Return attributes for identity
410 ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket); 363 *
411 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token); 364 * @param cls the request handle
412 ticket_json = json_string (ticket_str); 365 */
413 token_json = json_string (token_str); 366static void
414 GNUNET_JSONAPI_resource_add_attr (json_resource, 367return_response (void *cls)
415 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 368{
416 ticket_json); 369 char* result_str;
417 GNUNET_JSONAPI_resource_add_attr (json_resource, 370 struct RequestHandle *handle = cls;
418 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN, 371 struct MHD_Response *resp;
419 token_json);
420 GNUNET_free (ticket_str);
421 GNUNET_free (token_str);
422 json_decref (ticket_json);
423 json_decref (token_json);
424 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
425 372
426 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str); 373 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
428 resp = GNUNET_REST_create_response (result_str); 375 resp = GNUNET_REST_create_response (result_str);
429 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 376 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
430 GNUNET_free (result_str); 377 GNUNET_free (result_str);
431 GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle); 378 cleanup_handle (handle);
379}
380
381
382static void
383collect_finished_cb (void *cls)
384{
385 struct RequestHandle *handle = cls;
386 //Done
387 handle->attr_it = NULL;
388 handle->ticket_it = NULL;
389 GNUNET_SCHEDULER_add_now (&return_response, handle);
432} 390}
433 391
434 392
435/** 393/**
436 * Continueationf for token issue request 394 * Collect all attributes for an ego
437 * 395 *
438 * @param con the Rest handle
439 * @param url the requested url
440 * @param cls the request handle
441 */ 396 */
442static void 397static void
443issue_token_cont (struct GNUNET_REST_RequestHandle *con, 398ticket_collect (void *cls,
444 const char *url, 399 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
445 void *cls)
446{ 400{
447 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 401 struct GNUNET_JSONAPI_Resource *json_resource;
448 const char *egoname; 402 struct RequestHandle *handle = cls;
403 json_t *value;
404 char* tmp;
405
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
407 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
408 sizeof (uint64_t));
409 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET,
410 tmp);
411 GNUNET_free (tmp);
412 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
413
414 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
415 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
416 value = json_string (tmp);
417 GNUNET_JSONAPI_resource_add_attr (json_resource,
418 "issuer",
419 value);
420 GNUNET_free (tmp);
421 json_decref (value);
422 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
423 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
424 value = json_string (tmp);
425 GNUNET_JSONAPI_resource_add_attr (json_resource,
426 "audience",
427 value);
428 GNUNET_free (tmp);
429 json_decref (value);
430 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
431 sizeof (uint64_t));
432 value = json_string (tmp);
433 GNUNET_JSONAPI_resource_add_attr (json_resource,
434 "rnd",
435 value);
436 GNUNET_free (tmp);
437 json_decref (value);
438 GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (handle->ticket_it);
439}
440
449 441
442
443/**
444 * List tickets for identity request
445 *
446 * @param con_handle the connection handle
447 * @param url the url
448 * @param cls the RequestHandle
449 */
450static void
451list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
452 const char* url,
453 void *cls)
454{
455 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
450 struct RequestHandle *handle = cls; 456 struct RequestHandle *handle = cls;
451 struct EgoEntry *ego_entry; 457 struct EgoEntry *ego_entry;
452 struct GNUNET_HashCode key; 458 char *identity;
453 struct MHD_Response *resp; 459
454 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
455 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 461 handle->url);
456 struct GNUNET_TIME_Relative etime_rel; 462 if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
457 struct GNUNET_TIME_Absolute exp_time; 463 strlen (handle->url))
458 char *ego_val;
459 char *audience;
460 char *exp_str;
461 char *nonce_str;
462 char *scopes;
463 uint64_t time;
464 uint64_t nonce;
465
466 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
467 GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
468 {
469 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
470 resp = GNUNET_REST_create_response (NULL);
471 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
472 cleanup_handle (handle);
473 return;
474 }
475 egoname = NULL;
476 ego_entry = NULL;
477 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
478 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
479 &key);
480 if ( GNUNET_YES !=
481 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
482 &key) )
483 {
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
485 "Issuer not found\n");
486 GNUNET_SCHEDULER_add_now (&do_error, handle);
487 return;
488 }
489 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
490 &key);
491 if (NULL == ego_val)
492 { 464 {
465 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
493 GNUNET_SCHEDULER_add_now (&do_error, handle); 466 GNUNET_SCHEDULER_add_now (&do_error, handle);
494 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
495 "Ego invalid: %s\n",
496 ego_val);
497 return; 467 return;
498 } 468 }
469 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
470
499 for (ego_entry = handle->ego_head; 471 for (ego_entry = handle->ego_head;
500 NULL != ego_entry; 472 NULL != ego_entry;
501 ego_entry = ego_entry->next) 473 ego_entry = ego_entry->next)
474 if (0 == strcmp (identity, ego_entry->identifier))
475 break;
476 handle->resp_object = GNUNET_JSONAPI_document_new ();
477
478 if (NULL == ego_entry)
502 { 479 {
503 if (0 != strcmp (ego_val, ego_entry->identifier)) 480 //Done
504 continue; 481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
505 egoname = ego_entry->identifier; 482 identity);
506 break; 483 GNUNET_SCHEDULER_add_now (&return_response, handle);
507 }
508 if ( (NULL == egoname) ||
509 (NULL == ego_entry) )
510 {
511 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
512 "Ego not found: %s\n",
513 ego_val);
514 GNUNET_SCHEDULER_add_now (&do_error, handle);
515 return; 484 return;
516 } 485 }
517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 486 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
518 "Ego to issue token for: %s\n", 487 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
519 egoname); 488 handle->ticket_it = GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (handle->idp,
489 priv_key,
490 &collect_error_cb,
491 handle,
492 &ticket_collect,
493 handle,
494 &collect_finished_cb,
495 handle);
496}
520 497
521 498
522 //Meta info 499static void
523 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST, 500add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
524 strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST), 501 const char* url,
525 &key); 502 void *cls)
503{
504 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
505 const char* identity;
506 const char* name_str;
507 const char* value_str;
526 508
527 scopes = NULL; 509 struct RequestHandle *handle = cls;
528 if ( GNUNET_YES != 510 struct EgoEntry *ego_entry;
529 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 511 struct MHD_Response *resp;
530 &key) ) 512 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attribute;
513 struct GNUNET_JSONAPI_Document *json_obj;
514 struct GNUNET_JSONAPI_Resource *json_res;
515 char term_data[handle->rest_handle->data_size+1];
516 json_t *value_json;
517 json_t *data_json;
518 json_error_t err;
519 struct GNUNET_JSON_Specification docspec[] = {
520 GNUNET_JSON_spec_jsonapi_document (&json_obj),
521 GNUNET_JSON_spec_end()
522 };
523
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
525 handle->url);
526 if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
527 strlen (handle->url))
531 { 528 {
532 handle->emsg = GNUNET_strdup ("Scopes missing!\n"); 529 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
533 GNUNET_SCHEDULER_add_now (&do_error, handle); 530 GNUNET_SCHEDULER_add_now (&do_error, handle);
534 return; 531 return;
535 } 532 }
536 scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 533 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
537 &key); 534
538 535 for (ego_entry = handle->ego_head;
539 536 NULL != ego_entry;
540 //Token audience 537 ego_entry = ego_entry->next)
541 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST, 538 if (0 == strcmp (identity, ego_entry->identifier))
542 strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST), 539 break;
543 &key); 540
544 audience = NULL; 541 if (NULL == ego_entry)
545 if ( GNUNET_YES !=
546 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
547 &key) )
548 { 542 {
549 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 543 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
550 "Audience missing!\n"); 544 "Identity unknown (%s)\n", identity);
551 GNUNET_SCHEDULER_add_now (&do_error, handle); 545 GNUNET_JSONAPI_document_delete (json_obj);
552 return; 546 return;
553 } 547 }
554 audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 548 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
555 &key);
556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
557 "Audience to issue token for: %s\n",
558 audience);
559
560 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
561 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
562 &pub_key);
563 GNUNET_STRINGS_string_to_data (audience,
564 strlen (audience),
565 &aud_key,
566 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
567 549
568 //Remote nonce 550 if (0 >= handle->rest_handle->data_size)
569 nonce_str = NULL;
570 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
571 strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
572 &key);
573 if ( GNUNET_YES !=
574 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
575 &key) )
576 { 551 {
577 handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
578 GNUNET_SCHEDULER_add_now (&do_error, handle); 552 GNUNET_SCHEDULER_add_now (&do_error, handle);
579 return; 553 return;
580 } 554 }
581 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 555
582 &key); 556 term_data[handle->rest_handle->data_size] = '\0';
583 GNUNET_assert (NULL != nonce_str); 557 GNUNET_memcpy (term_data,
584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 558 handle->rest_handle->data,
585 "Request nonce: %s\n", 559 handle->rest_handle->data_size);
586 nonce_str); 560 data_json = json_loads (term_data,
587 GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce)); 561 JSON_DECODE_ANY,
588 562 &err);
589 //Get expiration for token from URL parameter 563 GNUNET_assert (GNUNET_OK ==
590 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING, 564 GNUNET_JSON_parse (data_json, docspec,
591 strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING), 565 NULL, NULL));
592 &key); 566 json_decref (data_json);
593 567 if (NULL == json_obj)
594 exp_str = NULL;
595 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
596 &key))
597 { 568 {
598 exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 569 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
599 &key); 570 "Unable to parse JSONAPI Object from %s\n",
600 } 571 term_data);
601 if (NULL == exp_str) {
602 handle->emsg = GNUNET_strdup ("No expiration given!\n");
603 GNUNET_SCHEDULER_add_now (&do_error, handle); 572 GNUNET_SCHEDULER_add_now (&do_error, handle);
604 return; 573 return;
605 } 574 }
606 575 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
607 if (GNUNET_OK !=
608 GNUNET_STRINGS_fancy_time_to_relative (exp_str,
609 &etime_rel))
610 { 576 {
611 handle->emsg = GNUNET_strdup ("Expiration invalid!\n"); 577 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
578 "Cannot create more than 1 resource! (Got %d)\n",
579 GNUNET_JSONAPI_document_resource_count (json_obj));
580 GNUNET_JSONAPI_document_delete (json_obj);
612 GNUNET_SCHEDULER_add_now (&do_error, handle); 581 GNUNET_SCHEDULER_add_now (&do_error, handle);
613 return; 582 return;
614 } 583 }
615 time = GNUNET_TIME_absolute_get().abs_value_us; 584 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
616 exp_time.abs_value_us = time + etime_rel.rel_value_us; 585 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
617 586 GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE))
587 {
588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
589 "Unsupported JSON data type\n");
590 GNUNET_JSONAPI_document_delete (json_obj);
591 resp = GNUNET_REST_create_response (NULL);
592 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
593 cleanup_handle (handle);
594 return;
595 }
596 name_str = GNUNET_JSONAPI_resource_get_id (json_res);
597 value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
598 "value");
599 value_str = json_string_value (value_json);
600 attribute = GNUNET_IDENTITY_ATTRIBUTE_claim_new (name_str,
601 GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
602 value_str,
603 strlen (value_str) + 1);
618 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); 604 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
619 handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp, 605 handle->idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (handle->idp,
620 priv_key, 606 identity_priv,
621 &aud_key, 607 attribute,
622 scopes, 608 &finished_cont,
623 exp_time, 609 handle);
624 nonce, 610 GNUNET_free (attribute);
625 &token_creat_cont, 611 GNUNET_JSONAPI_document_delete (json_obj);
626 handle);
627
628}
629
630
631/**
632 * Build a GNUid token for identity
633 *
634 * @param cls the request handle
635 */
636static void
637return_token_list (void *cls)
638{
639 char* result_str;
640 struct RequestHandle *handle = cls;
641 struct MHD_Response *resp;
642
643 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
645 resp = GNUNET_REST_create_response (result_str);
646 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
647 GNUNET_free (result_str);
648 cleanup_handle (handle);
649} 612}
650 613
651 614
652static void
653token_collect_error_cb (void *cls)
654{
655 struct RequestHandle *handle = cls;
656
657 do_error (handle);
658}
659
660 615
661/** 616/**
662 * Collect all tokens for an ego 617 * Collect all attributes for an ego
663 *
664 * TODO move this into the identity-provider service
665 * 618 *
666 */ 619 */
667static void 620static void
668token_collect (void *cls, 621attr_collect (void *cls,
669 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 622 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
670 const char *label, 623 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
671 unsigned int rd_count,
672 const struct GNUNET_GNSRECORD_Data *rd);
673
674
675static void
676token_collect_finished_cb (void *cls)
677{ 624{
625 struct GNUNET_JSONAPI_Resource *json_resource;
678 struct RequestHandle *handle = cls; 626 struct RequestHandle *handle = cls;
679 struct EgoEntry *ego_tmp; 627 json_t *value;
680 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 628
681 629 if ((NULL == attr->name) || (NULL == attr->data))
682 ego_tmp = handle->ego_head;
683 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
684 handle->ego_tail,
685 ego_tmp);
686 GNUNET_free (ego_tmp->identifier);
687 GNUNET_free (ego_tmp->keystring);
688 GNUNET_free (ego_tmp);
689
690 if (NULL == handle->ego_head)
691 { 630 {
692 //Done 631 GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
694 handle->ns_it = NULL;
695 GNUNET_SCHEDULER_add_now (&return_token_list, handle);
696 return; 632 return;
697 } 633 }
698 634
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
700 "Next ego: %s\n", 636 attr->name);
701 handle->ego_head->identifier); 637 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
702 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); 638 attr->name);
703 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, 639 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
704 priv_key,
705 &token_collect_error_cb,
706 handle,
707 &token_collect,
708 handle,
709 &token_collect_finished_cb,
710 handle);
711}
712
713
714/**
715 * Collect all tokens for an ego
716 *
717 * TODO move this into the identity-provider service
718 *
719 */
720static void
721token_collect (void *cls,
722 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
723 const char *label,
724 unsigned int rd_count,
725 const struct GNUNET_GNSRECORD_Data *rd)
726{
727 struct RequestHandle *handle = cls;
728 int i;
729 char* data;
730 struct GNUNET_JSONAPI_Resource *json_resource;
731 json_t *issuer;
732 json_t *token;
733
734 for (i = 0; i < rd_count; i++)
735 {
736 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
737 {
738 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
739 rd[i].data,
740 rd[i].data_size);
741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
742 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
743 label);
744 issuer = json_string (handle->ego_head->identifier);
745 GNUNET_JSONAPI_resource_add_attr (json_resource,
746 GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
747 issuer);
748 json_decref (issuer);
749 token = json_string (data);
750 GNUNET_JSONAPI_resource_add_attr (json_resource,
751 GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
752 token);
753 json_decref (token);
754
755 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
756 GNUNET_free (data);
757 }
758 }
759 640
760 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 641 value = json_string (attr->data);
642 GNUNET_JSONAPI_resource_add_attr (json_resource,
643 "value",
644 value);
645 json_decref (value);
646 GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
761} 647}
762 648
763 649
764 650
765/** 651/**
766 * Respond to OPTIONS request 652 * List attributes for identity request
767 * 653 *
768 * @param con_handle the connection handle 654 * @param con_handle the connection handle
769 * @param url the url 655 * @param url the url
770 * @param cls the RequestHandle 656 * @param cls the RequestHandle
771 */ 657 */
772static void 658static void
773list_token_cont (struct GNUNET_REST_RequestHandle *con_handle, 659list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
774 const char* url, 660 const char* url,
775 void *cls) 661 void *cls)
776{ 662{
777 char* ego_val;
778 struct GNUNET_HashCode key;
779 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 663 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
780 struct RequestHandle *handle = cls; 664 struct RequestHandle *handle = cls;
781 struct EgoEntry *ego_entry; 665 struct EgoEntry *ego_entry;
782 struct EgoEntry *ego_tmp; 666 char *identity;
783 667
784 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST, 668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
785 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST), 669 handle->url);
786 &key); 670 if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
787 671 strlen (handle->url))
788 if ( GNUNET_YES !=
789 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
790 &key) )
791 { 672 {
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No issuer given.\n"); 673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
793 GNUNET_SCHEDULER_add_now (&do_error, handle); 674 GNUNET_SCHEDULER_add_now (&do_error, handle);
794 return; 675 return;
795 } 676 }
796 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 677 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
797 &key); 678
798 GNUNET_assert (NULL != ego_val);
799 //Remove non-matching egos
800 for (ego_entry = handle->ego_head; 679 for (ego_entry = handle->ego_head;
801 NULL != ego_entry;) 680 NULL != ego_entry;
802 { 681 ego_entry = ego_entry->next)
803 ego_tmp = ego_entry; 682 if (0 == strcmp (identity, ego_entry->identifier))
804 ego_entry = ego_entry->next; 683 break;
805 if (0 != strcmp (ego_val, ego_tmp->identifier))
806 {
807 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
808 handle->ego_tail,
809 ego_tmp);
810 GNUNET_free (ego_tmp->identifier);
811 GNUNET_free (ego_tmp->keystring);
812 GNUNET_free (ego_tmp);
813 }
814 }
815 handle->resp_object = GNUNET_JSONAPI_document_new (); 684 handle->resp_object = GNUNET_JSONAPI_document_new ();
816 if (NULL == handle->ego_head) 685
686
687 if (NULL == ego_entry)
817 { 688 {
818 //Done 689 //Done
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n"); 690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
820 GNUNET_SCHEDULER_add_now (&return_token_list, handle); 691 identity);
692 GNUNET_SCHEDULER_add_now (&return_response, handle);
821 return; 693 return;
822 } 694 }
823 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); 695 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
824 handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); 696 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
825 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, 697 handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (handle->idp,
826 priv_key, 698 priv_key,
827 &token_collect_error_cb, 699 &collect_error_cb,
828 handle, 700 handle,
829 &token_collect, 701 &attr_collect,
830 handle, 702 handle,
831 &token_collect_finished_cb, 703 &collect_finished_cb,
832 handle); 704 handle);
833
834} 705}
835 706
836/** 707
837 * Return token to requestor
838 *
839 * @param cls request handle
840 * @param token the token
841 */
842static void 708static void
843exchange_cont (void *cls, 709revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
844 const struct GNUNET_IDENTITY_PROVIDER_Token *token, 710 const char* url,
845 uint64_t ticket_nonce) 711 void *cls)
846{ 712{
847 json_t *root; 713 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
714 const char* identity_str;
715 const char* audience_str;
716 const char* rnd_str;
717
848 struct RequestHandle *handle = cls; 718 struct RequestHandle *handle = cls;
719 struct EgoEntry *ego_entry;
849 struct MHD_Response *resp; 720 struct MHD_Response *resp;
850 struct GNUNET_HashCode key; 721 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
851 char* result; 722 struct GNUNET_JSONAPI_Document *json_obj;
852 char* token_str; 723 struct GNUNET_JSONAPI_Resource *json_res;
853 char* nonce_str; 724 struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
854 uint64_t expected_nonce; 725 char term_data[handle->rest_handle->data_size+1];
855 726 json_t *rnd_json;
856 //Get nonce 727 json_t *identity_json;
857 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE, 728 json_t *audience_json;
858 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE), 729 json_t *data_json;
859 &key); 730 json_error_t err;
860 731 struct GNUNET_JSON_Specification docspec[] = {
861 if ( GNUNET_NO == 732 GNUNET_JSON_spec_jsonapi_document (&json_obj),
862 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 733 GNUNET_JSON_spec_end()
863 &key) ) 734 };
735
736 if (0 >= handle->rest_handle->data_size)
864 { 737 {
865 handle->emsg = GNUNET_strdup ("No nonce given.");
866 GNUNET_SCHEDULER_add_now (&do_error, handle); 738 GNUNET_SCHEDULER_add_now (&do_error, handle);
867 return; 739 return;
868 } 740 }
869 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
870 &key);
871 GNUNET_assert (NULL != nonce_str);
872 GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
873 741
874 if (ticket_nonce != expected_nonce) 742 term_data[handle->rest_handle->data_size] = '\0';
743 GNUNET_memcpy (term_data,
744 handle->rest_handle->data,
745 handle->rest_handle->data_size);
746 data_json = json_loads (term_data,
747 JSON_DECODE_ANY,
748 &err);
749 GNUNET_assert (GNUNET_OK ==
750 GNUNET_JSON_parse (data_json, docspec,
751 NULL, NULL));
752 json_decref (data_json);
753 if (NULL == json_obj)
754 {
755 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
756 "Unable to parse JSONAPI Object from %s\n",
757 term_data);
758 GNUNET_SCHEDULER_add_now (&do_error, handle);
759 return;
760 }
761 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
875 { 762 {
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
877 "Ticket nonce %"SCNu64" does not match expected nonce %"SCNu64"\n", 764 "Cannot create more than 1 resource! (Got %d)\n",
878 ticket_nonce, expected_nonce); 765 GNUNET_JSONAPI_document_resource_count (json_obj));
879 handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n"); 766 GNUNET_JSONAPI_document_delete (json_obj);
880 GNUNET_SCHEDULER_add_now (&do_error, handle); 767 GNUNET_SCHEDULER_add_now (&do_error, handle);
881 return; 768 return;
882 } 769 }
770 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
771 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
772 GNUNET_REST_JSONAPI_IDENTITY_TICKET))
773 {
774 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
775 "Unsupported JSON data type\n");
776 GNUNET_JSONAPI_document_delete (json_obj);
777 resp = GNUNET_REST_create_response (NULL);
778 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
779 cleanup_handle (handle);
780 return;
781 }
782 rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
783 "rnd");
784 identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
785 "identity");
786 audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
787 "audience");
788 rnd_str = json_string_value (rnd_json);
789 identity_str = json_string_value (identity_json);
790 audience_str = json_string_value (audience_json);
791
792 GNUNET_STRINGS_string_to_data (rnd_str,
793 strlen (rnd_str),
794 &ticket.rnd,
795 sizeof (uint64_t));
796 GNUNET_STRINGS_string_to_data (identity_str,
797 strlen (identity_str),
798 &ticket.identity,
799 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
800 GNUNET_STRINGS_string_to_data (audience_str,
801 strlen (audience_str),
802 &ticket.audience,
803 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
883 804
884 root = json_object (); 805 for (ego_entry = handle->ego_head;
885 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token); 806 NULL != ego_entry;
886 json_object_set_new (root, "token", json_string (token_str)); 807 ego_entry = ego_entry->next)
887 json_object_set_new (root, "token_type", json_string ("jwt")); 808 {
888 GNUNET_free (token_str); 809 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
810 &tmp_pk);
811 if (0 == memcmp (&ticket.identity,
812 &tmp_pk,
813 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
814 break;
815 }
816 if (NULL == ego_entry)
817 {
818 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
819 "Identity unknown (%s)\n", identity_str);
820 GNUNET_JSONAPI_document_delete (json_obj);
821 return;
822 }
823 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
889 824
890 result = json_dumps (root, JSON_INDENT(1)); 825 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
891 resp = GNUNET_REST_create_response (result); 826 handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp,
892 GNUNET_free (result); 827 identity_priv,
893 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 828 &ticket,
894 cleanup_handle (handle); 829 &finished_cont,
895 json_decref (root); 830 handle);
831 GNUNET_JSONAPI_document_delete (json_obj);
896} 832}
897 833
898
899/**
900 *
901 * Callback called when identity for token exchange has been found
902 *
903 * @param cls request handle
904 * @param ego the identity to use as issuer
905 * @param ctx user context
906 * @param name identity name
907 *
908 */
909static void 834static void
910exchange_token_ticket_cb (void *cls, 835consume_cont (void *cls,
911 struct GNUNET_IDENTITY_Ego *ego, 836 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
912 void **ctx, 837 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
913 const char *name)
914{ 838{
915 struct RequestHandle *handle = cls; 839 struct RequestHandle *handle = cls;
916 struct GNUNET_HashCode key; 840 struct GNUNET_JSONAPI_Resource *json_resource;
917 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; 841 json_t *value;
918 char* ticket_str;
919 842
920 handle->op = NULL; 843 if (NULL == identity)
844 {
845 GNUNET_SCHEDULER_add_now (&return_response, handle);
846 return;
847 }
848
849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
850 attr->name);
851 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
852 attr->name);
853 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
854
855 value = json_string (attr->data);
856 GNUNET_JSONAPI_resource_add_attr (json_resource,
857 "value",
858 value);
859 json_decref (value);
860}
921 861
922 if (NULL == ego) 862static void
863consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
864 const char* url,
865 void *cls)
866{
867 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
868 const char* identity_str;
869 const char* audience_str;
870 const char* rnd_str;
871
872 struct RequestHandle *handle = cls;
873 struct EgoEntry *ego_entry;
874 struct MHD_Response *resp;
875 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
876 struct GNUNET_JSONAPI_Document *json_obj;
877 struct GNUNET_JSONAPI_Resource *json_res;
878 struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
879 char term_data[handle->rest_handle->data_size+1];
880 json_t *rnd_json;
881 json_t *identity_json;
882 json_t *audience_json;
883 json_t *data_json;
884 json_error_t err;
885 struct GNUNET_JSON_Specification docspec[] = {
886 GNUNET_JSON_spec_jsonapi_document (&json_obj),
887 GNUNET_JSON_spec_end()
888 };
889
890 if (0 >= handle->rest_handle->data_size)
923 { 891 {
924 handle->emsg = GNUNET_strdup ("No identity found.");
925 GNUNET_SCHEDULER_add_now (&do_error, handle); 892 GNUNET_SCHEDULER_add_now (&do_error, handle);
926 return; 893 return;
927 } 894 }
928 895
929 //Get ticket 896 term_data[handle->rest_handle->data_size] = '\0';
930 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 897 GNUNET_memcpy (term_data,
931 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET), 898 handle->rest_handle->data,
932 &key); 899 handle->rest_handle->data_size);
933 900 data_json = json_loads (term_data,
934 if ( GNUNET_NO == 901 JSON_DECODE_ANY,
935 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 902 &err);
936 &key) ) 903 GNUNET_assert (GNUNET_OK ==
904 GNUNET_JSON_parse (data_json, docspec,
905 NULL, NULL));
906 json_decref (data_json);
907 if (NULL == json_obj)
908 {
909 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
910 "Unable to parse JSONAPI Object from %s\n",
911 term_data);
912 GNUNET_SCHEDULER_add_now (&do_error, handle);
913 return;
914 }
915 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
937 { 916 {
938 handle->emsg = GNUNET_strdup ("No ticket given."); 917 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
918 "Cannot create more than 1 resource! (Got %d)\n",
919 GNUNET_JSONAPI_document_resource_count (json_obj));
920 GNUNET_JSONAPI_document_delete (json_obj);
939 GNUNET_SCHEDULER_add_now (&do_error, handle); 921 GNUNET_SCHEDULER_add_now (&do_error, handle);
940 return; 922 return;
941 } 923 }
942 ticket_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 924 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
943 &key); 925 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
944 handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego); 926 GNUNET_REST_JSONAPI_IDENTITY_TICKET))
945 GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str, 927 {
946 &ticket); 928 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
929 "Unsupported JSON data type\n");
930 GNUNET_JSONAPI_document_delete (json_obj);
931 resp = GNUNET_REST_create_response (NULL);
932 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
933 cleanup_handle (handle);
934 return;
935 }
936 rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
937 "rnd");
938 identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
939 "identity");
940 audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
941 "audience");
942 rnd_str = json_string_value (rnd_json);
943 identity_str = json_string_value (identity_json);
944 audience_str = json_string_value (audience_json);
945
946 GNUNET_STRINGS_string_to_data (rnd_str,
947 strlen (rnd_str),
948 &ticket.rnd,
949 sizeof (uint64_t));
950 GNUNET_STRINGS_string_to_data (identity_str,
951 strlen (identity_str),
952 &ticket.identity,
953 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
954 GNUNET_STRINGS_string_to_data (audience_str,
955 strlen (audience_str),
956 &ticket.audience,
957 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
947 958
959 for (ego_entry = handle->ego_head;
960 NULL != ego_entry;
961 ego_entry = ego_entry->next)
962 {
963 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
964 &tmp_pk);
965 if (0 == memcmp (&ticket.audience,
966 &tmp_pk,
967 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
968 break;
969 }
970 if (NULL == ego_entry)
971 {
972 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
973 "Identity unknown (%s)\n", identity_str);
974 GNUNET_JSONAPI_document_delete (json_obj);
975 return;
976 }
977 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
978 handle->resp_object = GNUNET_JSONAPI_document_new ();
948 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); 979 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
949 handle->idp_op = GNUNET_IDENTITY_PROVIDER_exchange_ticket (handle->idp, 980 handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (handle->idp,
950 ticket, 981 identity_priv,
951 handle->priv_key, 982 &ticket,
952 &exchange_cont, 983 &consume_cont,
953 handle); 984 handle);
954 GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket); 985 GNUNET_JSONAPI_document_delete (json_obj);
955
956} 986}
957 987
958 988
959 989
960/** 990/**
961 * Respond to issue request
962 *
963 * @param con_handle the connection handle
964 * @param url the url
965 * @param cls the RequestHandle
966 */
967static void
968exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
969 const char* url,
970 void *cls)
971{
972 struct RequestHandle *handle = cls;
973
974 //Get token from GNS
975 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
976 "gns-master",
977 &exchange_token_ticket_cb,
978 handle);
979}
980
981/**
982 * Respond to OPTIONS request 991 * Respond to OPTIONS request
983 * 992 *
984 * @param con_handle the connection handle 993 * @param con_handle the connection handle
@@ -1013,15 +1022,17 @@ init_cont (struct RequestHandle *handle)
1013{ 1022{
1014 struct GNUNET_REST_RequestHandlerError err; 1023 struct GNUNET_REST_RequestHandlerError err;
1015 static const struct GNUNET_REST_RequestHandler handlers[] = { 1024 static const struct GNUNET_REST_RequestHandler handlers[] = {
1016 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont}, 1025 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont},
1017 //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont}, 1026 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont},
1018 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont}, 1027 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
1019 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &options_cont}, 1028 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
1020 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont}, 1029 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
1030 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER,
1031 &options_cont},
1021 GNUNET_REST_HANDLER_END 1032 GNUNET_REST_HANDLER_END
1022 }; 1033 };
1023 1034
1024 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, 1035 if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
1025 handlers, 1036 handlers,
1026 &err, 1037 &err,
1027 handle)) 1038 handle))
@@ -1092,19 +1103,8 @@ list_ego (void *cls,
1092 1103
1093} 1104}
1094 1105
1095/**
1096 * Function processing the REST call
1097 *
1098 * @param method HTTP method
1099 * @param url URL of the HTTP request
1100 * @param data body of the HTTP request (optional)
1101 * @param data_size length of the body
1102 * @param proc callback function for the result
1103 * @param proc_cls closure for callback function
1104 * @return GNUNET_OK if request accepted
1105 */
1106static void 1106static void
1107rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, 1107rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
1108 GNUNET_REST_ResultProcessor proc, 1108 GNUNET_REST_ResultProcessor proc,
1109 void *proc_cls) 1109 void *proc_cls)
1110{ 1110{
@@ -1114,10 +1114,9 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1114 handle->proc_cls = proc_cls; 1114 handle->proc_cls = proc_cls;
1115 handle->proc = proc; 1115 handle->proc = proc;
1116 handle->state = ID_REST_STATE_INIT; 1116 handle->state = ID_REST_STATE_INIT;
1117 handle->conndata_handle = conndata_handle; 1117 handle->rest_handle = rest_handle;
1118 1118
1119 1119 handle->url = GNUNET_strdup (rest_handle->url);
1120 handle->url = GNUNET_strdup (conndata_handle->url);
1121 if (handle->url[strlen (handle->url)-1] == '/') 1120 if (handle->url[strlen (handle->url)-1] == '/')
1122 handle->url[strlen (handle->url)-1] = '\0'; 1121 handle->url[strlen (handle->url)-1] = '\0';
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1162,8 +1161,8 @@ libgnunet_plugin_rest_identity_provider_init (void *cls)
1162 MHD_HTTP_METHOD_DELETE, 1161 MHD_HTTP_METHOD_DELETE,
1163 MHD_HTTP_METHOD_OPTIONS); 1162 MHD_HTTP_METHOD_OPTIONS);
1164 1163
1165 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1166 _("Identity Token REST API initialized\n")); 1165 _("Identity Provider REST API initialized\n"));
1167 return api; 1166 return api;
1168} 1167}
1169 1168
@@ -1184,8 +1183,8 @@ libgnunet_plugin_rest_identity_provider_done (void *cls)
1184 GNUNET_free_non_null (allow_methods); 1183 GNUNET_free_non_null (allow_methods);
1185 GNUNET_free (api); 1184 GNUNET_free (api);
1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "Identity Token REST plugin is finished\n"); 1186 "Identity Provider REST plugin is finished\n");
1188 return NULL; 1187 return NULL;
1189} 1188}
1190 1189
1191/* end of plugin_rest_gns.c */ 1190/* end of plugin_rest_identity_provider.c */
diff --git a/src/identity-provider/test_idp.conf b/src/identity-provider/test_idp.conf
new file mode 100644
index 000000000..2b76c7bf2
--- /dev/null
+++ b/src/identity-provider/test_idp.conf
@@ -0,0 +1,28 @@
1@INLINE@ test_idp_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-idp-peer-1/
5
6[dht]
7AUTOSTART = YES
8
9[rest]
10AUTOSTART = YES
11#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
12
13[transport]
14PLUGINS =
15
16[identity-provider]
17AUTOSTART = YES
18#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=/tmp/idplog
19
20[gns]
21#PREFIX = valgrind --leak-check=full --track-origins=yes
22AUTOSTART = YES
23AUTO_IMPORT_PKEY = YES
24MAX_PARALLEL_BACKGROUND_QUERIES = 10
25DEFAULT_LOOKUP_TIMEOUT = 15 s
26RECORD_PUT_INTERVAL = 1 h
27ZONE_PUBLISH_TIME_WINDOW = 1 h
28DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
diff --git a/src/identity-provider/test_idp.sh b/src/identity-provider/test_idp.sh
new file mode 100755
index 000000000..598d1008c
--- /dev/null
+++ b/src/identity-provider/test_idp.sh
@@ -0,0 +1,31 @@
1#!/bin/bash
2#trap "gnunet-arm -e -c test_idp_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_idp.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_idp.conf
27gnunet-identity -C testego -c test_idp.conf
28valgrind gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
29gnunet-idp -e testego -a name -V John -c test_idp.conf
30gnunet-idp -e testego -D -c test_idp.conf
31gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_attribute.sh b/src/identity-provider/test_idp_attribute.sh
new file mode 100755
index 000000000..7f0f06dac
--- /dev/null
+++ b/src/identity-provider/test_idp_attribute.sh
@@ -0,0 +1,40 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_idp.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_idp.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_idp.conf
27#gnunet-arm -i rest -c test_idp.conf
28gnunet-identity -C testego -c test_idp.conf
29gnunet-identity -C rpego -c test_idp.conf
30TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
31gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
32gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
33if test $? != 0
34then
35 echo "Failed."
36 exit 1
37fi
38
39#curl localhost:7776/idp/attributes/testego
40gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_consume.sh b/src/identity-provider/test_idp_consume.sh
new file mode 100755
index 000000000..11f6865a4
--- /dev/null
+++ b/src/identity-provider/test_idp_consume.sh
@@ -0,0 +1,43 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_idp.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_idp.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_idp.conf
27#gnunet-arm -i rest -c test_idp.conf
28gnunet-identity -C testego -c test_idp.conf
29gnunet-identity -C rpego -c test_idp.conf
30SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}')
31TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
32gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
33gnunet-idp -e testego -a name -V John -c test_idp.conf
34TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf | awk '{print $1}')
35gnunet-idp -e rpego -C $TICKET -c test_idp.conf > /dev/null 2>&1
36
37if test $? != 0
38then
39 "Failed."
40 exit 1
41fi
42#curl http://localhost:7776/idp/tickets/testego
43gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_defaults.conf b/src/identity-provider/test_idp_defaults.conf
new file mode 100644
index 000000000..10d89c2fb
--- /dev/null
+++ b/src/identity-provider/test_idp_defaults.conf
@@ -0,0 +1,24 @@
1@INLINE@ ../../contrib/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-idp-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/identity-provider/test_idp_issue.sh b/src/identity-provider/test_idp_issue.sh
new file mode 100755
index 000000000..90487ee73
--- /dev/null
+++ b/src/identity-provider/test_idp_issue.sh
@@ -0,0 +1,42 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_idp.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_idp.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_idp.conf
27#gnunet-arm -i rest -c test_idp.conf
28gnunet-identity -C testego -c test_idp.conf
29gnunet-identity -C rpego -c test_idp.conf
30SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}')
31TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
32gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf > /dev/null 2>&1
33gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
34#gnunet-idp -e testego -D -c test_idp.conf
35gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf > /dev/null 2>&1
36if test $? != 0
37then
38 echo "Failed."
39 exit 1
40fi
41#curl http://localhost:7776/idp/attributes/testego
42gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_revoke.sh b/src/identity-provider/test_idp_revoke.sh
new file mode 100755
index 000000000..d5c2c3f77
--- /dev/null
+++ b/src/identity-provider/test_idp_revoke.sh
@@ -0,0 +1,60 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_idp.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_idp.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_idp.conf
27gnunet-identity -C alice -c test_idp.conf
28gnunet-identity -C bob -c test_idp.conf
29gnunet-identity -C eve -c test_idp.conf
30ALICE_KEY=$(gnunet-identity -d -c test_idp.conf | grep alice | awk '{print $3}')
31BOB_KEY=$(gnunet-identity -d -c test_idp.conf | grep bob | awk '{print $3}')
32EVE_KEY=$(gnunet-identity -d -c test_idp.conf | grep eve | awk '{print $3}')
33
34gnunet-idp -e alice -a email -V john@doe.gnu -c test_idp.conf
35gnunet-idp -e alice -a name -V John -c test_idp.conf
36TICKET_BOB=$(gnunet-idp -e alice -i "email,name" -r $BOB_KEY -c test_idp.conf | awk '{print $1}')
37#gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf
38TICKET_EVE=$(gnunet-idp -e alice -i "email" -r $EVE_KEY -c test_idp.conf | awk '{print $1}')
39
40
41#echo "Consuming $TICKET"
42#gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf
43gnunet-idp -e alice -R $TICKET_EVE -c test_idp.conf
44
45gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf > /dev/null 2>&1
46if test $? == 0
47then
48 echo "Eve can still resolve attributes..."
49 gnunet-arm -e -c test_idp.conf
50 exit 1
51fi
52gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf > /dev/null 2>&1
53if test $? != 0
54then
55 echo "Bob cannot resolve attributes..."
56 gnunet-arm -e -c test_idp.conf
57 exit 1
58fi
59
60gnunet-arm -e -c test_idp.conf
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index 94e8c5e94..b8e70fffb 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -42,8 +42,7 @@ libexec_PROGRAMS = \
42if HAVE_MHD 42if HAVE_MHD
43if HAVE_JSON 43if HAVE_JSON
44plugin_LTLIBRARIES = \ 44plugin_LTLIBRARIES = \
45 libgnunet_plugin_rest_identity.la \ 45 libgnunet_plugin_rest_identity.la
46 libgnunet_plugin_gnsrecord_identity.la
47endif 46endif
48endif 47endif
49 48
@@ -55,14 +54,6 @@ gnunet_service_identity_LDADD = \
55 $(top_builddir)/src/util/libgnunetutil.la \ 54 $(top_builddir)/src/util/libgnunetutil.la \
56 $(GN_LIBINTL) 55 $(GN_LIBINTL)
57 56
58libgnunet_plugin_gnsrecord_identity_la_SOURCES = \
59 plugin_gnsrecord_identity.c
60libgnunet_plugin_gnsrecord_identity_la_LIBADD = \
61 $(top_builddir)/src/util/libgnunetutil.la \
62 $(LTLIBINTL)
63libgnunet_plugin_gnsrecord_identity_la_LDFLAGS = \
64 $(GN_PLUGIN_LDFLAGS)
65
66 57
67libgnunet_plugin_rest_identity_la_SOURCES = \ 58libgnunet_plugin_rest_identity_la_SOURCES = \
68 plugin_rest_identity.c 59 plugin_rest_identity.c
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
index e64b2685a..5f34d0f1b 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -427,9 +427,6 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con,
427 continue; 427 continue;
428 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, 428 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO,
429 ego_entry->keystring); 429 ego_entry->keystring);
430 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
431 "Egoname: %s\n",
432 ego_entry->identifier);
433 name_str = json_string (ego_entry->identifier); 430 name_str = json_string (ego_entry->identifier);
434 GNUNET_JSONAPI_resource_add_attr ( 431 GNUNET_JSONAPI_resource_add_attr (
435 json_resource, 432 json_resource,
diff --git a/src/include/gnunet_abe_lib.h b/src/include/gnunet_abe_lib.h
new file mode 100644
index 000000000..f73ea2431
--- /dev/null
+++ b/src/include/gnunet_abe_lib.h
@@ -0,0 +1,193 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2018 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 include/gnunet_abe_lib.h
23 * @brief Attribute-Based Encryption primitives for GNUnet
24 *
25 * @author Martin Schanzenbach
26 *
27 * @defgroup abe ABE Crypto library: Attribute-Based Encryption operations
28 *
29 */
30#ifndef GNUNET_ABE_LIB_H
31#define GNUNET_ABE_LIB_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "gnunet_common.h"
42#include <gcrypt.h>
43
44/**
45 * @brief type for ABE master keys
46 */
47struct GNUNET_CRYPTO_AbeMasterKey;
48
49/**
50 * @brief type for ABE keys
51 */
52struct GNUNET_CRYPTO_AbeKey;
53
54
55
56/**
57 * @ingroup abe
58 * Create a new CP-ABE master key. Caller must free return value.
59 *
60 * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
61 */
62struct GNUNET_ABE_AbeMasterKey *
63GNUNET_ABE_cpabe_create_master_key (void);
64
65/**
66 * @ingroup abe
67 * Delete a CP-ABE master key.
68 *
69 * @param key the master key
70 * @return fresh private key; free using #GNUNET_free
71 */
72void
73GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key);
74
75/**
76 * @ingroup abe
77 * Create a new CP-ABE key. Caller must free return value.
78 *
79 * @param key the master key
80 * @param attrs the attributes to append to the key
81 * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
82 */
83struct GNUNET_ABE_AbeKey *
84GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
85 char **attrs);
86
87/**
88 * @ingroup abe
89 * Delete a CP-ABE key.
90 *
91 * @param key the key to delete
92 * @param delete_pub GNUNE_YES if the public key should also be freed (bug in gabe)
93 * @return fresh private key; free using #GNUNET_free
94 */
95void
96GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
97 int delete_pub);
98
99
100/**
101 * @ingroup abe
102 * Encrypt a block using sessionkey.
103 *
104 * @param block the block to encrypt
105 * @param size the size of the @a block
106 * @param policy the ABE policy
107 * @param key the key used to encrypt
108 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
109 * @return the size of the encrypted block, -1 for errors
110 */
111ssize_t
112GNUNET_ABE_cpabe_encrypt (const void *block,
113 size_t size,
114 const char *policy,
115 const struct GNUNET_ABE_AbeMasterKey *key,
116 void **result);
117
118/**
119 * @ingroup abe
120 * Decrypt a block using the ABE key.
121 *
122 * @param block the block to encrypt
123 * @param size the size of the @a block
124 * @param key the key used to decrypt
125 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
126 * @return the size of the encrypted block, -1 for errors
127 */
128ssize_t
129GNUNET_ABE_cpabe_decrypt (const void *block,
130 size_t size,
131 const struct GNUNET_ABE_AbeKey *key,
132 void **result);
133
134/**
135 * @ingroup abe
136 * Serialize an ABE key.
137 *
138 * @param key the key to serialize
139 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
140 * @return the size of the encrypted block, -1 for errors
141 */
142ssize_t
143GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
144 void **result);
145
146/**
147 * @ingroup abe
148 * Deserialize a serialized ABE key.
149 *
150 * @param data the data to deserialize
151 * @param len the length of the data.
152 * @return the ABE key. NULL of unsuccessful
153 */
154struct GNUNET_ABE_AbeKey*
155GNUNET_ABE_cpabe_deserialize_key (const void *data,
156 size_t len);
157
158/**
159 * @ingroup abe
160 * Serialize an ABE master key.
161 *
162 * @param key the key to serialize
163 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
164 * @return the size of the encrypted block, -1 for errors
165 */
166ssize_t
167GNUNET_ABE_cpabe_serialize_master_key (const struct GNUNET_ABE_AbeMasterKey *key,
168 void **result);
169
170/**
171 * @ingroup abe
172 * Deserialize an ABE master key.
173 *
174 * @param data the data to deserialize
175 * @param len the length of the data.
176 * @return the ABE key. NULL of unsuccessful
177 */
178struct GNUNET_ABE_AbeMasterKey*
179GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
180 size_t len);
181
182
183#if 0 /* keep Emacsens' auto-indent happy */
184{
185#endif
186#ifdef __cplusplus
187}
188#endif
189
190
191/* ifndef GNUNET_ABE_LIB_H */
192#endif
193/* end of gnunet_abe_lib.h */
diff --git a/src/include/gnunet_credential_service.h b/src/include/gnunet_credential_service.h
index 9e765c12b..7d6f9e973 100644
--- a/src/include/gnunet_credential_service.h
+++ b/src/include/gnunet_credential_service.h
@@ -34,6 +34,7 @@
34 34
35#include "gnunet_util_lib.h" 35#include "gnunet_util_lib.h"
36#include "gnunet_gns_service.h" 36#include "gnunet_gns_service.h"
37#include "gnunet_identity_service.h"
37 38
38#ifdef __cplusplus 39#ifdef __cplusplus
39extern "C" 40extern "C"
@@ -52,7 +53,157 @@ struct GNUNET_CREDENTIAL_Handle;
52/** 53/**
53 * Handle to control a lookup operation. 54 * Handle to control a lookup operation.
54 */ 55 */
55struct GNUNET_CREDENTIAL_LookupRequest; 56struct GNUNET_CREDENTIAL_Request;
57
58/*
59* Enum used for checking whether the issuer has the authority to issue credentials or is just a subject
60*/
61enum GNUNET_CREDENTIAL_CredentialFlags {
62
63 //Subject had credentials before, but have been revoked now
64 GNUNET_CREDENTIAL_FLAG_REVOKED=0,
65
66 //Subject flag indicates that the subject is a holder of this credential and may present it as such
67 GNUNET_CREDENTIAL_FLAG_SUBJECT=1,
68
69 //Issuer flag is used to signify that the subject is allowed to issue this credential and delegate issuance
70 GNUNET_CREDENTIAL_FLAG_ISSUER=2
71
72};
73
74GNUNET_NETWORK_STRUCT_BEGIN
75/**
76 * The attribute delegation record
77 */
78struct GNUNET_CREDENTIAL_DelegationRecord {
79
80 /**
81 * Number of delegation sets in this record
82 */
83 uint32_t set_count;
84
85 /**
86 * Length of delegation sets
87 */
88 uint64_t data_size;
89 /**
90 * Followed by set_count DelegationSetRecords
91 *
92 */
93};
94
95/**
96 * The attribute delegation record
97 */
98struct GNUNET_CREDENTIAL_DelegationRecordSet {
99
100 /**
101 * Public key of the subject this attribute was delegated to
102 */
103 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
104
105 /**
106 * Length of attribute, may be 0
107 */
108 uint32_t subject_attribute_len;
109};
110
111
112GNUNET_NETWORK_STRUCT_END
113
114/**
115 * The attribute delegation record
116 */
117struct GNUNET_CREDENTIAL_DelegationSet {
118
119 /**
120 * Public key of the subject this attribute was delegated to
121 */
122 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
123
124 uint32_t subject_attribute_len;
125
126 /**
127 * The subject attribute
128 */
129 const char *subject_attribute;
130};
131
132
133/**
134 * A delegation
135 */
136struct GNUNET_CREDENTIAL_Delegation {
137
138 /**
139 * The issuer of the delegation
140 */
141 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
142
143 /**
144 * Public key of the subject this attribute was delegated to
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
147
148 /**
149 * Length of the attribute
150 */
151 uint32_t issuer_attribute_len;
152
153 /**
154 * The attribute
155 */
156 const char *issuer_attribute;
157
158 /**
159 * Length of the attribute
160 */
161 uint32_t subject_attribute_len;
162
163 /**
164 * The attribute
165 */
166 const char *subject_attribute;
167};
168
169
170/**
171 * A credential
172 */
173struct GNUNET_CREDENTIAL_Credential {
174
175 /**
176 * The issuer of the credential
177 */
178 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
179
180 /**
181 * Public key of the subject this credential was issued to
182 */
183 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
184
185 /**
186 * Signature of this credential
187 */
188 struct GNUNET_CRYPTO_EcdsaSignature signature;
189
190 /**
191 * Expiration of this credential
192 */
193 struct GNUNET_TIME_Absolute expiration;
194
195 /**
196 * Length of the attribute
197 */
198 uint32_t issuer_attribute_len;
199
200 /**
201 * The attribute
202 */
203 const char *issuer_attribute;
204
205};
206
56 207
57 208
58/** 209/**
@@ -61,7 +212,7 @@ struct GNUNET_CREDENTIAL_LookupRequest;
61 * @param cfg configuration to use 212 * @param cfg configuration to use
62 * @return handle to the Credential service, or NULL on error 213 * @return handle to the Credential service, or NULL on error
63 */ 214 */
64struct GNUNET_Credential_Handle * 215struct GNUNET_CREDENTIAL_Handle *
65GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); 216GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
66 217
67 218
@@ -75,73 +226,131 @@ GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle);
75 226
76 227
77/** 228/**
78 * Iterator called on obtained result for a Credential lookup. 229 * Iterator called on obtained result for an attribute verification.
230 *
231 * @param cls closure
232 * @param d_count the number of delegations processed
233 * @param delegation_chain the delegations processed
234 * @param c_count the number of credentials found
235 * @param credential the credentials
236 */
237typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls,
238 unsigned int d_count,
239 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
240 unsigned int c_count,
241 struct GNUNET_CREDENTIAL_Credential *credential);
242
243/**
244 * Iterator called on obtained result for an attribute delegation.
245 *
246 * @param cls closure
247 * @param success GNUNET_YES if successful
248 * @param result the record data that can be handed to the subject
249 */
250typedef void (*GNUNET_CREDENTIAL_DelegateResultProcessor) (void *cls,
251 uint32_t success);
252
253/**
254 * Iterator called on obtained result for an attribute delegation removal.
79 * 255 *
80 * @param cls closure 256 * @param cls closure
81 * @param issuer the issuer chain 257 * @param success GNUNET_YES if successful
82 * @param issuer_len length of issuer chain 258 * @param result the record data that can be handed to the subject
83 * @param value the value returned
84 */ 259 */
85typedef void 260typedef void (*GNUNET_CREDENTIAL_RemoveDelegateResultProcessor) (void *cls,
86(*GNUNET_CREDENTIAL_LookupResultProcessor) (void *cls, 261 uint32_t success);
87 struct GNUNET_IDENTITY_Ego *issuer,
88 uint16_t issuer_len,
89 const struct GNUNET_CREDENTIAL_Value *value);
90 262
91 263
92/** 264/**
93 * Perform an asynchronous lookup operation for a credential. 265 * Performs attribute verification.
266 * Checks if there is a delegation chain from
267 * attribute ``issuer_attribute'' issued by the issuer
268 * with public key ``issuer_key'' maps to the attribute
269 * ``subject_attribute'' claimed by the subject with key
270 * ``subject_key''
94 * 271 *
95 * @param handle handle to the Credential service 272 * @param handle handle to the Credential service
96 * @param credential the credential to look up 273 * @param issuer_key the issuer public key
97 * @param subject Ego to check the credential for 274 * @param issuer_attribute the issuer attribute
275 * @param subject_key the subject public key
276 * @param credential_count number of credentials
277 * @param credentials the subject credentials
98 * @param proc function to call on result 278 * @param proc function to call on result
99 * @param proc_cls closure for processor 279 * @param proc_cls closure for processor
100 * @return handle to the queued request 280 * @return handle to the queued request
101 */ 281 */
102struct GNUNET_CREDENTIAL_LookupRequest * 282struct GNUNET_CREDENTIAL_Request*
103GNUNET_CREDENTIAL_lookup (struct GNUNET_CREDENTIAL_Handle *handle, 283GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
104 const char *credential, 284 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
105 const struct GNUNET_IDENTITY_Ego *subject, 285 const char *issuer_attribute,
106 GNUNET_CREDENTIAL_LookupResultProcessor proc, 286 const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
287 uint32_t credential_count,
288 const struct GNUNET_CREDENTIAL_Credential *credentials,
289 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
107 void *proc_cls); 290 void *proc_cls);
108 291
292struct GNUNET_CREDENTIAL_Request*
293GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
294 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
295 const char *issuer_attribute,
296 const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
297 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
298 void *proc_cls);
109 299
110/** 300/**
111 * Issue a credential to an identity 301 * Delegate an attribute
112 * 302 *
113 * @param handle handle to the Credential service 303 * @param handle handle to the Credential service
114 * @param issuer the identity that issues the credential 304 * @param issuer the ego that should be used to delegate the attribute
115 * @param subject the subject of the credential 305 * @param attribute the name of the attribute to delegate
116 * @param credential the name of the credential 306 * @param subject the subject of the delegation
117 * @param value the value of the credential 307 * @param delegated_attribute the name of the attribute that is delegated to
308 * @param proc the result callback
309 * @param proc_cls the result closure context
118 * @return handle to the queued request 310 * @return handle to the queued request
119 */ 311 */
120struct GNUNET_CREDENTIAL_IssueRequest * 312struct GNUNET_CREDENTIAL_Request *
121GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle, 313GNUNET_CREDENTIAL_add_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
122 struct GNUNET_IDENTITY_Ego *issuer, 314 struct GNUNET_IDENTITY_Ego *issuer,
123 struct GNUNET_IDENTITY_Ego *subject, 315 const char *attribute,
124 const char *credential, 316 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
125 struct GNUNET_CREDENTIAL_Value *value, 317 const char *delegated_attribute,
126 GNUNET_CREDENTIAL_IssueResultProcessor proc, 318 GNUNET_CREDENTIAL_DelegateResultProcessor proc,
127 void *proc_cls); 319 void *proc_cls);
128 320
129/** 321/**
130 * Remove a credential 322 * Remove a delegation
131 * 323 *
132 * @param handle handle to the Credential service 324 * @param handle handle to the Credential service
133 * @param issuer the identity that issued the credential 325 * @param issuer the ego that was used to delegate the attribute
134 * @param subject the subject of the credential 326 * @param attribute the name of the attribute that is delegated
135 * @param credential the name of the credential 327 * @param proc the callback
328 * @param proc_cls callback closure
136 * @return handle to the queued request 329 * @return handle to the queued request
137 */ 330 */
138struct GNUNET_CREDENTIAL_IssueRequest * 331struct GNUNET_CREDENTIAL_Request *
139GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle, 332GNUNET_CREDENTIAL_remove_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
140 struct GNUNET_IDENTITY_Ego *issuer, 333 struct GNUNET_IDENTITY_Ego *issuer,
141 struct GNUNET_IDENTITY_Ego *subject, 334 const char *attribute,
142 const char *credential, 335 GNUNET_CREDENTIAL_RemoveDelegateResultProcessor proc,
143 GNUNET_CREDENTIAL_IssueResultProcessor proc, 336 void *proc_cls);
144 void *proc_cls); 337
338
339
340/**
341 * Issue an attribute to a subject
342 *
343 * @param issuer the ego that should be used to issue the attribute
344 * @param subject the subject of the attribute
345 * @param attribute the name of the attribute
346 * @param expiration the TTL of the credential
347 * @return handle to the queued request
348 */
349struct GNUNET_CREDENTIAL_Credential*
350GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
351 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
352 const char *attribute,
353 struct GNUNET_TIME_Absolute *expiration);
145 354
146 355
147 356
@@ -151,7 +360,7 @@ GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle,
151 * @param lr the lookup request to cancel 360 * @param lr the lookup request to cancel
152 */ 361 */
153void 362void
154GNUNET_CREDENTIAL_lookup_cancel (struct GNUNET_CREDENTIAL_LookupRequest *lr); 363GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *lr);
155 364
156 365
157#if 0 /* keep Emacsens' auto-indent happy */ 366#if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index 985ae1f7a..d03b4db3b 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -109,9 +109,29 @@ extern "C"
109#define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546 109#define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546
110 110
111/** 111/**
112 * Record type for credential
113 */
114#define GNUNET_GNSRECORD_TYPE_CREDENTIAL 65547
115
116/**
117 * Record type for policies
118 */
119#define GNUNET_GNSRECORD_TYPE_POLICY 65548
120
121/**
112 * Record type for reverse lookups 122 * Record type for reverse lookups
113 */ 123 */
114#define GNUNET_GNSRECORD_TYPE_REVERSE 65548 124#define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549
125
126/**
127 * Record type for ABE records
128 */
129#define GNUNET_GNSRECORD_TYPE_ABE_KEY 65550
130
131/**
132 * Record type for ABE master keys
133 */
134#define GNUNET_GNSRECORD_TYPE_ABE_MASTER 65551
115 135
116/** 136/**
117 * Flags that can be set for a record. 137 * Flags that can be set for a record.
diff --git a/src/include/gnunet_identity_attribute_lib.h b/src/include/gnunet_identity_attribute_lib.h
new file mode 100644
index 000000000..316b0bf95
--- /dev/null
+++ b/src/include/gnunet_identity_attribute_lib.h
@@ -0,0 +1,277 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2017 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 * @author Martin Schanzenbach
23 *
24 * @file
25 * Identity attribute definitions
26 *
27 * @defgroup identity-provider Identity Provider service
28 * @{
29 */
30#ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H
31#define GNUNET_IDENTITY_ATTRIBUTE_LIB_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "gnunet_util_lib.h"
42
43
44/**
45 * No value attribute.
46 */
47#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_NONE 0
48
49/**
50 * String attribute.
51 */
52#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING 1
53
54
55
56/**
57 * An attribute.
58 */
59struct GNUNET_IDENTITY_ATTRIBUTE_Claim
60{
61 /**
62 * The name of the attribute. Note "name" must never be individually
63 * free'd
64 */
65 const char* name;
66
67 /**
68 * Type of Claim
69 */
70 uint32_t type;
71
72 /**
73 * Version
74 */
75 uint32_t version;
76
77 /**
78 * Number of bytes in @e data.
79 */
80 size_t data_size;
81
82 /**
83 * Binary value stored as attribute value. Note: "data" must never
84 * be individually 'malloc'ed, but instead always points into some
85 * existing data area.
86 */
87 const void *data;
88
89};
90
91struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList
92{
93 /**
94 * List head
95 */
96 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_head;
97
98 /**
99 * List tail
100 */
101 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_tail;
102};
103
104struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry
105{
106 /**
107 * DLL
108 */
109 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *prev;
110
111 /**
112 * DLL
113 */
114 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *next;
115
116 /**
117 * The attribute claim
118 */
119 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
120};
121
122/**
123 * Create a new attribute claim.
124 *
125 * @param attr_name the attribute name
126 * @param type the attribute type
127 * @param data the attribute value
128 * @param data_size the attribute value size
129 * @return the new attribute
130 */
131struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
132GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
133 uint32_t type,
134 const void* data,
135 size_t data_size);
136
137
138/**
139 * Get required size for serialization buffer
140 *
141 * @param attrs the attribute list to serialize
142 *
143 * @return the required buffer size
144 */
145size_t
146GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
147
148void
149GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
150
151
152/**
153 * Serialize an attribute list
154 *
155 * @param attrs the attribute list to serialize
156 * @param result the serialized attribute
157 *
158 * @return length of serialized data
159 */
160size_t
161GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
162 char *result);
163
164/**
165 * Deserialize an attribute list
166 *
167 * @param data the serialized attribute list
168 * @param data_size the length of the serialized data
169 *
170 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
171 */
172struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
173GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
174 size_t data_size);
175
176
177/**
178 * Get required size for serialization buffer
179 *
180 * @param attr the attribute to serialize
181 *
182 * @return the required buffer size
183 */
184size_t
185GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
186
187
188
189/**
190 * Serialize an attribute
191 *
192 * @param attr the attribute to serialize
193 * @param result the serialized attribute
194 *
195 * @return length of serialized data
196 */
197size_t
198GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
199 char *result);
200
201/**
202 * Deserialize an attribute
203 *
204 * @param data the serialized attribute
205 * @param data_size the length of the serialized data
206 *
207 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
208 */
209struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
210GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
211 size_t data_size);
212
213struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
214GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
215
216/**
217 * Convert a type name to the corresponding number
218 *
219 * @param typename name to convert
220 * @return corresponding number, UINT32_MAX on error
221 */
222uint32_t
223GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename);
224
225/**
226 * Convert human-readable version of a 'claim' of an attribute to the binary
227 * representation
228 *
229 * @param type type of the claim
230 * @param s human-readable string
231 * @param data set to value in binary encoding (will be allocated)
232 * @param data_size set to number of bytes in @a data
233 * @return #GNUNET_OK on success
234 */
235int
236GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
237 const char *s,
238 void **data,
239 size_t *data_size);
240
241/**
242 * Convert the 'claim' of an attribute to a string
243 *
244 * @param type the type of attribute
245 * @param data claim in binary encoding
246 * @param data_size number of bytes in @a data
247 * @return NULL on error, otherwise human-readable representation of the claim
248 */
249char *
250GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
251 const void* data,
252 size_t data_size);
253
254/**
255 * Convert a type number to the corresponding type string
256 *
257 * @param type number of a type
258 * @return corresponding typestring, NULL on error
259 */
260const char*
261GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type);
262
263
264#if 0 /* keep Emacsens' auto-indent happy */
265{
266#endif
267#ifdef __cplusplus
268}
269#endif
270
271
272/* ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H */
273#endif
274
275/** @} */ /* end of group identity */
276
277/* end of gnunet_identity_attribute_lib.h */
diff --git a/src/include/gnunet_identity_attribute_plugin.h b/src/include/gnunet_identity_attribute_plugin.h
new file mode 100644
index 000000000..edeed57fd
--- /dev/null
+++ b/src/include/gnunet_identity_attribute_plugin.h
@@ -0,0 +1,149 @@
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/**
22 * @author Martin Schanzenbach
23 *
24 * @file
25 * Plugin API for the idp database backend
26 *
27 * @defgroup identity-provider-plugin IdP service plugin API
28 * Plugin API for the idp database backend
29 * @{
30 */
31#ifndef GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H
32#define GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H
33
34#include "gnunet_util_lib.h"
35#include "gnunet_identity_attribute_lib.h"
36
37#ifdef __cplusplus
38extern "C"
39{
40#if 0 /* keep Emacsens' auto-indent happy */
41}
42#endif
43#endif
44
45
46/**
47 * Function called to convert the binary value @a data of an attribute of
48 * type @a type to a human-readable string.
49 *
50 * @param cls closure
51 * @param type type of the attribute
52 * @param data value in binary encoding
53 * @param data_size number of bytes in @a data
54 * @return NULL on error, otherwise human-readable representation of the value
55 */
56typedef char * (*GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction) (void *cls,
57 uint32_t type,
58 const void *data,
59 size_t data_size);
60
61
62/**
63 * Function called to convert human-readable version of the value @a s
64 * of an attribute of type @a type to the respective binary
65 * representation.
66 *
67 * @param cls closure
68 * @param type type of the attribute
69 * @param s human-readable string
70 * @param data set to value in binary encoding (will be allocated)
71 * @param data_size set to number of bytes in @a data
72 * @return #GNUNET_OK on success
73 */
74typedef int (*GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction) (void *cls,
75 uint32_t type,
76 const char *s,
77 void **data,
78 size_t *data_size);
79
80
81/**
82 * Function called to convert a type name to the
83 * corresponding number.
84 *
85 * @param cls closure
86 * @param typename name to convert
87 * @return corresponding number, UINT32_MAX on error
88 */
89typedef uint32_t (*GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction) (void *cls,
90 const char *typename);
91
92
93/**
94 * Function called to convert a type number (i.e. 1) to the
95 * corresponding type string
96 *
97 * @param cls closure
98 * @param type number of a type to convert
99 * @return corresponding typestring, NULL on error
100 */
101typedef const char * (*GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction) (void *cls,
102 uint32_t type);
103
104
105/**
106 * Each plugin is required to return a pointer to a struct of this
107 * type as the return value from its entry point.
108 */
109struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions
110{
111
112 /**
113 * Closure for all of the callbacks.
114 */
115 void *cls;
116
117 /**
118 * Conversion to string.
119 */
120 GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction value_to_string;
121
122 /**
123 * Conversion to binary.
124 */
125 GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction string_to_value;
126
127 /**
128 * Typename to number.
129 */
130 GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction typename_to_number;
131
132 /**
133 * Number to typename.
134 */
135 GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction number_to_typename;
136
137};
138
139
140#if 0 /* keep Emacsens' auto-indent happy */
141{
142#endif
143#ifdef __cplusplus
144}
145#endif
146
147#endif
148
149/** @} */ /* end of group */
diff --git a/src/include/gnunet_identity_provider_plugin.h b/src/include/gnunet_identity_provider_plugin.h
new file mode 100644
index 000000000..4b5098d58
--- /dev/null
+++ b/src/include/gnunet_identity_provider_plugin.h
@@ -0,0 +1,123 @@
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/**
22 * @author Martin Schanzenbach
23 *
24 * @file
25 * Plugin API for the idp database backend
26 *
27 * @defgroup identity-provider-plugin IdP service plugin API
28 * Plugin API for the idp database backend
29 * @{
30 */
31#ifndef GNUNET_IDENTITY_PROVIDER_PLUGIN_H
32#define GNUNET_IDENTITY_PROVIDER_PLUGIN_H
33
34#include "gnunet_util_lib.h"
35#include "gnunet_identity_provider_service.h"
36
37#ifdef __cplusplus
38extern "C"
39{
40#if 0 /* keep Emacsens' auto-indent happy */
41}
42#endif
43#endif
44
45
46/**
47 * Function called by for each matching ticket.
48 *
49 * @param cls closure
50 * @param ticket the ticket
51 */
52typedef void (*GNUNET_IDENTITY_PROVIDER_TicketIterator) (void *cls,
53 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
54 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
55
56
57/**
58 * @brief struct returned by the initialization function of the plugin
59 */
60struct GNUNET_IDENTITY_PROVIDER_PluginFunctions
61{
62
63 /**
64 * Closure to pass to all plugin functions.
65 */
66 void *cls;
67
68 /**
69 * Store a ticket in the database.
70 *
71 * @param cls closure (internal context for the plugin)
72 * @param ticket the ticket to store
73 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
74 */
75 int (*store_ticket) (void *cls,
76 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
77 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
78
79 /**
80 * Delete a ticket from the database.
81 *
82 * @param cls closure (internal context for the plugin)
83 * @param ticket the ticket to store
84 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
85 */
86 int (*delete_ticket) (void *cls,
87 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
88
89
90
91 /**
92 * Iterate over all tickets
93 *
94 * @param cls closure (internal context for the plugin)
95 * @param identity the identity
96 * @param audience GNUNET_YES if the identity is the audience of the ticket
97 * else it is considered the issuer
98 * @param iter function to call with the result
99 * @param iter_cls closure for @a iter
100 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
101 */
102 int (*iterate_tickets) (void *cls,
103 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
104 int audience,
105 uint64_t offset,
106 GNUNET_IDENTITY_PROVIDER_TicketIterator iter, void *iter_cls);
107
108 int (*get_ticket_attributes) (void* cls,
109 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
110 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
111 void *iter_cls);
112};
113
114#if 0 /* keep Emacsens' auto-indent happy */
115{
116#endif
117#ifdef __cplusplus
118}
119#endif
120
121#endif
122
123/** @} */ /* end of group */
diff --git a/src/include/gnunet_identity_provider_service.h b/src/include/gnunet_identity_provider_service.h
index e533f6f8c..be935e898 100644
--- a/src/include/gnunet_identity_provider_service.h
+++ b/src/include/gnunet_identity_provider_service.h
@@ -39,7 +39,7 @@ extern "C"
39#endif 39#endif
40 40
41#include "gnunet_util_lib.h" 41#include "gnunet_util_lib.h"
42 42#include "gnunet_identity_attribute_lib.h"
43 43
44/** 44/**
45 * Version number of GNUnet Identity Provider API. 45 * Version number of GNUnet Identity Provider API.
@@ -57,169 +57,310 @@ struct GNUNET_IDENTITY_PROVIDER_Handle;
57struct GNUNET_IDENTITY_PROVIDER_Token; 57struct GNUNET_IDENTITY_PROVIDER_Token;
58 58
59/** 59/**
60 * Handle for a ticket 60 * The ticket
61 */ 61 */
62struct GNUNET_IDENTITY_PROVIDER_Ticket; 62struct GNUNET_IDENTITY_PROVIDER_Ticket
63{
64 /**
65 * The ticket issuer
66 */
67 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
68
69 /**
70 * The ticket audience
71 */
72 struct GNUNET_CRYPTO_EcdsaPublicKey audience;
73
74 /**
75 * The ticket random (NBO)
76 */
77 uint64_t rnd;
78};
63 79
64/** 80/**
65 * Handle for an operation with the identity provider service. 81 * Handle for an operation with the identity provider service.
66 */ 82 */
67struct GNUNET_IDENTITY_PROVIDER_Operation; 83struct GNUNET_IDENTITY_PROVIDER_Operation;
68 84
85
69/** 86/**
70 * Method called when a token has been exchanged for a ticket. 87 * Connect to the identity provider service.
71 * On success returns a token
72 * 88 *
73 * @param cls closure 89 * @param cfg Configuration to contact the identity provider service.
74 * @param token the token 90 * @return handle to communicate with identity provider service
75 */ 91 */
76typedef void 92struct GNUNET_IDENTITY_PROVIDER_Handle *
77(*GNUNET_IDENTITY_PROVIDER_ExchangeCallback)(void *cls, 93GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
78 const struct GNUNET_IDENTITY_PROVIDER_Token *token,
79 uint64_t ticket_nonce);
80 94
81/** 95/**
82 * Method called when a token has been issued. 96 * Continuation called to notify client about result of the
83 * On success returns a ticket that can be given to the audience to retrive the 97 * operation.
84 * token
85 * 98 *
86 * @param cls closure 99 * @param cls closure
87 * @param grant the label in GNS pointing to the token 100 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
88 * @param ticket the ticket 101 * #GNUNET_NO if content was already there or not found
89 * @param token the issued token 102 * #GNUNET_YES (or other positive value) on success
90 * @param name name assigned by the user for this ego, 103 * @param emsg NULL on success, otherwise an error message
91 * NULL if the user just deleted the ego and it
92 * must thus no longer be used
93 */ 104 */
94typedef void 105typedef void
95(*GNUNET_IDENTITY_PROVIDER_IssueCallback)(void *cls, 106(*GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus) (void *cls,
96 const char *grant, 107 int32_t success,
97 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, 108 const char *emsg);
98 const struct GNUNET_IDENTITY_PROVIDER_Token *token);
99 109
100 110
101/** 111/**
102 * Connect to the identity provider service. 112 * Store an attribute. If the attribute is already present,
113 * it is replaced with the new attribute.
103 * 114 *
104 * @param cfg Configuration to contact the identity provider service. 115 * @param h handle to the identity provider
105 * @return handle to communicate with identity provider service 116 * @param pkey private key of the identity
117 * @param attr the attribute
118 * @param cont continuation to call when done
119 * @param cont_cls closure for @a cont
120 * @return handle to abort the request
106 */ 121 */
107struct GNUNET_IDENTITY_PROVIDER_Handle * 122struct GNUNET_IDENTITY_PROVIDER_Operation *
108GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); 123GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
124 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
125 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
126 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
127 void *cont_cls);
109 128
110 129
111/** 130/**
112 * Issue a token for a specific audience. 131 * Process an attribute that was stored in the idp.
113 * 132 *
114 * @param id identity provider service to use 133 * @param cls closure
115 * @param iss issuer (identity) 134 * @param identity the identity
116 * @param aud audience (identity) 135 * @param attr the attribute
117 * @param scope the identity attributes requested, comman separated
118 * @param expiration the token expiration
119 * @param nonce the nonce that will be included in token and ticket
120 * @param cb callback to call with result
121 * @param cb_cls closure
122 * @return handle to abort the operation
123 */ 136 */
124struct GNUNET_IDENTITY_PROVIDER_Operation * 137typedef void
125GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id, 138(*GNUNET_IDENTITY_PROVIDER_AttributeResult) (void *cls,
126 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key, 139 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
127 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, 140 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
128 const char* scope, 141
129 struct GNUNET_TIME_Absolute expiration,
130 uint64_t nonce,
131 GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
132 void *cb_cls);
133 142
134 143
135/** 144/**
136 * Exchange a ticket for a token. Intended to be used by audience that 145 * List all attributes for a local identity.
137 * received a ticket. 146 * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
147 * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
148 * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
149 * immediately, and then again after
150 * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
138 * 151 *
139 * @param id identity provider service to use 152 * On error (disconnect), @a error_cb will be invoked.
140 * @param ticket the ticket to exchange 153 * On normal completion, @a finish_cb proc will be
141 * @param aud_privkey the audience of the ticket 154 * invoked.
142 * @param cont function to call once the operation finished 155 *
143 * @param cont_cls closure for @a cont 156 * @param h handle to the idp
144 * @return handle to abort the operation 157 * @param identity identity to access
158 * @param error_cb function to call on error (i.e. disconnect),
159 * the handle is afterwards invalid
160 * @param error_cb_cls closure for @a error_cb
161 * @param proc function to call on each attribute; it
162 * will be called repeatedly with a value (if available)
163 * @param proc_cls closure for @a proc
164 * @param finish_cb function to call on completion
165 * the handle is afterwards invalid
166 * @param finish_cb_cls closure for @a finish_cb
167 * @return an iterator handle to use for iteration
145 */ 168 */
146struct GNUNET_IDENTITY_PROVIDER_Operation * 169struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
147GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id, 170GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
148 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, 171 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
149 const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey, 172 GNUNET_SCHEDULER_TaskCallback error_cb,
150 GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont, 173 void *error_cb_cls,
151 void *cont_cls); 174 GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
175 void *proc_cls,
176 GNUNET_SCHEDULER_TaskCallback finish_cb,
177 void *finish_cb_cls);
152 178
153 179
154/** 180/**
155 * Disconnect from identity provider service. 181 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
182 * for the next record.
156 * 183 *
157 * @param h identity provider service to disconnect 184 * @param it the iterator
158 */ 185 */
159void 186void
160GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); 187GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
161 188
162 189
163/** 190/**
164 * Cancel an identity provider operation. Note that the operation MAY still 191 * Stops iteration and releases the idp handle for further calls. Must
165 * be executed; this merely cancels the continuation; if the request 192 * be called on any iteration that has not yet completed prior to calling
166 * was already transmitted, the service may still choose to complete 193 * #GNUNET_IDENTITY_PROVIDER_disconnect.
167 * the operation.
168 * 194 *
169 * @param op operation to cancel 195 * @param it the iterator
170 */ 196 */
171void 197void
172GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op); 198GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
173 199
174 200
175/** 201/**
176 * Convenience API 202 * Method called when a token has been issued.
203 * On success returns a ticket that can be given to the audience to retrive the
204 * token
205 *
206 * @param cls closure
207 * @param ticket the ticket
177 */ 208 */
209typedef void
210(*GNUNET_IDENTITY_PROVIDER_TicketCallback)(void *cls,
211 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
178 212
179/** 213/**
180 * Destroy token 214 * Issues a ticket to another identity. The identity may use
215 * GNUNET_IDENTITY_PROVIDER_ticket_consume to consume the ticket
216 * and retrieve the attributes specified in the AttributeList.
181 * 217 *
182 * @param token the token 218 * @param h the identity provider to use
219 * @param iss the issuing identity
220 * @param rp the subject of the ticket (the relying party)
221 * @param attrs the attributes that the relying party is given access to
222 * @param cb the callback
223 * @param cb_cls the callback closure
224 * @return handle to abort the operation
183 */ 225 */
184void 226struct GNUNET_IDENTITY_PROVIDER_Operation *
185GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token); 227GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
228 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
229 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
230 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
231 GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
232 void *cb_cls);
186 233
187/** 234/**
188 * Returns string representation of token. A JSON-Web-Token. 235 * Revoked an issued ticket. The relying party will be unable to retrieve
236 * updated attributes.
189 * 237 *
190 * @param token the token 238 * @param h the identity provider to use
191 * @return The JWT (must be freed) 239 * @param identity the issuing identity
240 * @param ticket the ticket to revoke
241 * @param cb the callback
242 * @param cb_cls the callback closure
243 * @return handle to abort the operation
192 */ 244 */
193char * 245struct GNUNET_IDENTITY_PROVIDER_Operation *
194GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token); 246GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
247 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
248 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
249 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
250 void *cb_cls);
251
252
195 253
196/** 254/**
197 * Returns string representation of ticket. Base64-Encoded 255 * Consumes an issued ticket. The ticket is persisted
256 * and used to retrieve identity information from the issuer
198 * 257 *
199 * @param ticket the ticket 258 * @param h the identity provider to use
200 * @return the Base64-Encoded ticket 259 * @param identity the identity that is the subject of the issued ticket (the audience)
260 * @param ticket the issued ticket to consume
261 * @param cb the callback to call
262 * @param cb_cls the callback closure
263 * @return handle to abort the operation
264 */
265struct GNUNET_IDENTITY_PROVIDER_Operation *
266GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
267 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
268 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
269 GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
270 void *cb_cls);
271
272/**
273 * Lists all tickets that have been issued to remote
274 * identites (relying parties)
275 *
276 * @param h the identity provider to use
277 * @param identity the issuing identity
278 * @param error_cb function to call on error (i.e. disconnect),
279 * the handle is afterwards invalid
280 * @param error_cb_cls closure for @a error_cb
281 * @param proc function to call on each ticket; it
282 * will be called repeatedly with a value (if available)
283 * @param proc_cls closure for @a proc
284 * @param finish_cb function to call on completion
285 * the handle is afterwards invalid
286 * @param finish_cb_cls closure for @a finish_cb
287 * @return an iterator handle to use for iteration
288 */
289struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
290GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
291 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
292 GNUNET_SCHEDULER_TaskCallback error_cb,
293 void *error_cb_cls,
294 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
295 void *proc_cls,
296 GNUNET_SCHEDULER_TaskCallback finish_cb,
297 void *finish_cb_cls);
298
299/**
300 * Lists all tickets that have been issued to remote
301 * identites (relying parties)
302 *
303 * @param h the identity provider to use
304 * @param identity the issuing identity
305 * @param error_cb function to call on error (i.e. disconnect),
306 * the handle is afterwards invalid
307 * @param error_cb_cls closure for @a error_cb
308 * @param proc function to call on each ticket; it
309 * will be called repeatedly with a value (if available)
310 * @param proc_cls closure for @a proc
311 * @param finish_cb function to call on completion
312 * the handle is afterwards invalid
313 * @param finish_cb_cls closure for @a finish_cb
314 * @return an iterator handle to use for iteration
201 */ 315 */
202char * 316struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
203GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); 317GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
318 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
319 GNUNET_SCHEDULER_TaskCallback error_cb,
320 void *error_cb_cls,
321 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
322 void *proc_cls,
323 GNUNET_SCHEDULER_TaskCallback finish_cb,
324 void *finish_cb_cls);
204 325
205/** 326/**
206 * Created a ticket from a string (Base64 encoded ticket) 327 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
328 * for the next record.
207 * 329 *
208 * @param input Base64 encoded ticket 330 * @param it the iterator
209 * @param ticket pointer where the ticket is stored
210 * @return GNUNET_OK
211 */ 331 */
212int 332void
213GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, 333GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
214 struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket);
215 334
216/** 335/**
217 * Destroys a ticket 336 * Stops iteration and releases the idp handle for further calls. Must
337 * be called on any iteration that has not yet completed prior to calling
338 * #GNUNET_IDENTITY_PROVIDER_disconnect.
218 * 339 *
219 * @param ticket the ticket to destroy 340 * @param it the iterator
220 */ 341 */
221void 342void
222GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); 343GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
344
345/**
346 * Disconnect from identity provider service.
347 *
348 * @param h identity provider service to disconnect
349 */
350void
351GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
352
353
354/**
355 * Cancel an identity provider operation. Note that the operation MAY still
356 * be executed; this merely cancels the continuation; if the request
357 * was already transmitted, the service may still choose to complete
358 * the operation.
359 *
360 * @param op operation to cancel
361 */
362void
363GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op);
223 364
224#if 0 /* keep Emacsens' auto-indent happy */ 365#if 0 /* keep Emacsens' auto-indent happy */
225{ 366{
diff --git a/src/include/gnunet_jsonapi_lib.h b/src/include/gnunet_jsonapi_lib.h
index f95bff836..2f6b810f0 100644
--- a/src/include/gnunet_jsonapi_lib.h
+++ b/src/include/gnunet_jsonapi_lib.h
@@ -248,7 +248,7 @@ GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource
248 * @param res the JSON resource 248 * @param res the JSON resource
249 * @return the resource id 249 * @return the resource id
250 */ 250 */
251char* 251const char*
252GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource); 252GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource);
253 253
254 254
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 9cfd00e39..436adc5a4 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2628,13 +2628,47 @@ extern "C"
2628 * 2628 *
2629 * IDENTITY PROVIDER MESSAGE TYPES 2629 * IDENTITY PROVIDER MESSAGE TYPES
2630 */ 2630 */
2631#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE 961 2631#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE 961
2632 2632
2633#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE 962 2633#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE 962
2634 2634
2635#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT 963 2635#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START 963
2636 2636
2637#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT 964 2637#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP 964
2638
2639#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT 965
2640
2641#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 966
2642
2643#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET 967
2644
2645#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 968
2646
2647#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET 969
2648
2649#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT 970
2650
2651#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET 971
2652
2653#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT 972
2654
2655#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START 973
2656
2657#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP 974
2658
2659#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT 975
2660
2661/**************************************************
2662 *
2663 * CREDENTIAL MESSAGE TYPES
2664 */
2665#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY 981
2666
2667#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 982
2668
2669#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 983
2670
2671#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 984
2638 2672
2639/******************************************************************************/ 2673/******************************************************************************/
2640 2674
diff --git a/src/include/gnunet_rest_lib.h b/src/include/gnunet_rest_lib.h
index a4dbb0696..e571eead3 100644
--- a/src/include/gnunet_rest_lib.h
+++ b/src/include/gnunet_rest_lib.h
@@ -89,7 +89,7 @@ typedef void (*GNUNET_REST_ResultProcessor) (void *cls,
89 * 89 *
90 * @param url URL to check 90 * @param url URL to check
91 * @param namespace namespace to check against 91 * @param namespace namespace to check against
92 * @retun GNUNET_YES if namespace matches 92 * @return GNUNET_YES if namespace matches
93 */ 93 */
94int 94int
95GNUNET_REST_namespace_match (const char *url, const char *namespace); 95GNUNET_REST_namespace_match (const char *url, const char *namespace);
@@ -98,7 +98,7 @@ GNUNET_REST_namespace_match (const char *url, const char *namespace);
98 * Create REST MHD response 98 * Create REST MHD response
99 * 99 *
100 * @param data result 100 * @param data result
101 * @retun MHD response 101 * @return MHD response
102 */ 102 */
103 struct MHD_Response* 103 struct MHD_Response*
104GNUNET_REST_create_response (const char *data); 104GNUNET_REST_create_response (const char *data);
diff --git a/src/include/gnunet_rest_plugin.h b/src/include/gnunet_rest_plugin.h
index ecd5f66f1..424dbb1fc 100644
--- a/src/include/gnunet_rest_plugin.h
+++ b/src/include/gnunet_rest_plugin.h
@@ -57,7 +57,7 @@ struct GNUNET_REST_Plugin
57 57
58 /** 58 /**
59 * Plugin name. Used as the namespace for the API. 59 * Plugin name. Used as the namespace for the API.
60 * e.g. http://hostname:port/<name> 60 * e.g. http://hostname:port/name
61 */ 61 */
62 char *name; 62 char *name;
63 63
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index c1e0d005c..03bc4575e 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -185,6 +185,11 @@ extern "C"
185 */ 185 */
186#define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27 186#define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27
187 187
188/**
189 * Signature for a GNUnet credential
190 */
191#define GNUNET_SIGNATURE_PURPOSE_CREDENTIAL 28
192
188#if 0 /* keep Emacsens' auto-indent happy */ 193#if 0 /* keep Emacsens' auto-indent happy */
189{ 194{
190#endif 195#endif
diff --git a/src/jsonapi/jsonapi_document.c b/src/jsonapi/jsonapi_document.c
index 600b7ee6a..3a60940f6 100644
--- a/src/jsonapi/jsonapi_document.c
+++ b/src/jsonapi/jsonapi_document.c
@@ -332,28 +332,20 @@ GNUNET_JSONAPI_document_to_json (const struct GNUNET_JSONAPI_Document *doc,
332 GNUNET_JSONAPI_KEY_ERRORS, 332 GNUNET_JSONAPI_KEY_ERRORS,
333 res_json); 333 res_json);
334 } else { 334 } else {
335 switch (doc->res_count) 335 if (0 == doc->res_count)
336 { 336 {
337 case 0: 337 res_json = json_null();
338 res_json = json_null(); 338 } else {
339 break; 339 res_json = json_array ();
340 case 1: 340 for (res = doc->res_list_head;
341 res != NULL;
342 res = res->next)
343 {
341 GNUNET_assert (GNUNET_OK == 344 GNUNET_assert (GNUNET_OK ==
342 GNUNET_JSONAPI_resource_to_json (doc->res_list_head, 345 GNUNET_JSONAPI_resource_to_json (res,
343 &res_json)); 346 &res_json_tmp));
344 break; 347 json_array_append_new (res_json, res_json_tmp);
345 default: 348 }
346 res_json = json_array ();
347 for (res = doc->res_list_head;
348 res != NULL;
349 res = res->next)
350 {
351 GNUNET_assert (GNUNET_OK ==
352 GNUNET_JSONAPI_resource_to_json (res,
353 &res_json_tmp));
354 json_array_append (res_json, res_json_tmp);
355 }
356 break;
357 } 349 }
358 json_object_set_new (*root_json, 350 json_object_set_new (*root_json,
359 GNUNET_JSONAPI_KEY_DATA, 351 GNUNET_JSONAPI_KEY_DATA,
diff --git a/src/jsonapi/jsonapi_resource.c b/src/jsonapi/jsonapi_resource.c
index 85bca10ee..be28ad5df 100644
--- a/src/jsonapi/jsonapi_resource.c
+++ b/src/jsonapi/jsonapi_resource.c
@@ -92,9 +92,9 @@ GNUNET_JSONAPI_resource_new (const char *type, const char *id)
92{ 92{
93 struct GNUNET_JSONAPI_Resource *res; 93 struct GNUNET_JSONAPI_Resource *res;
94 94
95 if ( (NULL == type) || (0 == strlen (type)) ) 95 if (NULL == type)
96 return NULL; 96 return NULL;
97 if ( (NULL == id) || (0 == strlen (id)) ) 97 if (NULL == id)
98 return NULL; 98 return NULL;
99 99
100 res = GNUNET_new (struct GNUNET_JSONAPI_Resource); 100 res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
@@ -245,7 +245,7 @@ GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource
245 * @param res the JSON resource 245 * @param res the JSON resource
246 * @return the resource id 246 * @return the resource id
247 */ 247 */
248char* 248const char*
249GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource) 249GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource)
250{ 250{
251 return resource->id; 251 return resource->id;
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c
index 50957a5b4..05776801b 100644
--- a/src/namestore/plugin_rest_namestore.c
+++ b/src/namestore/plugin_rest_namestore.c
@@ -401,11 +401,16 @@ namestore_list_finished (void *cls)
401 struct MHD_Response *resp; 401 struct MHD_Response *resp;
402 402
403 handle->list_it = NULL; 403 handle->list_it = NULL;
404 if (NULL == handle->resp_object)
405 handle->resp_object = GNUNET_JSONAPI_document_new ();
406
404 if (GNUNET_SYSERR == 407 if (GNUNET_SYSERR ==
405 GNUNET_JSONAPI_document_serialize (handle->resp_object, 408 GNUNET_JSONAPI_document_serialize (handle->resp_object,
406 &result)) 409 &result))
407 { 410 {
408 do_error (handle); 411 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
412 GNUNET_SCHEDULER_add_now (&do_error,
413 handle);
409 return; 414 return;
410 } 415 }
411 resp = GNUNET_REST_create_response (result); 416 resp = GNUNET_REST_create_response (result);
@@ -467,10 +472,10 @@ namestore_list_response (void *cls,
467 if (0 < json_array_size(result_array)) 472 if (0 < json_array_size(result_array))
468 { 473 {
469 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO, 474 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
470 rname); 475 rname);
471 GNUNET_JSONAPI_resource_add_attr (json_resource, 476 GNUNET_JSONAPI_resource_add_attr (json_resource,
472 GNUNET_REST_JSONAPI_NAMESTORE_RECORD, 477 GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
473 result_array); 478 result_array);
474 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); 479 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
475 } 480 }
476 481
@@ -767,8 +772,8 @@ namestore_create_cont (struct GNUNET_REST_RequestHandle *con,
767 } 772 }
768 term_data[handle->rest_handle->data_size] = '\0'; 773 term_data[handle->rest_handle->data_size] = '\0';
769 GNUNET_memcpy (term_data, 774 GNUNET_memcpy (term_data,
770 handle->rest_handle->data, 775 handle->rest_handle->data,
771 handle->rest_handle->data_size); 776 handle->rest_handle->data_size);
772 data_js = json_loads (term_data, 777 data_js = json_loads (term_data,
773 JSON_DECODE_ANY, 778 JSON_DECODE_ANY,
774 &err); 779 &err);
@@ -902,7 +907,7 @@ namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con,
902 if ((NULL == handle->zkey_str) || 907 if ((NULL == handle->zkey_str) ||
903 (GNUNET_OK != 908 (GNUNET_OK !=
904 GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str, 909 GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str,
905 strlen (handle->zkey_str), 910 strlen (handle->zkey_str),
906 &pubkey))) 911 &pubkey)))
907 { 912 {
908 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 913 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1021,13 +1026,13 @@ identity_cb (void *cls,
1021 1026
1022 if (GNUNET_OK != 1027 if (GNUNET_OK !=
1023 GNUNET_JSONAPI_handle_request (handle->rest_handle, 1028 GNUNET_JSONAPI_handle_request (handle->rest_handle,
1024 handlers, 1029 handlers,
1025 &err, 1030 &err,
1026 handle)) 1031 handle))
1027 { 1032 {
1028 handle->response_code = err.error_code; 1033 handle->response_code = err.error_code;
1029 GNUNET_SCHEDULER_add_now (&do_error, 1034 GNUNET_SCHEDULER_add_now (&do_error,
1030 (void *) handle); 1035 (void *) handle);
1031 } 1036 }
1032} 1037}
1033 1038
diff --git a/src/rest/rest.conf b/src/rest/rest.conf
index 6cd013345..b86e6c1a0 100644
--- a/src/rest/rest.conf
+++ b/src/rest/rest.conf
@@ -1,4 +1,5 @@
1[rest] 1[rest]
2UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-rest.sock
2BINARY=gnunet-rest-server 3BINARY=gnunet-rest-server
3REST_PORT=7776 4REST_PORT=7776
4REST_ALLOW_HEADERS=Authorization,Accept,Content-Type 5REST_ALLOW_HEADERS=Authorization,Accept,Content-Type
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index c26e3e84b..eb655157d 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -123,7 +123,6 @@ libgnunetutil_la_LDFLAGS = \
123 $(GN_LIB_LDFLAGS) \ 123 $(GN_LIB_LDFLAGS) \
124 -version-info 13:0:0 124 -version-info 13:0:0
125 125
126
127libgnunetutil_taler_wallet_la_SOURCES = \ 126libgnunetutil_taler_wallet_la_SOURCES = \
128 common_allocation.c \ 127 common_allocation.c \
129 common_endian.c \ 128 common_endian.c \
diff --git a/src/util/crypto_abe.c b/src/util/crypto_abe.c
new file mode 100644
index 000000000..fcaa826ed
--- /dev/null
+++ b/src/util/crypto_abe.c
@@ -0,0 +1,416 @@
1/*
2 This file is part of GNUnet. Copyright (C) 2001-2014 Christian Grothoff
3 (and other contributing authors)
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 util/crypto_random.c
24 * @brief functions to gather random numbers
25 * @author Christian Grothoff
26 */
27
28
29#include "platform.h"
30#include <pbc/pbc.h>
31#include <gabe.h>
32
33#include "gnunet_crypto_lib.h"
34
35struct GNUNET_CRYPTO_AbeMasterKey
36{
37 gabe_pub_t* pub;
38 gabe_msk_t* msk;
39};
40
41struct GNUNET_CRYPTO_AbeKey
42{
43 gabe_pub_t* pub;
44 gabe_prv_t* prv;
45};
46
47static int
48init_aes( element_t k, int enc,
49 gcry_cipher_hd_t* handle,
50 struct GNUNET_CRYPTO_SymmetricSessionKey *key,
51 unsigned char* iv)
52{
53 int rc;
54 int key_len;
55 unsigned char* key_buf;
56
57 key_len = element_length_in_bytes(k) < 33 ? 3 : element_length_in_bytes(k);
58 key_buf = (unsigned char*) malloc(key_len);
59 element_to_bytes(key_buf, k);
60
61 memcpy (key->aes_key, key_buf, GNUNET_CRYPTO_AES_KEY_LENGTH);
62 GNUNET_assert (0 ==
63 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
64 GCRY_CIPHER_MODE_CFB, 0));
65 rc = gcry_cipher_setkey (*handle,
66 key->aes_key,
67 sizeof (key->aes_key));
68 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
69 memset (iv, 0, 16); //TODO make reasonable
70 rc = gcry_cipher_setiv (*handle,
71 iv,
72 16);
73 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
74
75 free(key_buf);
76 return rc;
77}
78
79static int
80aes_128_cbc_encrypt( char* pt,
81 int size,
82 element_t k,
83 char **ct )
84{
85 gcry_cipher_hd_t handle;
86 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
87 unsigned char iv[16];
88 char* buf;
89 int padding;
90 int buf_size;
91 uint8_t len[4];
92 init_aes(k, 1, &handle, &skey, iv);
93
94 /* TODO make less crufty */
95
96 /* stuff in real length (big endian) before padding */
97 len[0] = (size & 0xff000000)>>24;
98 len[1] = (size & 0xff0000)>>16;
99 len[2] = (size & 0xff00)>>8;
100 len[3] = (size & 0xff)>>0;
101 padding = 16 - ((4+size) % 16);
102 buf_size = 4 + size + padding;
103 buf = GNUNET_malloc (buf_size);
104 GNUNET_memcpy (buf, len, 4);
105 GNUNET_memcpy (buf+4, pt, size);
106 *ct = GNUNET_malloc (buf_size);
107
108 GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf, buf_size));
109 gcry_cipher_close (handle);
110 //AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
111 GNUNET_free (buf);
112 return buf_size;
113}
114
115static int
116aes_128_cbc_decrypt( char* ct,
117 int size,
118 element_t k,
119 char **pt )
120{
121 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
122 gcry_cipher_hd_t handle;
123 unsigned char iv[16];
124 char* tmp;
125 uint32_t len;
126
127 init_aes(k, 1, &handle, &skey, iv);
128
129 tmp = GNUNET_malloc (size);
130
131 //AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
132 GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size));
133 gcry_cipher_close (handle);
134 /* TODO make less crufty */
135
136 /* get real length */
137 len = 0;
138 len = len
139 | ((tmp[0])<<24) | ((tmp[1])<<16)
140 | ((tmp[2])<<8) | ((tmp[3])<<0);
141 /* truncate any garbage from the padding */
142 *pt = GNUNET_malloc (len);
143 GNUNET_memcpy (*pt, tmp+4, len);
144 GNUNET_free (tmp);
145 return len;
146}
147
148struct GNUNET_CRYPTO_AbeMasterKey*
149GNUNET_CRYPTO_cpabe_create_master_key (void)
150{
151 struct GNUNET_CRYPTO_AbeMasterKey* key;
152 key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
153 gabe_setup(&key->pub, &key->msk);
154 GNUNET_assert (NULL != key->pub);
155 GNUNET_assert (NULL != key->msk);
156 return key;
157}
158
159void
160GNUNET_CRYPTO_cpabe_delete_master_key (struct GNUNET_CRYPTO_AbeMasterKey *key)
161{
162 gabe_msk_free (key->msk);
163 gabe_pub_free (key->pub);
164 //GNUNET_free (key->msk);
165 //gabe_msk_free (key->msk); //For some reason free of pub implicit?
166 GNUNET_free (key);
167}
168
169struct GNUNET_CRYPTO_AbeKey*
170GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *key,
171 char **attrs)
172{
173 struct GNUNET_CRYPTO_AbeKey *prv_key;
174 int size;
175 char *tmp;
176
177 prv_key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
178 prv_key->prv = gabe_keygen(key->pub, key->msk, attrs);
179 size = gabe_pub_serialize(key->pub, &tmp);
180 prv_key->pub = gabe_pub_unserialize(tmp, size);
181 GNUNET_free (tmp);
182 GNUNET_assert (NULL != prv_key->prv);
183 return prv_key;
184}
185
186void
187GNUNET_CRYPTO_cpabe_delete_key (struct GNUNET_CRYPTO_AbeKey *key,
188 int delete_pub)
189{
190 //Memory management in gabe is buggy
191 gabe_prv_free (key->prv);
192 if (GNUNET_YES == delete_pub)
193 gabe_pub_free (key->pub);
194 GNUNET_free (key);
195}
196
197ssize_t
198write_cpabe (void **result,
199 uint32_t file_len,
200 char* cph_buf,
201 int cph_buf_len,
202 char* aes_buf,
203 int aes_buf_len)
204{
205 char *ptr;
206 uint32_t *len;
207
208 *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
209 ptr = *result;
210 len = (uint32_t*) ptr;
211 *len = htonl (file_len);
212 ptr += 4;
213 len = (uint32_t*) ptr;
214 *len = htonl (aes_buf_len);
215 ptr += 4;
216 memcpy (ptr, aes_buf, aes_buf_len);
217 ptr += aes_buf_len;
218 len = (uint32_t*) ptr;
219 *len = htonl (cph_buf_len);
220 ptr += 4;
221 memcpy (ptr, cph_buf, cph_buf_len);
222 return 12 + cph_buf_len + aes_buf_len;
223}
224
225ssize_t
226read_cpabe (const void *data,
227 char** cph_buf,
228 int *cph_buf_len,
229 char** aes_buf,
230 int *aes_buf_len)
231{
232 int buf_len;
233 char *ptr;
234 uint32_t *len;
235
236 ptr = (char*)data;
237 len = (uint32_t*)ptr;
238 buf_len = ntohl (*len);
239 ptr += 4;
240 len = (uint32_t*)ptr;
241 *aes_buf_len = ntohl (*len);
242 ptr += 4;
243 *aes_buf = GNUNET_malloc (*aes_buf_len);
244 memcpy(*aes_buf, ptr, *aes_buf_len);
245 ptr += *aes_buf_len;
246 len = (uint32_t*)ptr;
247 *cph_buf_len = ntohl (*len);
248 ptr += 4;
249 *cph_buf = GNUNET_malloc (*cph_buf_len);
250 memcpy(*cph_buf, ptr, *cph_buf_len);
251
252 return buf_len;
253}
254
255ssize_t
256GNUNET_CRYPTO_cpabe_encrypt (const void *block,
257 size_t size,
258 const char *policy,
259 const struct GNUNET_CRYPTO_AbeMasterKey *key,
260 void **result)
261{
262 gabe_cph_t* cph;
263 char* plt;
264 char* cph_buf;
265 char* aes_buf;
266 element_t m;
267 int cph_buf_len;
268 int aes_buf_len;
269 ssize_t result_len;
270
271 if( !(cph = gabe_enc(key->pub, m, (char*)policy)) )
272 return GNUNET_SYSERR;
273 cph_buf_len = gabe_cph_serialize(cph,
274 &cph_buf);
275 gabe_cph_free(cph);
276 GNUNET_free (cph);
277 plt = GNUNET_memdup (block, size);
278 aes_buf_len = aes_128_cbc_encrypt(plt, size, m, &aes_buf);
279 GNUNET_free (plt);
280 element_clear(m);
281 result_len = write_cpabe(result, size, cph_buf, cph_buf_len, aes_buf, aes_buf_len);
282 GNUNET_free(cph_buf);
283 GNUNET_free(aes_buf);
284 return result_len;
285}
286
287ssize_t
288GNUNET_CRYPTO_cpabe_decrypt (const void *block,
289 size_t size,
290 const struct GNUNET_CRYPTO_AbeKey *key,
291 void **result)
292{
293 char* aes_buf;
294 char* cph_buf;
295 gabe_cph_t* cph;
296 element_t m;
297 int cph_buf_size;
298 int aes_buf_size;
299 int plt_len;
300
301 read_cpabe(block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
302 cph = gabe_cph_unserialize(key->pub, cph_buf, cph_buf_size);
303 if( !gabe_dec(key->pub, key->prv, cph, m) ) {
304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
305 "%s\n", gabe_error());
306 GNUNET_free (aes_buf);
307 GNUNET_free (cph_buf);
308 gabe_cph_free(cph);
309 GNUNET_free (cph);
310 element_clear (m);
311 return GNUNET_SYSERR;
312 }
313 gabe_cph_free(cph);
314 GNUNET_free (cph);
315 plt_len = aes_128_cbc_decrypt(aes_buf, aes_buf_size, m, (char**)result);
316 GNUNET_free (cph_buf);
317 GNUNET_free (aes_buf);
318 element_clear (m);
319 //freeing is buggy in gabe
320 //gabe_prv_free (prv);
321 //gabe_pub_free (pub);
322 return plt_len;
323}
324
325ssize_t
326GNUNET_CRYPTO_cpabe_serialize_key (const struct GNUNET_CRYPTO_AbeKey *key,
327 void **result)
328{
329 ssize_t len;
330 char *pub;
331 char *prv;
332 int pub_len;
333 int prv_len;
334
335 pub_len = gabe_pub_serialize (key->pub, &pub);
336 prv_len = gabe_prv_serialize (key->prv, &prv);
337
338 len = pub_len + prv_len + 12;
339 write_cpabe (result, len, pub, pub_len, prv, prv_len);
340
341 GNUNET_free (pub);
342 GNUNET_free (prv);
343
344 return len;
345}
346
347struct GNUNET_CRYPTO_AbeKey*
348GNUNET_CRYPTO_cpabe_deserialize_key (const void *data,
349 size_t len)
350{
351 struct GNUNET_CRYPTO_AbeKey *key;
352 char *pub;
353 char *prv;
354 int prv_len;
355 int pub_len;
356
357 key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
358 read_cpabe (data,
359 &pub,
360 &pub_len,
361 &prv,
362 &prv_len);
363 key->pub = gabe_pub_unserialize (pub, pub_len);
364 key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
365
366 GNUNET_free (pub);
367 GNUNET_free (prv);
368 return key;
369}
370
371ssize_t
372GNUNET_CRYPTO_cpabe_serialize_master_key (const struct GNUNET_CRYPTO_AbeMasterKey *key,
373 void **result)
374{
375 ssize_t len;
376 char *pub;
377 char *msk;
378 int pub_len;
379 int msk_len;
380
381 pub_len = gabe_pub_serialize (key->pub, &pub);
382 msk_len = gabe_msk_serialize (key->msk, &msk);
383
384 len = pub_len + msk_len + 12;
385 write_cpabe (result, len, pub, pub_len, msk, msk_len);
386
387 GNUNET_free (pub);
388 GNUNET_free (msk);
389
390 return len;
391}
392
393struct GNUNET_CRYPTO_AbeMasterKey*
394GNUNET_CRYPTO_cpabe_deserialize_master_key (const void *data,
395 size_t len)
396{
397 struct GNUNET_CRYPTO_AbeMasterKey *key;
398 char *msk;
399 char *pub;
400 int msk_len;
401 int pub_len;
402
403 key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
404 read_cpabe (data,
405 &pub,
406 &pub_len,
407 &msk,
408 &msk_len);
409 key->pub = gabe_pub_unserialize (pub, pub_len);
410 key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
411
412 GNUNET_free (pub);
413 GNUNET_free (msk);
414
415 return key;
416}