aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Dockerfile63
-rw-r--r--configure.ac24
-rw-r--r--docker-entrypoint.sh3
-rw-r--r--po/POTFILES.in133
-rw-r--r--src/Makefile.am13
-rw-r--r--src/credential/Makefile.am112
-rw-r--r--src/credential/credential.conf.in5
-rw-r--r--src/credential/credential.h221
-rw-r--r--src/credential/credential_api.c513
-rw-r--r--src/credential/credential_misc.c169
-rw-r--r--src/credential/credential_misc.h35
-rw-r--r--src/credential/credential_serialization.c463
-rw-r--r--src/credential/credential_serialization.h159
-rw-r--r--src/credential/gnunet-credential.c602
-rw-r--r--src/credential/gnunet-service-credential.c1238
-rw-r--r--src/credential/plugin_gnsrecord_credential.c353
-rw-r--r--src/credential/plugin_rest_credential.c1179
-rwxr-xr-xsrc/credential/test_credential_collect.sh47
-rwxr-xr-xsrc/credential/test_credential_collect_rest.sh90
-rw-r--r--src/credential/test_credential_defaults.conf24
-rwxr-xr-xsrc/credential/test_credential_issue.sh44
-rwxr-xr-xsrc/credential/test_credential_issue_rest.sh53
-rw-r--r--src/credential/test_credential_lookup.conf28
-rwxr-xr-xsrc/credential/test_credential_verify.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_and.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_rest.sh87
-rwxr-xr-xsrc/credential/test_credential_verify_simple.sh50
-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.am73
-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.c3104
-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.c1205
-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)44
-rw-r--r--src/identity-provider/plugin_identity_provider_sqlite.c736
-rw-r--r--src/identity-provider/plugin_rest_identity_provider.c1108
-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_credential_service.h308
-rw-r--r--src/include/gnunet_crypto_lib.h82
-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.h332
-rw-r--r--src/include/gnunet_jsonapi_lib.h2
-rw-r--r--src/include/gnunet_protocols.h42
-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.am24
-rw-r--r--src/util/crypto_abe.c416
-rw-r--r--src/util/test_crypto_abe.c86
73 files changed, 13818 insertions, 3742 deletions
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..5a193a46d
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,63 @@
1from fedora:26
2
3# Install the required build tools
4RUN dnf -y update && dnf -y install which git automake texinfo gettext-devel autoconf libtool libtool-ltdl-devel libidn-devel libunistring-devel glpk libextractor-devel libmicrohttpd-devel gnutls libgcrypt-devel jansson-devel sqlite-devel npm
5
6WORKDIR /usr/src
7
8# Install gnurl from source at version gnurl-7.54.0
9RUN git clone https://git.taler.net/gnurl.git --branch gnurl-7.54.0
10WORKDIR /usr/src/gnurl
11RUN autoreconf -i
12RUN ./configure --enable-ipv6 --with-gnutls --without-libssh2 \
13--without-libmetalink --without-winidn --without-librtmp \
14--without-nghttp2 --without-nss --without-cyassl \
15--without-polarssl --without-ssl --without-winssl \
16--without-darwinssl --disable-sspi --disable-ntlm-wb --disable-ldap \
17--disable-rtsp --disable-dict --disable-telnet --disable-tftp \
18--disable-pop3 --disable-imap --disable-smtp --disable-gopher \
19--disable-file --disable-ftp --disable-smb
20RUN make install
21WORKDIR /usr/src
22
23RUN dnf -y install wget flex bison
24
25# Install libpbc
26RUN wget https://crypto.stanford.edu/pbc/files/pbc-0.5.14.tar.gz
27RUN tar xvzpf pbc-0.5.14.tar.gz
28WORKDIR /usr/src/pbc-0.5.14
29RUN ./configure --prefix=/usr
30RUN make install
31WORKDIR /usr/src
32
33RUN dnf -y install glib2-devel
34
35# Install libbswabe
36RUN git clone https://github.com/schanzen/libgabe.git
37WORKDIR /usr/src/libgabe
38RUN ./configure --prefix=/usr
39RUN make install
40
41# Install WebUI
42WORKDIR /usr/src/
43RUN git clone https://github.com/schanzen/gnunet-webui.git
44WORKDIR /usr/src/gnunet-webui
45RUN git checkout gnuidentity
46
47RUN mkdir /usr/src/gnunet
48WORKDIR /usr/src/gnunet
49ADD . .
50ARG NUM_JOBS
51RUN ./bootstrap
52RUN ./configure --prefix=/usr/local
53RUN make -j$NUM_JOBS
54RUN make install
55
56RUN groupadd gnunetdns
57RUN adduser --system -m --home-dir /var/lib/gnunet gnunet
58RUN chown gnunet:gnunet /var/lib/gnunet
59RUN echo '[arm]\nSYSTEM_ONLY = YES\nUSER_ONLY = NO\n' > /etc/gnunet.conf
60
61ADD docker-entrypoint.sh .
62
63CMD ["sh", "docker-entrypoint.sh"]
diff --git a/configure.ac b/configure.ac
index eae03b01b..ac00bd5d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -446,6 +446,27 @@ AC_CHECK_LIB(ogg, ogg_stream_flush_fill,
446 ogg=0) 446 ogg=0)
447 447
448 448
449PKG_CHECK_MODULES([GLIB], [glib-2.0])
450# check for pbc library
451pbc=0
452AC_CHECK_HEADER([pbc/pbc.h],pbc=1)
453AC_CHECK_HEADER([gabe.h],abe=1)
454AM_CONDITIONAL(HAVE_PBC, [test "$pbc" = 1])
455AM_CONDITIONAL(HAVE_ABE, [test "$abe" = 1])
456if test "x$pbc" = x1
457then
458 AC_DEFINE([HAVE_PBC],[1],[Have pbc library])
459else
460 AC_DEFINE([HAVE_PBC],[0],[Lacking pbc library])
461fi
462if test "x$abe" = x1
463then
464 AC_DEFINE([HAVE_ABE],[1],[Have ABE library])
465else
466 AC_DEFINE([HAVE_ABE],[0],[Lacking ABE library])
467fi
468
469
449 470
450gst=0 471gst=0
451PKG_CHECK_MODULES( 472PKG_CHECK_MODULES(
@@ -1570,6 +1591,8 @@ src/gnsrecord/Makefile
1570src/hello/Makefile 1591src/hello/Makefile
1571src/identity/Makefile 1592src/identity/Makefile
1572src/identity/identity.conf 1593src/identity/identity.conf
1594src/credential/Makefile
1595src/credential/credential.conf
1573src/include/Makefile 1596src/include/Makefile
1574src/integration-tests/Makefile 1597src/integration-tests/Makefile
1575src/json/Makefile 1598src/json/Makefile
@@ -1635,6 +1658,7 @@ src/vpn/vpn.conf
1635src/zonemaster/Makefile 1658src/zonemaster/Makefile
1636src/zonemaster/zonemaster.conf 1659src/zonemaster/zonemaster.conf
1637src/rest/Makefile 1660src/rest/Makefile
1661src/identity-attribute/Makefile
1638src/identity-provider/Makefile 1662src/identity-provider/Makefile
1639pkgconfig/Makefile 1663pkgconfig/Makefile
1640pkgconfig/gnunetarm.pc 1664pkgconfig/gnunetarm.pc
diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh
new file mode 100644
index 000000000..807d86d6f
--- /dev/null
+++ b/docker-entrypoint.sh
@@ -0,0 +1,3 @@
1#!/bin/bash
2gnunet-arm -s > $HOME/gnunet.log 2>&1
3exec bash \ No newline at end of file
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4a4cfbd96..e0654d4b4 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,13 +3,21 @@ src/arm/arm_monitor_api.c
3src/arm/gnunet-arm.c 3src/arm/gnunet-arm.c
4src/arm/gnunet-service-arm.c 4src/arm/gnunet-service-arm.c
5src/arm/mockup-service.c 5src/arm/mockup-service.c
6src/ats-tests/ats-testing-experiment.c
7src/ats-tests/ats-testing-log.c
8src/ats-tests/ats-testing-preferences.c
9src/ats-tests/ats-testing-traffic.c
10src/ats-tests/ats-testing.c
11src/ats-tests/gnunet-ats-sim.c
12src/ats-tests/gnunet-solver-eval.c
13src/ats-tool/gnunet-ats.c
6src/ats/ats_api_connectivity.c 14src/ats/ats_api_connectivity.c
7src/ats/ats_api_performance.c 15src/ats/ats_api_performance.c
8src/ats/ats_api_scanner.c 16src/ats/ats_api_scanner.c
9src/ats/ats_api_scheduling.c 17src/ats/ats_api_scheduling.c
10src/ats/gnunet-ats-solver-eval.c 18src/ats/gnunet-ats-solver-eval.c
11src/ats/gnunet-service-ats_addresses.c
12src/ats/gnunet-service-ats.c 19src/ats/gnunet-service-ats.c
20src/ats/gnunet-service-ats_addresses.c
13src/ats/gnunet-service-ats_connectivity.c 21src/ats/gnunet-service-ats_connectivity.c
14src/ats/gnunet-service-ats_normalization.c 22src/ats/gnunet-service-ats_normalization.c
15src/ats/gnunet-service-ats_performance.c 23src/ats/gnunet-service-ats_performance.c
@@ -20,14 +28,6 @@ src/ats/gnunet-service-ats_scheduling.c
20src/ats/plugin_ats_mlp.c 28src/ats/plugin_ats_mlp.c
21src/ats/plugin_ats_proportional.c 29src/ats/plugin_ats_proportional.c
22src/ats/plugin_ats_ril.c 30src/ats/plugin_ats_ril.c
23src/ats-tests/ats-testing.c
24src/ats-tests/ats-testing-experiment.c
25src/ats-tests/ats-testing-log.c
26src/ats-tests/ats-testing-preferences.c
27src/ats-tests/ats-testing-traffic.c
28src/ats-tests/gnunet-ats-sim.c
29src/ats-tests/gnunet-solver-eval.c
30src/ats-tool/gnunet-ats.c
31src/auction/gnunet-auction-create.c 31src/auction/gnunet-auction-create.c
32src/auction/gnunet-auction-info.c 32src/auction/gnunet-auction-info.c
33src/auction/gnunet-auction-join.c 33src/auction/gnunet-auction-join.c
@@ -39,8 +39,8 @@ src/block/plugin_block_test.c
39src/cadet/cadet_api.c 39src/cadet/cadet_api.c
40src/cadet/cadet_test_lib.c 40src/cadet/cadet_test_lib.c
41src/cadet/desirability_table.c 41src/cadet/desirability_table.c
42src/cadet/gnunet-cadet.c
43src/cadet/gnunet-cadet-profiler.c 42src/cadet/gnunet-cadet-profiler.c
43src/cadet/gnunet-cadet.c
44src/cadet/gnunet-service-cadet.c 44src/cadet/gnunet-service-cadet.c
45src/cadet/gnunet-service-cadet_channel.c 45src/cadet/gnunet-service-cadet_channel.c
46src/cadet/gnunet-service-cadet_connection.c 46src/cadet/gnunet-service-cadet_connection.c
@@ -56,15 +56,15 @@ src/consensus/gnunet-service-consensus.c
56src/consensus/plugin_block_consensus.c 56src/consensus/plugin_block_consensus.c
57src/conversation/conversation_api.c 57src/conversation/conversation_api.c
58src/conversation/conversation_api_call.c 58src/conversation/conversation_api_call.c
59src/conversation/gnunet-conversation.c
60src/conversation/gnunet-conversation-test.c 59src/conversation/gnunet-conversation-test.c
61src/conversation/gnunet_gst.c 60src/conversation/gnunet-conversation.c
62src/conversation/gnunet_gst_test.c
63src/conversation/gnunet-helper-audio-playback.c
64src/conversation/gnunet-helper-audio-playback-gst.c 61src/conversation/gnunet-helper-audio-playback-gst.c
65src/conversation/gnunet-helper-audio-record.c 62src/conversation/gnunet-helper-audio-playback.c
66src/conversation/gnunet-helper-audio-record-gst.c 63src/conversation/gnunet-helper-audio-record-gst.c
64src/conversation/gnunet-helper-audio-record.c
67src/conversation/gnunet-service-conversation.c 65src/conversation/gnunet-service-conversation.c
66src/conversation/gnunet_gst.c
67src/conversation/gnunet_gst_test.c
68src/conversation/microphone.c 68src/conversation/microphone.c
69src/conversation/plugin_gnsrecord_conversation.c 69src/conversation/plugin_gnsrecord_conversation.c
70src/conversation/speaker.c 70src/conversation/speaker.c
@@ -75,6 +75,13 @@ src/core/gnunet-service-core.c
75src/core/gnunet-service-core_kx.c 75src/core/gnunet-service-core_kx.c
76src/core/gnunet-service-core_sessions.c 76src/core/gnunet-service-core_sessions.c
77src/core/gnunet-service-core_typemap.c 77src/core/gnunet-service-core_typemap.c
78src/credential/credential_api.c
79src/credential/credential_misc.c
80src/credential/credential_serialization.c
81src/credential/gnunet-credential.c
82src/credential/gnunet-service-credential.c
83src/credential/plugin_gnsrecord_credential.c
84src/credential/plugin_rest_credential.c
78src/curl/curl.c 85src/curl/curl.c
79src/curl/curl_reschedule.c 86src/curl/curl_reschedule.c
80src/datacache/datacache.c 87src/datacache/datacache.c
@@ -94,7 +101,6 @@ src/dht/dht_api.c
94src/dht/dht_test_lib.c 101src/dht/dht_test_lib.c
95src/dht/gnunet-dht-get.c 102src/dht/gnunet-dht-get.c
96src/dht/gnunet-dht-monitor.c 103src/dht/gnunet-dht-monitor.c
97src/dht/gnunet_dht_profiler.c
98src/dht/gnunet-dht-put.c 104src/dht/gnunet-dht-put.c
99src/dht/gnunet-service-dht.c 105src/dht/gnunet-service-dht.c
100src/dht/gnunet-service-dht_clients.c 106src/dht/gnunet-service-dht_clients.c
@@ -103,6 +109,7 @@ src/dht/gnunet-service-dht_hello.c
103src/dht/gnunet-service-dht_neighbours.c 109src/dht/gnunet-service-dht_neighbours.c
104src/dht/gnunet-service-dht_nse.c 110src/dht/gnunet-service-dht_nse.c
105src/dht/gnunet-service-dht_routing.c 111src/dht/gnunet-service-dht_routing.c
112src/dht/gnunet_dht_profiler.c
106src/dht/plugin_block_dht.c 113src/dht/plugin_block_dht.c
107src/dns/dns_api.c 114src/dns/dns_api.c
108src/dns/dnsparser.c 115src/dns/dnsparser.c
@@ -117,8 +124,8 @@ src/dv/gnunet-dv.c
117src/dv/gnunet-service-dv.c 124src/dv/gnunet-service-dv.c
118src/dv/plugin_transport_dv.c 125src/dv/plugin_transport_dv.c
119src/exit/gnunet-daemon-exit.c 126src/exit/gnunet-daemon-exit.c
120src/exit/gnunet-helper-exit.c
121src/exit/gnunet-helper-exit-windows.c 127src/exit/gnunet-helper-exit-windows.c
128src/exit/gnunet-helper-exit.c
122src/fragmentation/defragmentation.c 129src/fragmentation/defragmentation.c
123src/fragmentation/fragmentation.c 130src/fragmentation/fragmentation.c
124src/fs/fs_api.c 131src/fs/fs_api.c
@@ -143,8 +150,8 @@ src/fs/gnunet-auto-share.c
143src/fs/gnunet-daemon-fsprofiler.c 150src/fs/gnunet-daemon-fsprofiler.c
144src/fs/gnunet-directory.c 151src/fs/gnunet-directory.c
145src/fs/gnunet-download.c 152src/fs/gnunet-download.c
146src/fs/gnunet-fs.c
147src/fs/gnunet-fs-profiler.c 153src/fs/gnunet-fs-profiler.c
154src/fs/gnunet-fs.c
148src/fs/gnunet-helper-fs-publish.c 155src/fs/gnunet-helper-fs-publish.c
149src/fs/gnunet-publish.c 156src/fs/gnunet-publish.c
150src/fs/gnunet-search.c 157src/fs/gnunet-search.c
@@ -162,10 +169,10 @@ src/fs/plugin_block_fs.c
162src/gns/gns_api.c 169src/gns/gns_api.c
163src/gns/gnunet-bcd.c 170src/gns/gnunet-bcd.c
164src/gns/gnunet-dns2gns.c 171src/gns/gnunet-dns2gns.c
165src/gns/gnunet-gns.c
166src/gns/gnunet-gns-helper-service-w32.c 172src/gns/gnunet-gns-helper-service-w32.c
167src/gns/gnunet-gns-import.c 173src/gns/gnunet-gns-import.c
168src/gns/gnunet-gns-proxy.c 174src/gns/gnunet-gns-proxy.c
175src/gns/gnunet-gns.c
169src/gns/gnunet-service-gns.c 176src/gns/gnunet-service-gns.c
170src/gns/gnunet-service-gns_interceptor.c 177src/gns/gnunet-service-gns_interceptor.c
171src/gns/gnunet-service-gns_resolver.c 178src/gns/gnunet-service-gns_resolver.c
@@ -174,41 +181,44 @@ src/gns/nss/nss_gns_query.c
174src/gns/plugin_block_gns.c 181src/gns/plugin_block_gns.c
175src/gns/plugin_gnsrecord_gns.c 182src/gns/plugin_gnsrecord_gns.c
176src/gns/plugin_rest_gns.c 183src/gns/plugin_rest_gns.c
184src/gns/w32nsp-install.c
185src/gns/w32nsp-resolve.c
186src/gns/w32nsp-uninstall.c
187src/gns/w32nsp.c
177src/gnsrecord/gnsrecord.c 188src/gnsrecord/gnsrecord.c
178src/gnsrecord/gnsrecord_crypto.c 189src/gnsrecord/gnsrecord_crypto.c
179src/gnsrecord/gnsrecord_misc.c 190src/gnsrecord/gnsrecord_misc.c
180src/gnsrecord/gnsrecord_serialization.c 191src/gnsrecord/gnsrecord_serialization.c
181src/gnsrecord/plugin_gnsrecord_dns.c 192src/gnsrecord/plugin_gnsrecord_dns.c
182src/gns/w32nsp.c
183src/gns/w32nsp-install.c
184src/gns/w32nsp-resolve.c
185src/gns/w32nsp-uninstall.c
186src/hello/address.c 193src/hello/address.c
187src/hello/gnunet-hello.c 194src/hello/gnunet-hello.c
188src/hello/hello.c 195src/hello/hello.c
189src/hostlist/gnunet-daemon-hostlist.c 196src/hostlist/gnunet-daemon-hostlist.c
190src/hostlist/gnunet-daemon-hostlist_client.c 197src/hostlist/gnunet-daemon-hostlist_client.c
191src/hostlist/gnunet-daemon-hostlist_server.c 198src/hostlist/gnunet-daemon-hostlist_server.c
199src/identity-attribute/identity_attribute.c
200src/identity-attribute/plugin_identity_attribute_gnuid.c
201src/identity-provider/gnunet-idp.c
202src/identity-provider/gnunet-service-identity-provider.c
203src/identity-provider/identity_provider_api.c
204src/identity-provider/jwt.c
205src/identity-provider/plugin_gnsrecord_identity_provider.c
206src/identity-provider/plugin_identity_provider_sqlite.c
207src/identity-provider/plugin_rest_identity_provider.c
192src/identity/gnunet-identity.c 208src/identity/gnunet-identity.c
193src/identity/gnunet-service-identity.c 209src/identity/gnunet-service-identity.c
194src/identity/identity_api.c 210src/identity/identity_api.c
195src/identity/identity_api_lookup.c 211src/identity/identity_api_lookup.c
196src/identity/plugin_gnsrecord_identity.c
197src/identity/plugin_rest_identity.c 212src/identity/plugin_rest_identity.c
198src/identity-provider/gnunet-identity-token.c 213src/json/json.c
199src/identity-provider/gnunet-service-identity-provider.c 214src/json/json_generator.c
200src/identity-provider/identity_provider_api.c 215src/json/json_helper.c
201src/identity-provider/identity_token.c 216src/json/json_mhd.c
202src/identity-provider/plugin_rest_identity_provider.c
203src/jsonapi/jsonapi.c 217src/jsonapi/jsonapi.c
204src/jsonapi/jsonapi_document.c 218src/jsonapi/jsonapi_document.c
205src/jsonapi/jsonapi_error.c 219src/jsonapi/jsonapi_error.c
206src/jsonapi/jsonapi_relationship.c 220src/jsonapi/jsonapi_relationship.c
207src/jsonapi/jsonapi_resource.c 221src/jsonapi/jsonapi_resource.c
208src/json/json.c
209src/json/json_generator.c
210src/json/json_helper.c
211src/json/json_mhd.c
212src/multicast/gnunet-multicast.c 222src/multicast/gnunet-multicast.c
213src/multicast/gnunet-service-multicast.c 223src/multicast/gnunet-service-multicast.c
214src/multicast/multicast_api.c 224src/multicast/multicast_api.c
@@ -222,8 +232,8 @@ src/namecache/namecache_api.c
222src/namecache/plugin_namecache_flat.c 232src/namecache/plugin_namecache_flat.c
223src/namecache/plugin_namecache_postgres.c 233src/namecache/plugin_namecache_postgres.c
224src/namecache/plugin_namecache_sqlite.c 234src/namecache/plugin_namecache_sqlite.c
225src/namestore/gnunet-namestore.c
226src/namestore/gnunet-namestore-fcfsd.c 235src/namestore/gnunet-namestore-fcfsd.c
236src/namestore/gnunet-namestore.c
227src/namestore/gnunet-service-namestore.c 237src/namestore/gnunet-service-namestore.c
228src/namestore/namestore_api.c 238src/namestore/namestore_api.c
229src/namestore/namestore_api_monitor.c 239src/namestore/namestore_api_monitor.c
@@ -238,10 +248,10 @@ src/nat-auto/gnunet-service-nat-auto.c
238src/nat-auto/gnunet-service-nat-auto_legacy.c 248src/nat-auto/gnunet-service-nat-auto_legacy.c
239src/nat-auto/nat_auto_api.c 249src/nat-auto/nat_auto_api.c
240src/nat-auto/nat_auto_api_test.c 250src/nat-auto/nat_auto_api_test.c
241src/nat/gnunet-helper-nat-client.c
242src/nat/gnunet-helper-nat-client-windows.c 251src/nat/gnunet-helper-nat-client-windows.c
243src/nat/gnunet-helper-nat-server.c 252src/nat/gnunet-helper-nat-client.c
244src/nat/gnunet-helper-nat-server-windows.c 253src/nat/gnunet-helper-nat-server-windows.c
254src/nat/gnunet-helper-nat-server.c
245src/nat/gnunet-nat.c 255src/nat/gnunet-nat.c
246src/nat/gnunet-service-nat.c 256src/nat/gnunet-service-nat.c
247src/nat/gnunet-service-nat_externalip.c 257src/nat/gnunet-service-nat_externalip.c
@@ -250,15 +260,15 @@ src/nat/gnunet-service-nat_mini.c
250src/nat/gnunet-service-nat_stun.c 260src/nat/gnunet-service-nat_stun.c
251src/nat/nat_api.c 261src/nat/nat_api.c
252src/nat/nat_api_stun.c 262src/nat/nat_api_stun.c
253src/nse/gnunet-nse.c
254src/nse/gnunet-nse-profiler.c 263src/nse/gnunet-nse-profiler.c
264src/nse/gnunet-nse.c
255src/nse/gnunet-service-nse.c 265src/nse/gnunet-service-nse.c
256src/nse/nse_api.c 266src/nse/nse_api.c
267src/peerinfo-tool/gnunet-peerinfo.c
268src/peerinfo-tool/gnunet-peerinfo_plugins.c
257src/peerinfo/gnunet-service-peerinfo.c 269src/peerinfo/gnunet-service-peerinfo.c
258src/peerinfo/peerinfo_api.c 270src/peerinfo/peerinfo_api.c
259src/peerinfo/peerinfo_api_notify.c 271src/peerinfo/peerinfo_api_notify.c
260src/peerinfo-tool/gnunet-peerinfo.c
261src/peerinfo-tool/gnunet-peerinfo_plugins.c
262src/peerstore/gnunet-peerstore.c 272src/peerstore/gnunet-peerstore.c
263src/peerstore/gnunet-service-peerstore.c 273src/peerstore/gnunet-service-peerstore.c
264src/peerstore/peerstore_api.c 274src/peerstore/peerstore_api.c
@@ -309,13 +319,13 @@ src/rps/gnunet-service-rps_custommap.c
309src/rps/gnunet-service-rps_sampler.c 319src/rps/gnunet-service-rps_sampler.c
310src/rps/gnunet-service-rps_sampler_elem.c 320src/rps/gnunet-service-rps_sampler_elem.c
311src/rps/gnunet-service-rps_view.c 321src/rps/gnunet-service-rps_view.c
312src/rps/rps_api.c
313src/rps/rps-test_util.c 322src/rps/rps-test_util.c
323src/rps/rps_api.c
314src/scalarproduct/gnunet-scalarproduct.c 324src/scalarproduct/gnunet-scalarproduct.c
315src/scalarproduct/gnunet-service-scalarproduct_alice.c
316src/scalarproduct/gnunet-service-scalarproduct_bob.c
317src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c 325src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
318src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c 326src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
327src/scalarproduct/gnunet-service-scalarproduct_alice.c
328src/scalarproduct/gnunet-service-scalarproduct_bob.c
319src/scalarproduct/scalarproduct_api.c 329src/scalarproduct/scalarproduct_api.c
320src/secretsharing/gnunet-secretsharing-profiler.c 330src/secretsharing/gnunet-secretsharing-profiler.c
321src/secretsharing/gnunet-service-secretsharing.c 331src/secretsharing/gnunet-service-secretsharing.c
@@ -342,15 +352,16 @@ src/statistics/gnunet-statistics.c
342src/statistics/statistics_api.c 352src/statistics/statistics_api.c
343src/template/gnunet-service-template.c 353src/template/gnunet-service-template.c
344src/template/gnunet-template.c 354src/template/gnunet-template.c
355src/testbed-logger/gnunet-service-testbed-logger.c
356src/testbed-logger/testbed_logger_api.c
345src/testbed/generate-underlay-topology.c 357src/testbed/generate-underlay-topology.c
346src/testbed/gnunet-daemon-latency-logger.c 358src/testbed/gnunet-daemon-latency-logger.c
347src/testbed/gnunet-daemon-testbed-blacklist.c 359src/testbed/gnunet-daemon-testbed-blacklist.c
348src/testbed/gnunet-daemon-testbed-underlay.c 360src/testbed/gnunet-daemon-testbed-underlay.c
349src/testbed/gnunet-helper-testbed.c 361src/testbed/gnunet-helper-testbed.c
350src/testbed/gnunet_mpi_test.c
351src/testbed/gnunet-service-test-barriers.c 362src/testbed/gnunet-service-test-barriers.c
352src/testbed/gnunet-service-testbed_barriers.c
353src/testbed/gnunet-service-testbed.c 363src/testbed/gnunet-service-testbed.c
364src/testbed/gnunet-service-testbed_barriers.c
354src/testbed/gnunet-service-testbed_cache.c 365src/testbed/gnunet-service-testbed_cache.c
355src/testbed/gnunet-service-testbed_connectionpool.c 366src/testbed/gnunet-service-testbed_connectionpool.c
356src/testbed/gnunet-service-testbed_cpustatus.c 367src/testbed/gnunet-service-testbed_cpustatus.c
@@ -358,20 +369,19 @@ src/testbed/gnunet-service-testbed_links.c
358src/testbed/gnunet-service-testbed_meminfo.c 369src/testbed/gnunet-service-testbed_meminfo.c
359src/testbed/gnunet-service-testbed_oc.c 370src/testbed/gnunet-service-testbed_oc.c
360src/testbed/gnunet-service-testbed_peers.c 371src/testbed/gnunet-service-testbed_peers.c
361src/testbed/gnunet_testbed_mpi_spawn.c
362src/testbed/gnunet-testbed-profiler.c 372src/testbed/gnunet-testbed-profiler.c
363src/testbed-logger/gnunet-service-testbed-logger.c 373src/testbed/gnunet_mpi_test.c
364src/testbed-logger/testbed_logger_api.c 374src/testbed/gnunet_testbed_mpi_spawn.c
365src/testbed/testbed_api_barriers.c
366src/testbed/testbed_api.c 375src/testbed/testbed_api.c
376src/testbed/testbed_api_barriers.c
367src/testbed/testbed_api_hosts.c 377src/testbed/testbed_api_hosts.c
368src/testbed/testbed_api_operations.c 378src/testbed/testbed_api_operations.c
369src/testbed/testbed_api_peers.c 379src/testbed/testbed_api_peers.c
370src/testbed/testbed_api_sd.c 380src/testbed/testbed_api_sd.c
371src/testbed/testbed_api_services.c 381src/testbed/testbed_api_services.c
372src/testbed/testbed_api_statistics.c 382src/testbed/testbed_api_statistics.c
373src/testbed/testbed_api_testbed.c
374src/testbed/testbed_api_test.c 383src/testbed/testbed_api_test.c
384src/testbed/testbed_api_testbed.c
375src/testbed/testbed_api_topology.c 385src/testbed/testbed_api_topology.c
376src/testbed/testbed_api_underlay.c 386src/testbed/testbed_api_underlay.c
377src/testing/gnunet-testing.c 387src/testing/gnunet-testing.c
@@ -380,34 +390,39 @@ src/testing/testing.c
380src/topology/friends.c 390src/topology/friends.c
381src/topology/gnunet-daemon-topology.c 391src/topology/gnunet-daemon-topology.c
382src/transport/gnunet-helper-transport-bluetooth.c 392src/transport/gnunet-helper-transport-bluetooth.c
383src/transport/gnunet-helper-transport-wlan.c
384src/transport/gnunet-helper-transport-wlan-dummy.c 393src/transport/gnunet-helper-transport-wlan-dummy.c
385src/transport/gnunet-service-transport_ats.c 394src/transport/gnunet-helper-transport-wlan.c
386src/transport/gnunet-service-transport.c 395src/transport/gnunet-service-transport.c
396src/transport/gnunet-service-transport_ats.c
387src/transport/gnunet-service-transport_hello.c 397src/transport/gnunet-service-transport_hello.c
388src/transport/gnunet-service-transport_manipulation.c 398src/transport/gnunet-service-transport_manipulation.c
389src/transport/gnunet-service-transport_neighbours.c 399src/transport/gnunet-service-transport_neighbours.c
390src/transport/gnunet-service-transport_plugins.c 400src/transport/gnunet-service-transport_plugins.c
391src/transport/gnunet-service-transport_validation.c 401src/transport/gnunet-service-transport_validation.c
392src/transport/gnunet-transport.c
393src/transport/gnunet-transport-certificate-creation.c 402src/transport/gnunet-transport-certificate-creation.c
394src/transport/gnunet-transport-profiler.c 403src/transport/gnunet-transport-profiler.c
395src/transport/gnunet-transport-wlan-receiver.c 404src/transport/gnunet-transport-wlan-receiver.c
396src/transport/gnunet-transport-wlan-sender.c 405src/transport/gnunet-transport-wlan-sender.c
406src/transport/gnunet-transport.c
397src/transport/plugin_transport_http_client.c 407src/transport/plugin_transport_http_client.c
398src/transport/plugin_transport_http_common.c 408src/transport/plugin_transport_http_common.c
399src/transport/plugin_transport_http_server.c 409src/transport/plugin_transport_http_server.c
400src/transport/plugin_transport_smtp.c 410src/transport/plugin_transport_smtp.c
401src/transport/plugin_transport_tcp.c 411src/transport/plugin_transport_tcp.c
402src/transport/plugin_transport_template.c 412src/transport/plugin_transport_template.c
403src/transport/plugin_transport_udp_broadcasting.c
404src/transport/plugin_transport_udp.c 413src/transport/plugin_transport_udp.c
414src/transport/plugin_transport_udp_broadcasting.c
405src/transport/plugin_transport_unix.c 415src/transport/plugin_transport_unix.c
406src/transport/plugin_transport_wlan.c 416src/transport/plugin_transport_wlan.c
407src/transport/tcp_connection_legacy.c 417src/transport/tcp_connection_legacy.c
408src/transport/tcp_server_legacy.c 418src/transport/tcp_server_legacy.c
409src/transport/tcp_server_mst_legacy.c 419src/transport/tcp_server_mst_legacy.c
410src/transport/tcp_service_legacy.c 420src/transport/tcp_service_legacy.c
421src/transport/transport-testing-filenames.c
422src/transport/transport-testing-loggers.c
423src/transport/transport-testing-main.c
424src/transport/transport-testing-send.c
425src/transport/transport-testing.c
411src/transport/transport_api_address_to_string.c 426src/transport/transport_api_address_to_string.c
412src/transport/transport_api_blacklist.c 427src/transport/transport_api_blacklist.c
413src/transport/transport_api_core.c 428src/transport/transport_api_core.c
@@ -416,11 +431,6 @@ src/transport/transport_api_manipulation.c
416src/transport/transport_api_monitor_peers.c 431src/transport/transport_api_monitor_peers.c
417src/transport/transport_api_monitor_plugins.c 432src/transport/transport_api_monitor_plugins.c
418src/transport/transport_api_offer_hello.c 433src/transport/transport_api_offer_hello.c
419src/transport/transport-testing.c
420src/transport/transport-testing-filenames.c
421src/transport/transport-testing-loggers.c
422src/transport/transport-testing-main.c
423src/transport/transport-testing-send.c
424src/tun/regex.c 434src/tun/regex.c
425src/tun/tun.c 435src/tun/tun.c
426src/util/bandwidth.c 436src/util/bandwidth.c
@@ -434,10 +444,11 @@ src/util/configuration_loader.c
434src/util/container_bloomfilter.c 444src/util/container_bloomfilter.c
435src/util/container_heap.c 445src/util/container_heap.c
436src/util/container_meta_data.c 446src/util/container_meta_data.c
437src/util/container_multihashmap32.c
438src/util/container_multihashmap.c 447src/util/container_multihashmap.c
448src/util/container_multihashmap32.c
439src/util/container_multipeermap.c 449src/util/container_multipeermap.c
440src/util/container_multishortmap.c 450src/util/container_multishortmap.c
451src/util/crypto_abe.c
441src/util/crypto_crc.c 452src/util/crypto_crc.c
442src/util/crypto_ecc.c 453src/util/crypto_ecc.c
443src/util/crypto_ecc_dlog.c 454src/util/crypto_ecc_dlog.c
@@ -454,8 +465,8 @@ src/util/crypto_symmetric.c
454src/util/disk.c 465src/util/disk.c
455src/util/getopt.c 466src/util/getopt.c
456src/util/getopt_helpers.c 467src/util/getopt_helpers.c
457src/util/gnunet-config.c
458src/util/gnunet-config-diff.c 468src/util/gnunet-config-diff.c
469src/util/gnunet-config.c
459src/util/gnunet-ecc.c 470src/util/gnunet-ecc.c
460src/util/gnunet-helper-w32-console.c 471src/util/gnunet-helper-w32-console.c
461src/util/gnunet-resolver.c 472src/util/gnunet-resolver.c
@@ -486,8 +497,8 @@ src/util/time.c
486src/util/w32cat.c 497src/util/w32cat.c
487src/util/win.c 498src/util/win.c
488src/util/winproc.c 499src/util/winproc.c
489src/vpn/gnunet-helper-vpn.c
490src/vpn/gnunet-helper-vpn-windows.c 500src/vpn/gnunet-helper-vpn-windows.c
501src/vpn/gnunet-helper-vpn.c
491src/vpn/gnunet-service-vpn.c 502src/vpn/gnunet-service-vpn.c
492src/vpn/gnunet-vpn.c 503src/vpn/gnunet-vpn.c
493src/vpn/vpn_api.c 504src/vpn/vpn_api.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 7f1a00177..fcdd44bfb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,11 +12,11 @@ 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 += identity-attribute \
18if HAVE_MHD 18 identity-provider \
19 PROVIDER_DIR = identity-provider 19 credential
20endif 20endif
21endif 21endif
22 22
@@ -128,7 +128,6 @@ SUBDIRS = \
128 psyc \ 128 psyc \
129 social \ 129 social \
130 $(AUCTION_DIR) \ 130 $(AUCTION_DIR) \
131 $(EXP_DIR) \ 131 $(EXP_DIR)
132 $(PROVIDER_DIR)
133 132
134endif 133endif
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
new file mode 100644
index 000000000..ca11c5e4f
--- /dev/null
+++ b/src/credential/Makefile.am
@@ -0,0 +1,112 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4EXTRA_DIST = \
5 test_credential_defaults.conf \
6 test_credential_lookup.conf
7
8
9if USE_COVERAGE
10 AM_CFLAGS = --coverage -O0
11endif
12
13pkgcfgdir = $(pkgdatadir)/config.d/
14
15libexecdir= $(pkglibdir)/libexec/
16
17plugindir = $(libdir)/gnunet
18
19pkgcfg_DATA = \
20 credential.conf
21
22
23# /usr/lib - compiles a layer which can be used to be communicagte with the service
24lib_LTLIBRARIES = \
25 libgnunetcredential.la
26
27# /usr/lib/gnunet/libexec - Business logic . Separate process
28libexec_PROGRAMS = \
29 gnunet-service-credential
30
31bin_PROGRAMS = \
32 gnunet-credential
33
34plugin_LTLIBRARIES = \
35 libgnunet_plugin_gnsrecord_credential.la
36
37
38if HAVE_MHD
39if HAVE_JSON
40plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la
41endif
42endif
43
44
45gnunet_credential_SOURCES = \
46 gnunet-credential.c
47gnunet_credential_LDADD = \
48 libgnunetcredential.la \
49 $(top_builddir)/src/util/libgnunetutil.la \
50 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
51 $(top_builddir)/src/identity/libgnunetidentity.la \
52 $(GN_LIBINTL)
53
54
55libgnunet_plugin_gnsrecord_credential_la_SOURCES = \
56 plugin_gnsrecord_credential.c
57libgnunet_plugin_gnsrecord_credential_la_LIBADD = \
58 libgnunetcredential.la \
59 $(top_builddir)/src/util/libgnunetutil.la \
60 $(LTLIBINTL)
61libgnunet_plugin_gnsrecord_credential_la_LDFLAGS = \
62 $(GN_PLUGIN_LDFLAGS)
63
64
65
66gnunet_service_credential_SOURCES = \
67 gnunet-service-credential.c
68gnunet_service_credential_LDADD = \
69 libgnunetcredential.la \
70 $(top_builddir)/src/util/libgnunetutil.la \
71 $(top_builddir)/src/gns/libgnunetgns.la \
72 $(top_builddir)/src/namestore/libgnunetnamestore.la \
73 $(top_builddir)/src/statistics/libgnunetstatistics.la \
74 $(GN_LIBINTL)
75
76
77libgnunetcredential_la_SOURCES = \
78 credential_api.c \
79 credential_serialization.c \
80 credential_misc.c
81libgnunetcredential_la_LIBADD = \
82 $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
83libgnunetcredential_la_LDFLAGS = \
84 $(GN_LIB_LDFLAGS)
85
86
87libgnunet_plugin_rest_credential_la_SOURCES = \
88 plugin_rest_credential.c
89libgnunet_plugin_rest_credential_la_LIBADD = \
90 libgnunetcredential.la \
91 $(top_builddir)/src/rest/libgnunetrest.la \
92 $(top_builddir)/src/identity/libgnunetidentity.la \
93 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
94 $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
95 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
96 $(LTLIBINTL) -ljansson -lmicrohttpd
97libgnunet_plugin_rest_credential_la_LDFLAGS = \
98 $(GN_PLUGIN_LDFLAGS)
99
100
101check_SCRIPTS = \
102 test_credential_issue.sh \
103 test_credential_verify_simple.sh \
104 test_credential_verify.sh \
105 test_credential_verify_and.sh
106
107if ENABLE_TEST_RUN
108if HAVE_SQLITE
109 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
110 TESTS = $(check_SCRIPTS)
111endif
112endif
diff --git a/src/credential/credential.conf.in b/src/credential/credential.conf.in
new file mode 100644
index 000000000..71f3066ca
--- /dev/null
+++ b/src/credential/credential.conf.in
@@ -0,0 +1,5 @@
1[credential]
2BINARY = gnunet-service-credential
3UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-credential.sock
4USER_SERVICE = YES
5OPTIONS = -L DEBUG \ No newline at end of file
diff --git a/src/credential/credential.h b/src/credential/credential.h
new file mode 100644
index 000000000..f16249c1b
--- /dev/null
+++ b/src/credential/credential.h
@@ -0,0 +1,221 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @file credential/credential.h
22 * @brief IPC messages between CREDENTIAL API and CREDENTIAL service
23 * @author Adnan Husain
24 */
25#ifndef CREDENTIAL_H
26#define CREDENTIAL_H
27
28#include "gnunet_credential_service.h"
29
30GNUNET_NETWORK_STRUCT_BEGIN
31
32/**
33 * Message from client to Credential service to collect credentials.
34 */
35struct CollectMessage
36{
37 /**
38 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
39 */
40 struct GNUNET_MessageHeader header;
41
42 /**
43 * Subject public key
44 */
45 struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key;
46
47 /**
48 * Trust anchor
49 */
50 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
51
52 /**
53 * Length of the issuer attribute
54 */
55 uint16_t issuer_attribute_len;
56
57 /**
58 * Unique identifier for this request (for key collisions).
59 */
60 uint32_t id GNUNET_PACKED;
61
62 /* Followed by the zero-terminated attribute */
63
64};
65
66
67/**
68 * Message from client to Credential service to verify attributes.
69 */
70struct VerifyMessage
71{
72 /**
73 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
74 */
75 struct GNUNET_MessageHeader header;
76
77 /**
78 * Subject public key
79 */
80 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
81
82 /**
83 * Trust anchor
84 */
85 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
86
87 /**
88 * Number of credentials
89 */
90 uint32_t c_count;
91
92 /**
93 * Length of the issuer attribute
94 */
95 uint16_t issuer_attribute_len;
96
97 /**
98 * Unique identifier for this request (for key collisions).
99 */
100 uint32_t id GNUNET_PACKED;
101
102 /* Followed by the zero-terminated attribute and credentials to look up */
103
104};
105
106
107/**
108 * Message from CREDENTIAL service to client: new results.
109 */
110struct DelegationChainResultMessage
111{
112 /**
113 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT
114 */
115 struct GNUNET_MessageHeader header;
116
117 /**
118 * Unique identifier for this request (for key collisions).
119 */
120 uint32_t id GNUNET_PACKED;
121
122 /**
123 * Indicates if credential has been found at all
124 */
125 uint32_t cred_found GNUNET_PACKED;
126
127 /**
128 * The number of delegations in the response
129 */
130 uint32_t d_count GNUNET_PACKED;
131
132 /**
133 * The number of credentials in the response
134 */
135 uint32_t c_count GNUNET_PACKED;
136
137 /* followed by ad_count GNUNET_CREDENTIAL_RecordData structs*/
138
139};
140
141struct DelegationRecordData
142{
143 /**
144 * Subject key
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
147
148 /**
149 * Subject attributes
150 */
151 uint32_t subject_attribute_len GNUNET_PACKED;
152};
153
154
155struct ChainEntry
156{
157 /**
158 * Issuer key
159 */
160 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
161
162 /**
163 * Subject key
164 */
165 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
166
167 /**
168 * Issuer attributes
169 */
170 uint32_t issuer_attribute_len GNUNET_PACKED;
171
172 /**
173 * Subject attributes
174 */
175 uint32_t subject_attribute_len GNUNET_PACKED;
176};
177
178
179struct CredentialEntry
180{
181
182 /**
183 * The signature for this credential by the issuer
184 */
185 struct GNUNET_CRYPTO_EcdsaSignature signature;
186
187 /**
188 * Signature meta
189 */
190 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
191
192 /**
193 * Public key of the issuer
194 */
195 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
196
197 /**
198 * Public key of the subject this credential was issued to
199 */
200 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
201
202 /**
203 * Expiration time of this credential
204 */
205 uint64_t expiration GNUNET_PACKED;
206
207 /**
208 * Issuer attribute length
209 */
210 uint32_t issuer_attribute_len;
211
212 /**
213 * Followed by the attribute string
214 */
215};
216
217
218GNUNET_NETWORK_STRUCT_END
219
220#endif
221
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
new file mode 100644
index 000000000..ca54137ad
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,513 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file credential/credential_api.c
22 * @brief library to access the CREDENTIAL service
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_constants.h"
28#include "gnunet_arm_service.h"
29#include "gnunet_hello_lib.h"
30#include "gnunet_protocols.h"
31#include "gnunet_signatures.h"
32#include "credential.h"
33#include "credential_serialization.h"
34#include "gnunet_credential_service.h"
35#include "gnunet_identity_service.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
39
40/**
41 * Handle to a verify request
42 */
43struct GNUNET_CREDENTIAL_Request
44{
45
46 /**
47 * DLL
48 */
49 struct GNUNET_CREDENTIAL_Request *next;
50
51 /**
52 * DLL
53 */
54 struct GNUNET_CREDENTIAL_Request *prev;
55
56 /**
57 * handle to credential service
58 */
59 struct GNUNET_CREDENTIAL_Handle *credential_handle;
60
61 /**
62 * processor to call on verify result
63 */
64 GNUNET_CREDENTIAL_CredentialResultProcessor verify_proc;
65
66 /**
67 * @e verify_proc closure
68 */
69 void *proc_cls;
70
71 /**
72 * Envelope with the message for this queue entry.
73 */
74 struct GNUNET_MQ_Envelope *env;
75
76 /**
77 * request id
78 */
79 uint32_t r_id;
80
81};
82
83
84/**
85 * Connection to the CREDENTIAL service.
86 */
87struct GNUNET_CREDENTIAL_Handle
88{
89
90 /**
91 * Configuration to use.
92 */
93 const struct GNUNET_CONFIGURATION_Handle *cfg;
94
95 /**
96 * Connection to service (if available).
97 */
98 struct GNUNET_MQ_Handle *mq;
99
100 /**
101 * Head of linked list of active verify requests.
102 */
103 struct GNUNET_CREDENTIAL_Request *request_head;
104
105 /**
106 * Tail of linked list of active verify requests.
107 */
108 struct GNUNET_CREDENTIAL_Request *request_tail;
109
110 /**
111 * Reconnect task
112 */
113 struct GNUNET_SCHEDULER_Task *reconnect_task;
114
115 /**
116 * How long do we wait until we try to reconnect?
117 */
118 struct GNUNET_TIME_Relative reconnect_backoff;
119
120 /**
121 * Request Id generator. Incremented by one for each request.
122 */
123 uint32_t r_id_gen;
124
125};
126
127
128/**
129 * Reconnect to CREDENTIAL service.
130 *
131 * @param handle the handle to the CREDENTIAL service
132 */
133static void
134reconnect (struct GNUNET_CREDENTIAL_Handle *handle);
135
136
137/**
138 * Reconnect to CREDENTIAL
139 *
140 * @param cls the handle
141 */
142static void
143reconnect_task (void *cls)
144{
145 struct GNUNET_CREDENTIAL_Handle *handle = cls;
146
147 handle->reconnect_task = NULL;
148 reconnect (handle);
149}
150
151
152/**
153 * Disconnect from service and then reconnect.
154 *
155 * @param handle our handle
156 */
157static void
158force_reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
159{
160 GNUNET_MQ_destroy (handle->mq);
161 handle->mq = NULL;
162 handle->reconnect_backoff
163 = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
164 handle->reconnect_task
165 = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
166 &reconnect_task,
167 handle);
168}
169
170
171/**
172 * Generic error handler, called with the appropriate error code and
173 * the same closure specified at the creation of the message queue.
174 * Not every message queue implementation supports an error handler.
175 *
176 * @param cls closure with the `struct GNUNET_CREDENTIAL_Handle *`
177 * @param error error code
178 */
179static void
180mq_error_handler (void *cls,
181 enum GNUNET_MQ_Error error)
182{
183 struct GNUNET_CREDENTIAL_Handle *handle = cls;
184
185 force_reconnect (handle);
186}
187
188/**
189 * Check validity of message received from the CREDENTIAL service
190 *
191 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
192 * @param loookup_msg the incoming message
193 */
194static int
195check_result (void *cls,
196 const struct DelegationChainResultMessage *vr_msg)
197{
198 //TODO
199 return GNUNET_OK;
200}
201
202
203/**
204 * Handler for messages received from the CREDENTIAL service
205 *
206 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
207 * @param loookup_msg the incoming message
208 */
209static void
210handle_result (void *cls,
211 const struct DelegationChainResultMessage *vr_msg)
212{
213 struct GNUNET_CREDENTIAL_Handle *handle = cls;
214 uint32_t r_id = ntohl (vr_msg->id);
215 struct GNUNET_CREDENTIAL_Request *vr;
216 size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg);
217 uint32_t d_count = ntohl (vr_msg->d_count);
218 uint32_t c_count = ntohl (vr_msg->c_count);
219 struct GNUNET_CREDENTIAL_Delegation d_chain[d_count];
220 struct GNUNET_CREDENTIAL_Credential creds[c_count];
221 GNUNET_CREDENTIAL_CredentialResultProcessor proc;
222 void *proc_cls;
223
224 LOG (GNUNET_ERROR_TYPE_DEBUG,
225 "Received verify reply from CREDENTIAL service\n");
226 for (vr = handle->request_head; NULL != vr; vr = vr->next)
227 if (vr->r_id == r_id)
228 break;
229 if (NULL == vr)
230 return;
231 proc = vr->verify_proc;
232 proc_cls = vr->proc_cls;
233 GNUNET_CONTAINER_DLL_remove (handle->request_head,
234 handle->request_tail,
235 vr);
236 GNUNET_MQ_discard (vr->env);
237 GNUNET_free (vr);
238 GNUNET_assert (GNUNET_OK ==
239 GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen,
240 (const char*) &vr_msg[1],
241 d_count,
242 d_chain,
243 c_count,
244 creds));
245 if (GNUNET_NO == ntohl (vr_msg->cred_found))
246 {
247 proc (proc_cls,
248 0,
249 NULL,
250 0,
251 NULL); // TODO
252 } else {
253 proc (proc_cls,
254 d_count,
255 d_chain,
256 c_count,
257 creds);
258 }
259}
260
261
262/**
263 * Reconnect to CREDENTIAL service.
264 *
265 * @param handle the handle to the CREDENTIAL service
266 */
267static void
268reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
269{
270 struct GNUNET_MQ_MessageHandler handlers[] = {
271 GNUNET_MQ_hd_var_size (result,
272 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
273 struct DelegationChainResultMessage,
274 handle),
275 GNUNET_MQ_hd_var_size (result,
276 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT,
277 struct DelegationChainResultMessage,
278 handle),
279 GNUNET_MQ_handler_end ()
280 };
281 struct GNUNET_CREDENTIAL_Request *vr;
282
283 GNUNET_assert (NULL == handle->mq);
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Trying to connect to CREDENTIAL\n");
286 handle->mq = GNUNET_CLIENT_connect (handle->cfg,
287 "credential",
288 handlers,
289 &mq_error_handler,
290 handle);
291 if (NULL == handle->mq)
292 return;
293 for (vr = handle->request_head; NULL != vr; vr = vr->next)
294 GNUNET_MQ_send_copy (handle->mq,
295 vr->env);
296}
297
298
299/**
300 * Initialize the connection with the CREDENTIAL service.
301 *
302 * @param cfg configuration to use
303 * @return handle to the CREDENTIAL service, or NULL on error
304 */
305struct GNUNET_CREDENTIAL_Handle *
306GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
307{
308 struct GNUNET_CREDENTIAL_Handle *handle;
309
310 handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
311 handle->cfg = cfg;
312 reconnect (handle);
313 if (NULL == handle->mq)
314 {
315 GNUNET_free (handle);
316 return NULL;
317 }
318 return handle;
319}
320
321
322/**
323 * Shutdown connection with the CREDENTIAL service.
324 *
325 * @param handle handle of the CREDENTIAL connection to stop
326 */
327void
328GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle)
329{
330 if (NULL != handle->mq)
331 {
332 GNUNET_MQ_destroy (handle->mq);
333 handle->mq = NULL;
334 }
335 if (NULL != handle->reconnect_task)
336 {
337 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
338 handle->reconnect_task = NULL;
339 }
340 GNUNET_assert (NULL == handle->request_head);
341 GNUNET_free (handle);
342}
343
344
345/**
346 * Cancel pending verify request
347 *
348 * @param lr the verify request to cancel
349 */
350void
351GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *vr)
352{
353 struct GNUNET_CREDENTIAL_Handle *handle = vr->credential_handle;
354
355 GNUNET_CONTAINER_DLL_remove (handle->request_head,
356 handle->request_tail,
357 vr);
358 GNUNET_MQ_discard (vr->env);
359 GNUNET_free (vr);
360}
361
362
363/**
364 * Performs attribute collection.
365 * Collects all credentials of subject to fulfill the
366 * attribute, if possible
367 *
368 * @param handle handle to the Credential service
369 * @param issuer_key the issuer public key
370 * @param issuer_attribute the issuer attribute
371 * @param subject_key the subject public key
372 * @param credential_count number of credentials provided
373 * @param credentials subject credentials
374 * @param proc function to call on result
375 * @param proc_cls closure for processor
376 * @return handle to the queued request
377 */
378struct GNUNET_CREDENTIAL_Request*
379GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
380 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
381 const char *issuer_attribute,
382 const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
383 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
384 void *proc_cls)
385{
386 /* IPC to shorten credential names, return shorten_handle */
387 struct CollectMessage *c_msg;
388 struct GNUNET_CREDENTIAL_Request *vr;
389 size_t nlen;
390
391 if (NULL == issuer_attribute)
392 {
393 GNUNET_break (0);
394 return NULL;
395 }
396
397 //DEBUG LOG
398 LOG (GNUNET_ERROR_TYPE_DEBUG,
399 "Trying to collect `%s' in CREDENTIAL\n",
400 issuer_attribute);
401 nlen = strlen (issuer_attribute) + 1;
402 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
403 {
404 GNUNET_break (0);
405 return NULL;
406 }
407 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
408 vr->credential_handle = handle;
409 vr->verify_proc = proc;
410 vr->proc_cls = proc_cls;
411 vr->r_id = handle->r_id_gen++;
412 vr->env = GNUNET_MQ_msg_extra (c_msg,
413 nlen,
414 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT);
415 c_msg->id = htonl (vr->r_id);
416 c_msg->subject_key = *subject_key;
417 c_msg->issuer_key = *issuer_key;
418 c_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
419 GNUNET_memcpy (&c_msg[1],
420 issuer_attribute,
421 strlen (issuer_attribute));
422 GNUNET_CONTAINER_DLL_insert (handle->request_head,
423 handle->request_tail,
424 vr);
425 if (NULL != handle->mq)
426 GNUNET_MQ_send_copy (handle->mq,
427 vr->env);
428 return vr;
429}
430/**
431 * Performs attribute verification.
432 * Checks if there is a delegation chain from
433 * attribute ``issuer_attribute'' issued by the issuer
434 * with public key ``issuer_key'' maps to the attribute
435 * ``subject_attribute'' claimed by the subject with key
436 * ``subject_key''
437 *
438 * @param handle handle to the Credential service
439 * @param issuer_key the issuer public key
440 * @param issuer_attribute the issuer attribute
441 * @param subject_key the subject public key
442 * @param credential_count number of credentials provided
443 * @param credentials subject credentials
444 * @param proc function to call on result
445 * @param proc_cls closure for processor
446 * @return handle to the queued request
447 */
448struct GNUNET_CREDENTIAL_Request*
449GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
450 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
451 const char *issuer_attribute,
452 const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
453 uint32_t credential_count,
454 const struct GNUNET_CREDENTIAL_Credential *credentials,
455 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
456 void *proc_cls)
457{
458 /* IPC to shorten credential names, return shorten_handle */
459 struct VerifyMessage *v_msg;
460 struct GNUNET_CREDENTIAL_Request *vr;
461 size_t nlen;
462 size_t clen;
463
464 if (NULL == issuer_attribute || NULL == credentials)
465 {
466 GNUNET_break (0);
467 return NULL;
468 }
469
470 clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
471 credentials);
472
473 //DEBUG LOG
474 LOG (GNUNET_ERROR_TYPE_DEBUG,
475 "Trying to verify `%s' in CREDENTIAL\n",
476 issuer_attribute);
477 nlen = strlen (issuer_attribute) + 1 + clen;
478 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
479 {
480 GNUNET_break (0);
481 return NULL;
482 }
483 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
484 vr->credential_handle = handle;
485 vr->verify_proc = proc;
486 vr->proc_cls = proc_cls;
487 vr->r_id = handle->r_id_gen++;
488 vr->env = GNUNET_MQ_msg_extra (v_msg,
489 nlen,
490 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
491 v_msg->id = htonl (vr->r_id);
492 v_msg->subject_key = *subject_key;
493 v_msg->c_count = htonl(credential_count);
494 v_msg->issuer_key = *issuer_key;
495 v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
496 GNUNET_memcpy (&v_msg[1],
497 issuer_attribute,
498 strlen (issuer_attribute));
499 GNUNET_CREDENTIAL_credentials_serialize (credential_count,
500 credentials,
501 clen,
502 ((char*)&v_msg[1])
503 + strlen (issuer_attribute) + 1);
504 GNUNET_CONTAINER_DLL_insert (handle->request_head,
505 handle->request_tail,
506 vr);
507 if (NULL != handle->mq)
508 GNUNET_MQ_send_copy (handle->mq,
509 vr->env);
510 return vr;
511}
512
513/* end of credential_api.c */
diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c
new file mode 100644
index 000000000..7849e81e6
--- /dev/null
+++ b/src/credential/credential_misc.c
@@ -0,0 +1,169 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_mic.c
24 * @brief Misc API for credentials
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34#include <inttypes.h>
35
36char*
37GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred)
38{
39 char *cred_str;
40 char *subject_pkey;
41 char *issuer_pkey;
42 char *signature;
43
44
45 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
46 issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
47 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
48 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
49 &signature);
50 GNUNET_asprintf (&cred_str,
51 "%s.%s -> %s | %s | %"SCNu64,
52 issuer_pkey,
53 cred->issuer_attribute,
54 subject_pkey,
55 signature,
56 cred->expiration.abs_value_us);
57 GNUNET_free (subject_pkey);
58 GNUNET_free (issuer_pkey);
59 GNUNET_free (signature);
60 return cred_str;
61}
62
63struct GNUNET_CREDENTIAL_Credential*
64GNUNET_CREDENTIAL_credential_from_string (const char* s)
65{
66 struct GNUNET_CREDENTIAL_Credential *cred;
67 size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
68 if (enclen % 5 > 0)
69 enclen += 5 - enclen % 5;
70 enclen /= 5; /* 260/5 = 52 */
71 char subject_pkey[enclen + 1];
72 char issuer_pkey[enclen + 1];
73 char name[253 + 1];
74 char signature[256]; //TODO max payload size
75
76 struct GNUNET_CRYPTO_EcdsaSignature *sig;
77 struct GNUNET_TIME_Absolute etime_abs;
78
79 if (5 != SSCANF (s,
80 "%52s.%253s -> %52s | %s | %"SCNu64,
81 issuer_pkey,
82 name,
83 subject_pkey,
84 signature,
85 &etime_abs.abs_value_us))
86 {
87 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
88 _("Unable to parse CRED record string `%s'\n"),
89 s);
90 return NULL;
91 }
92 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1);
93 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
94 strlen (subject_pkey),
95 &cred->subject_key);
96 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
97 strlen (issuer_pkey),
98 &cred->issuer_key);
99 GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature,
100 strlen (signature),
101 (char**)&sig));
102 cred->signature = *sig;
103 cred->expiration = etime_abs;
104 GNUNET_free (sig);
105 GNUNET_memcpy (&cred[1],
106 name,
107 strlen (name)+1);
108 cred->issuer_attribute_len = strlen ((char*)&cred[1]);
109 cred->issuer_attribute = (char*)&cred[1];
110 return cred;
111}
112
113/**
114 * Issue an attribute to a subject
115 *
116 * @param handle handle to the Credential service
117 * @param issuer the ego that should be used to issue the attribute
118 * @param subject the subject of the attribute
119 * @param attribute the name of the attribute
120 * @return handle to the queued request
121 */
122struct GNUNET_CREDENTIAL_Credential *
123GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
124 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
125 const char *attribute,
126 struct GNUNET_TIME_Absolute *expiration)
127{
128 struct CredentialEntry *crd;
129 struct GNUNET_CREDENTIAL_Credential *cred;
130 size_t size;
131
132 size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
133 crd = GNUNET_malloc (size);
134 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1);
135 crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
136
137 crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
138 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
139 &crd->issuer_key);
140 crd->subject_key = *subject;
141 crd->expiration = GNUNET_htonll (expiration->abs_value_us);
142 crd->issuer_attribute_len = htonl (strlen (attribute)+1);
143 GNUNET_memcpy ((char*)&crd[1],
144 attribute,
145 strlen (attribute)+1);
146 if (GNUNET_OK !=
147 GNUNET_CRYPTO_ecdsa_sign (issuer,
148 &crd->purpose,
149 &crd->signature))
150 {
151 GNUNET_break (0);
152 GNUNET_free (crd);
153 return NULL;
154 }
155 cred->signature = crd->signature;
156 cred->expiration = *expiration;
157 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
158 &cred->issuer_key);
159
160 cred->subject_key = *subject;
161 GNUNET_memcpy (&cred[1],
162 attribute,
163 strlen (attribute)+1);
164 cred->issuer_attribute = (char*)&cred[1];
165 GNUNET_free (crd);
166 return cred;
167}
168
169
diff --git a/src/credential/credential_misc.h b/src/credential/credential_misc.h
new file mode 100644
index 000000000..c3aa8c214
--- /dev/null
+++ b/src/credential/credential_misc.h
@@ -0,0 +1,35 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @file credential/credential_misc.h
22 * @brief Credential helper functions
23 */
24#ifndef CREDENTIAL_MISC_H
25#define CREDENTIAL_MISC_H
26
27
28
29char*
30GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred);
31
32struct GNUNET_CREDENTIAL_Credential*
33GNUNET_CREDENTIAL_credential_from_string (const char* str);
34
35#endif
diff --git a/src/credential/credential_serialization.c b/src/credential/credential_serialization.c
new file mode 100644
index 000000000..1fc72c203
--- /dev/null
+++ b/src/credential/credential_serialization.c
@@ -0,0 +1,463 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_serialization.c
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34
35/**
36 * Calculate how many bytes we will need to serialize
37 * the given delegation chain and credential
38 *
39 * @param d_count number of delegation chain entries
40 * @param dd array of #GNUNET_CREDENTIAL_Delegation
41 * @param cd a #GNUNET_CREDENTIAL_Credential
42 * @return the required size to serialize
43 */
44size_t
45GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
46 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
47{
48 unsigned int i;
49 size_t ret;
50
51 ret = sizeof (struct DelegationRecordData) * (ds_count);
52
53 for (i=0; i<ds_count;i++)
54 {
55 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
56 ret += dsr[i].subject_attribute_len;
57 }
58 return ret;
59}
60
61/**
62 * Serizalize the given delegation chain entries and credential
63 *
64 * @param d_count number of delegation chain entries
65 * @param dd array of #GNUNET_CREDENTIAL_Delegation
66 * @param cd a #GNUNET_CREDENTIAL_Credential
67 * @param dest_size size of the destination
68 * @param dest where to store the result
69 * @return the size of the data, -1 on failure
70 */
71ssize_t
72GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
73 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
74 size_t dest_size,
75 char *dest)
76{
77 struct DelegationRecordData rec;
78 unsigned int i;
79 size_t off;
80
81 off = 0;
82 for (i=0;i<d_count;i++)
83 {
84 rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
85 rec.subject_key = dsr[i].subject_key;
86 if (off + sizeof (rec) > dest_size)
87 return -1;
88 GNUNET_memcpy (&dest[off],
89 &rec,
90 sizeof (rec));
91 off += sizeof (rec);
92 if (0 == dsr[i].subject_attribute_len)
93 continue;
94 if (off + dsr[i].subject_attribute_len > dest_size)
95 return -1;
96 GNUNET_memcpy (&dest[off],
97 dsr[i].subject_attribute,
98 dsr[i].subject_attribute_len);
99 off += dsr[i].subject_attribute_len;
100 }
101 return off;
102}
103
104
105/**
106 * Deserialize the given destination
107 *
108 * @param len size of the serialized delegation chain and cred
109 * @param src the serialized data
110 * @param d_count the number of delegation chain entries
111 * @param dd where to put the delegation chain entries
112 * @param cd where to put the credential data
113 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
114 */
115int
116GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
117 const char *src,
118 unsigned int d_count,
119 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
120{
121 struct DelegationRecordData rec;
122 unsigned int i;
123 size_t off;
124
125 off = 0;
126 for (i=0;i<d_count;i++)
127 {
128 if (off + sizeof (rec) > len)
129 return GNUNET_SYSERR;
130 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
131 dsr[i].subject_key = rec.subject_key;
132 off += sizeof (rec);
133 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
134 if (off + dsr[i].subject_attribute_len > len)
135 return GNUNET_SYSERR;
136 dsr[i].subject_attribute = (char*)&src[off];
137 off += dsr[i].subject_attribute_len;
138 }
139 return GNUNET_OK;
140}
141
142
143/**
144 * Calculate how many bytes we will need to serialize
145 * the credentials
146 *
147 * @param c_count number of credential entries
148 * @param cd a #GNUNET_CREDENTIAL_Credential
149 * @return the required size to serialize
150 */
151size_t
152GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
153 const struct GNUNET_CREDENTIAL_Credential *cd)
154{
155 unsigned int i;
156 size_t ret;
157
158 ret = sizeof (struct CredentialEntry) * (c_count);
159
160 for (i=0; i<c_count;i++)
161 {
162 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
163 ret += cd[i].issuer_attribute_len;
164 }
165 return ret;
166}
167/**
168 * Serizalize the given credentials
169 *
170 * @param c_count number of credential entries
171 * @param cd a #GNUNET_CREDENTIAL_Credential
172 * @param dest_size size of the destination
173 * @param dest where to store the result
174 * @return the size of the data, -1 on failure
175 */
176ssize_t
177GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
178 const struct GNUNET_CREDENTIAL_Credential *cd,
179 size_t dest_size,
180 char *dest)
181{
182 struct CredentialEntry c_rec;
183 unsigned int i;
184 size_t off;
185
186 off = 0;
187 for (i=0;i<c_count;i++)
188 {
189 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
190 c_rec.issuer_key = cd[i].issuer_key;
191 c_rec.subject_key = cd[i].subject_key;
192 c_rec.signature = cd[i].signature;
193 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
194 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
195 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
196 if (off + sizeof (c_rec) > dest_size)
197 return -1;
198 GNUNET_memcpy (&dest[off],
199 &c_rec,
200 sizeof (c_rec));
201 off += sizeof (c_rec);
202 if (off + cd[i].issuer_attribute_len > dest_size)
203 return -1;
204 GNUNET_memcpy (&dest[off],
205 cd[i].issuer_attribute,
206 cd[i].issuer_attribute_len);
207 off += cd[i].issuer_attribute_len;
208 }
209
210 return off;
211}
212
213
214
215/**
216 * Deserialize the given destination
217 *
218 * @param len size of the serialized creds
219 * @param src the serialized data
220 * @param c_count the number of credential entries
221 * @param cd where to put the credential data
222 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
223 */
224int
225GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
226 const char *src,
227 unsigned int c_count,
228 struct GNUNET_CREDENTIAL_Credential *cd)
229{
230 struct CredentialEntry c_rec;
231 unsigned int i;
232 size_t off;
233
234 off = 0;
235 for (i=0;i<c_count;i++)
236 {
237 if (off + sizeof (c_rec) > len)
238 return GNUNET_SYSERR;
239 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
240 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
241 cd[i].issuer_key = c_rec.issuer_key;
242 cd[i].subject_key = c_rec.subject_key;
243 cd[i].signature = c_rec.signature;
244 cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
245 off += sizeof (c_rec);
246 if (off + cd[i].issuer_attribute_len > len)
247 return GNUNET_SYSERR;
248 cd[i].issuer_attribute = &src[off];
249 off += cd[i].issuer_attribute_len;
250 }
251 return GNUNET_OK;
252}
253
254
255
256/**
257 * Calculate how many bytes we will need to serialize
258 * the given delegation chain and credential
259 *
260 * @param d_count number of delegation chain entries
261 * @param dd array of #GNUNET_CREDENTIAL_Delegation
262 * @param c_count number of credential entries
263 * @param cd a #GNUNET_CREDENTIAL_Credential
264 * @return the required size to serialize
265 */
266size_t
267GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
268 const struct GNUNET_CREDENTIAL_Delegation *dd,
269 unsigned int c_count,
270 const struct GNUNET_CREDENTIAL_Credential *cd)
271{
272 unsigned int i;
273 size_t ret;
274
275 ret = sizeof (struct ChainEntry) * (d_count);
276
277 for (i=0; i<d_count;i++)
278 {
279 GNUNET_assert ((ret +
280 dd[i].issuer_attribute_len +
281 dd[i].subject_attribute_len) >= ret);
282 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
283 }
284 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
285 return ret;
286}
287
288/**
289 * Serizalize the given delegation chain entries and credential
290 *
291 * @param d_count number of delegation chain entries
292 * @param dd array of #GNUNET_CREDENTIAL_Delegation
293 * @param c_count number of credential entries
294 * @param cd a #GNUNET_CREDENTIAL_Credential
295 * @param dest_size size of the destination
296 * @param dest where to store the result
297 * @return the size of the data, -1 on failure
298 */
299ssize_t
300GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
301 const struct GNUNET_CREDENTIAL_Delegation *dd,
302 unsigned int c_count,
303 const struct GNUNET_CREDENTIAL_Credential *cd,
304 size_t dest_size,
305 char *dest)
306{
307 struct ChainEntry rec;
308 unsigned int i;
309 size_t off;
310
311 off = 0;
312 for (i=0;i<d_count;i++)
313 {
314 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
315 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
316 rec.issuer_key = dd[i].issuer_key;
317 rec.subject_key = dd[i].subject_key;
318 if (off + sizeof (rec) > dest_size)
319 return -1;
320 GNUNET_memcpy (&dest[off],
321 &rec,
322 sizeof (rec));
323 off += sizeof (rec);
324 if (off + dd[i].issuer_attribute_len > dest_size)
325 return -1;
326 GNUNET_memcpy (&dest[off],
327 dd[i].issuer_attribute,
328 dd[i].issuer_attribute_len);
329 off += dd[i].issuer_attribute_len;
330 if (0 == dd[i].subject_attribute_len)
331 continue;
332 if (off + dd[i].subject_attribute_len > dest_size)
333 return -1;
334 GNUNET_memcpy (&dest[off],
335 dd[i].subject_attribute,
336 dd[i].subject_attribute_len);
337 off += dd[i].subject_attribute_len;
338 }
339 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
340 cd,
341 dest_size-off,
342 &dest[off]);
343}
344
345
346/**
347 * Deserialize the given destination
348 *
349 * @param len size of the serialized delegation chain and cred
350 * @param src the serialized data
351 * @param d_count the number of delegation chain entries
352 * @param dd where to put the delegation chain entries
353 * @param c_count the number of credential entries
354 * @param cd where to put the credential data
355 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
356 */
357int
358GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
359 const char *src,
360 unsigned int d_count,
361 struct GNUNET_CREDENTIAL_Delegation *dd,
362 unsigned int c_count,
363 struct GNUNET_CREDENTIAL_Credential *cd)
364{
365 struct ChainEntry rec;
366 unsigned int i;
367 size_t off;
368
369 off = 0;
370 for (i=0;i<d_count;i++)
371 {
372 if (off + sizeof (rec) > len)
373 return GNUNET_SYSERR;
374 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
375 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
376 dd[i].issuer_key = rec.issuer_key;
377 dd[i].subject_key = rec.subject_key;
378 off += sizeof (rec);
379 if (off + dd[i].issuer_attribute_len > len)
380 return GNUNET_SYSERR;
381 dd[i].issuer_attribute = &src[off];
382 off += dd[i].issuer_attribute_len;
383 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
384 if (off + dd[i].subject_attribute_len > len)
385 return GNUNET_SYSERR;
386 dd[i].subject_attribute = &src[off];
387 off += dd[i].subject_attribute_len;
388 }
389 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
390 &src[off],
391 c_count,
392 cd);
393}
394int
395GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
396 char **data)
397{
398 size_t size;
399 struct CredentialEntry *cdata;
400
401 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
402 *data = GNUNET_malloc (size);
403 cdata = (struct CredentialEntry*)*data;
404 cdata->subject_key = cred->subject_key;
405 cdata->issuer_key = cred->issuer_key;
406 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
407 cdata->signature = cred->signature;
408 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
409 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
410 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
411 GNUNET_memcpy (&cdata[1],
412 cred->issuer_attribute,
413 strlen (cred->issuer_attribute));
414
415 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
416 &cdata->purpose,
417 &cdata->signature,
418 &cdata->issuer_key))
419 {
420 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
421 "Invalid credential\n");
422 //return NULL;
423 }
424 return size;
425}
426
427struct GNUNET_CREDENTIAL_Credential*
428GNUNET_CREDENTIAL_credential_deserialize (const char* data,
429 size_t data_size)
430{
431 struct GNUNET_CREDENTIAL_Credential *cred;
432 struct CredentialEntry *cdata;
433 char *issuer_attribute;
434
435 if (data_size < sizeof (struct CredentialEntry))
436 return NULL;
437 cdata = (struct CredentialEntry*)data;
438 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
439 &cdata->purpose,
440 &cdata->signature,
441 &cdata->issuer_key))
442 {
443 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
444 "Invalid credential\n");
445 //return NULL;
446 }
447 issuer_attribute = (char*)&cdata[1];
448
449 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
450
451 cred->issuer_key = cdata->issuer_key;
452 cred->subject_key = cdata->subject_key;
453 GNUNET_memcpy (&cred[1],
454 issuer_attribute,
455 ntohl (cdata->issuer_attribute_len));
456 cred->signature = cdata->signature;
457 cred->issuer_attribute = (char*)&cred[1];
458 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
459 return cred;
460}
461
462
463/* end of credential_serialization.c */
diff --git a/src/credential/credential_serialization.h b/src/credential/credential_serialization.h
new file mode 100644
index 000000000..b870d47dc
--- /dev/null
+++ b/src/credential/credential_serialization.h
@@ -0,0 +1,159 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_serialization.h
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#ifndef CREDENTIAL_SERIALIZATION_H
29#define CREDENTIAL_SERIALIZATION_H
30
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_constants.h"
34#include "gnunet_credential_service.h"
35
36/**
37 * Calculate how many bytes we will need to serialize
38 * the given delegation record
39 *
40 * @param ds_count number of delegation chain entries
41 * @param dsr array of #GNUNET_CREDENTIAL_Delegation
42 * @return the required size to serialize
43 */
44size_t
45GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
46 const struct GNUNET_CREDENTIAL_DelegationSet *dsr);
47
48/**
49 * Serizalize the given delegation record entries
50 *
51 * @param d_count number of delegation chain entries
52 * @param dsr array of #GNUNET_CREDENTIAL_Delegation
53 * @param dest_size size of the destination
54 * @param dest where to store the result
55 * @return the size of the data, -1 on failure
56 */
57ssize_t
58GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
59 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
60 size_t dest_size,
61 char *dest);
62
63
64/**
65 * Deserialize the given destination
66 *
67 * @param len size of the serialized delegation recird
68 * @param src the serialized data
69 * @param d_count the number of delegation chain entries
70 * @param dsr where to put the delegation chain entries
71 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
72 */
73int
74GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
75 const char *src,
76 unsigned int d_count,
77 struct GNUNET_CREDENTIAL_DelegationSet *dsr);
78
79 /**
80 * Calculate how many bytes we will need to serialize
81 * the given delegation chain and credential
82 *
83 * @param d_count number of delegation chain entries
84 * @param dd array of #GNUNET_CREDENTIAL_Delegation
85 * @param c_count number of credential entries
86 * @param cd a #GNUNET_CREDENTIAL_Credential
87 * @return the required size to serialize
88 */
89 size_t
90 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
91 const struct GNUNET_CREDENTIAL_Delegation *dd,
92 unsigned int c_count,
93 const struct GNUNET_CREDENTIAL_Credential *cd);
94
95 /**
96 * Serizalize the given delegation chain entries and credential
97 *
98 * @param d_count number of delegation chain entries
99 * @param dd array of #GNUNET_CREDENTIAL_Delegation
100 * @param c_count number of credential entries
101 * @param cd a #GNUNET_CREDENTIAL_Credential
102 * @param dest_size size of the destination
103 * @param dest where to store the result
104 * @return the size of the data, -1 on failure
105 */
106 ssize_t
107 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
108 const struct GNUNET_CREDENTIAL_Delegation *dd,
109 unsigned int c_count,
110 const struct GNUNET_CREDENTIAL_Credential *cd,
111 size_t dest_size,
112 char *dest);
113
114
115 /**
116 * Deserialize the given destination
117 *
118 * @param len size of the serialized delegation chain and cred
119 * @param src the serialized data
120 * @param d_count the number of delegation chain entries
121 * @param dd where to put the delegation chain entries
122 * @param c_count number of credential entries
123 * @param cd where to put the credential data
124 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
125 */
126 int
127 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
128 const char *src,
129 unsigned int d_count,
130 struct GNUNET_CREDENTIAL_Delegation *dd,
131 unsigned int c_count,
132 struct GNUNET_CREDENTIAL_Credential *cd);
133 size_t
134 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
135 const struct GNUNET_CREDENTIAL_Credential *cd);
136
137ssize_t
138GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
139 const struct GNUNET_CREDENTIAL_Credential *cd,
140 size_t dest_size,
141 char *dest);
142
143
144int
145GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
146 const char *src,
147 unsigned int c_count,
148 struct GNUNET_CREDENTIAL_Credential *cd);
149
150
151int
152GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
153 char **data);
154
155struct GNUNET_CREDENTIAL_Credential*
156GNUNET_CREDENTIAL_credential_deserialize (const char* data,
157 size_t data_size);
158#endif
159/* end of credential_serialization.h */
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c
new file mode 100644
index 000000000..4a6dc5ccd
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,602 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file gnunet-credential.c
22 * @brief command line tool to access command line Credential service
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include <gnunet_util_lib.h>
27#include <gnunet_credential_service.h>
28#include <gnunet_gnsrecord_lib.h>
29#include "credential_misc.h"
30#include "credential_serialization.h"
31
32/**
33 * Configuration we are using.
34 */
35static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37/**
38 * EgoLookup
39 */
40static struct GNUNET_IDENTITY_EgoLookup *el;
41
42/**
43 * Handle to Credential service.
44 */
45static struct GNUNET_CREDENTIAL_Handle *credential;
46
47/**
48 * Desired timeout for the lookup (default is no timeout).
49 */
50static struct GNUNET_TIME_Relative timeout;
51
52/**
53 * Handle to verify request
54 */
55static struct GNUNET_CREDENTIAL_Request *verify_request;
56
57/**
58 * Handle to collect request
59 */
60static struct GNUNET_CREDENTIAL_Request *collect_request;
61
62/**
63 * Task scheduled to handle timeout.
64 */
65static struct GNUNET_SCHEDULER_Task *tt;
66
67/**
68 * Subject pubkey string
69 */
70static char *subject_key;
71
72/**
73 * Subject credential string
74 */
75static char *subject_credential;
76
77/**
78 * Credential TTL
79 */
80static char *expiration;
81
82/**
83 * Subject key
84 */
85struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
86
87/**
88 * Issuer key
89 */
90struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
91
92
93/**
94 * Issuer pubkey string
95 */
96static char *issuer_key;
97
98/**
99 * ego
100 */
101static char *ego_name;
102
103/**
104 * Issuer attribute
105 */
106static char *issuer_attr;
107
108/**
109 * Verify mode
110 */
111static 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
161/**
162 * Function called with the result of a Credential lookup.
163 *
164 * @param cls the 'const char *' name that was resolved
165 * @param cd_count number of records returned
166 * @param cd array of @a cd_count records with the results
167 */
168static void
169handle_collect_result (void *cls,
170 unsigned int d_count,
171 struct GNUNET_CREDENTIAL_Delegation *dc,
172 unsigned int c_count,
173 struct GNUNET_CREDENTIAL_Credential *cred)
174{
175 int i;
176 char* line;
177
178 verify_request = NULL;
179 if (NULL != cred)
180 {
181 for (i=0;i<c_count;i++)
182 {
183 line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
184 printf ("%s\n",
185 line);
186 GNUNET_free (line);
187 }
188 }
189
190
191 GNUNET_SCHEDULER_shutdown ();
192}
193
194
195/**
196 * Function called with the result of a Credential lookup.
197 *
198 * @param cls the 'const char *' name that was resolved
199 * @param cd_count number of records returned
200 * @param cd array of @a cd_count records with the results
201 */
202static void
203handle_verify_result (void *cls,
204 unsigned int d_count,
205 struct GNUNET_CREDENTIAL_Delegation *dc,
206 unsigned int c_count,
207 struct GNUNET_CREDENTIAL_Credential *cred)
208{
209 int i;
210 char* iss_key;
211 char* sub_key;
212
213 verify_request = NULL;
214 if (NULL == cred)
215 printf ("Failed.\n");
216 else
217 {
218 printf("Delegation Chain:\n");
219 for (i=0;i<d_count;i++)
220 {
221 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
222 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
223 if (0 != dc[i].subject_attribute_len)
224 {
225 printf ("(%d) %s.%s <- %s.%s\n", i,
226 iss_key, dc[i].issuer_attribute,
227 sub_key, dc[i].subject_attribute);
228 } else {
229 printf ("(%d) %s.%s <- %s\n", i,
230 iss_key, dc[i].issuer_attribute,
231 sub_key);
232 }
233 GNUNET_free (iss_key);
234 GNUNET_free (sub_key);
235 }
236 printf("\nCredentials:\n");
237 for (i=0;i<c_count;i++)
238 {
239 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
240 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
241 printf ("%s.%s <- %s\n",
242 iss_key, cred[i].issuer_attribute,
243 sub_key);
244 GNUNET_free (iss_key);
245 GNUNET_free (sub_key);
246
247 }
248 printf ("Successful.\n");
249 }
250
251
252 GNUNET_SCHEDULER_shutdown ();
253}
254
255/**
256 * Callback invoked from identity service with ego information.
257 * An @a ego of NULL means the ego was not found.
258 *
259 * @param cls closure with the configuration
260 * @param ego an ego known to identity service, or NULL
261 */
262static void
263identity_cb (void *cls,
264 const struct GNUNET_IDENTITY_Ego *ego)
265{
266 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
267 struct GNUNET_CREDENTIAL_Credential *crd;
268 struct GNUNET_TIME_Absolute etime_abs;
269 struct GNUNET_TIME_Relative etime_rel;
270 char *res;
271
272 el = NULL;
273 if (NULL == ego)
274 {
275 if (NULL != ego_name)
276 {
277 fprintf (stderr,
278 _("Ego `%s' not known to identity service\n"),
279 ego_name);
280 }
281 GNUNET_SCHEDULER_shutdown ();
282 return;
283 }
284
285 if (GNUNET_YES == collect)
286 {
287
288 if (GNUNET_OK !=
289 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
290 strlen (issuer_key),
291 &issuer_pkey))
292 {
293 fprintf (stderr,
294 _("Issuer public key `%s' is not well-formed\n"),
295 issuer_key);
296 GNUNET_SCHEDULER_shutdown ();
297 }
298 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
299
300 collect_request = GNUNET_CREDENTIAL_collect(credential,
301 &issuer_pkey,
302 issuer_attr, //TODO argument
303 privkey,
304 &handle_collect_result,
305 NULL);
306 return;
307 }
308
309 //Else issue
310
311 if (NULL == expiration)
312 {
313 fprintf (stderr,
314 "Please specify a TTL\n");
315 GNUNET_SCHEDULER_shutdown ();
316 return;
317 } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
318 &etime_rel))
319 {
320 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
321 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
322 &etime_abs))
323 {
324 fprintf (stderr,
325 "%s is not a valid ttl!\n",
326 expiration);
327 GNUNET_SCHEDULER_shutdown ();
328 return;
329 }
330
331
332 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
333 GNUNET_free_non_null (ego_name);
334 ego_name = NULL;
335 crd = GNUNET_CREDENTIAL_credential_issue (privkey,
336 &subject_pkey,
337 issuer_attr,
338 &etime_abs);
339
340 res = GNUNET_CREDENTIAL_credential_to_string (crd);
341 GNUNET_free (crd);
342 printf ("%s\n", res);
343 GNUNET_SCHEDULER_shutdown ();
344}
345
346
347
348
349/**
350 * Main function that will be run.
351 *
352 * @param cls closure
353 * @param args remaining command-line arguments
354 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
355 * @param c configuration
356 */
357static void
358run (void *cls,
359 char *const *args,
360 const char *cfgfile,
361 const struct GNUNET_CONFIGURATION_Handle *c)
362{
363
364 cfg = c;
365
366
367 tt = GNUNET_SCHEDULER_add_delayed (timeout,
368 &do_timeout, NULL);
369 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
370
371 if (GNUNET_YES == collect) {
372 if (NULL == issuer_key)
373 {
374 fprintf (stderr,
375 _("Issuer public key not well-formed\n"));
376 GNUNET_SCHEDULER_shutdown ();
377 return;
378
379 }
380
381 credential = GNUNET_CREDENTIAL_connect (cfg);
382
383 if (NULL == credential)
384 {
385 fprintf (stderr,
386 _("Failed to connect to CREDENTIAL\n"));
387 GNUNET_SCHEDULER_shutdown ();
388 }
389 if (NULL == issuer_attr)
390 {
391 fprintf (stderr,
392 _("You must provide issuer the attribute\n"));
393 GNUNET_SCHEDULER_shutdown ();
394 }
395
396 if (NULL == ego_name)
397 {
398 fprintf (stderr,
399 _("ego required\n"));
400 GNUNET_SCHEDULER_shutdown ();
401 return;
402
403 }
404 el = GNUNET_IDENTITY_ego_lookup (cfg,
405 ego_name,
406 &identity_cb,
407 (void *) cfg);
408 return;
409
410 }
411
412 if (NULL == subject_key)
413 {
414 fprintf (stderr,
415 _("Subject public key needed\n"));
416 GNUNET_SCHEDULER_shutdown ();
417 return;
418
419 }
420 if (GNUNET_OK !=
421 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
422 strlen (subject_key),
423 &subject_pkey))
424 {
425 fprintf (stderr,
426 _("Subject public key `%s' is not well-formed\n"),
427 subject_key);
428 GNUNET_SCHEDULER_shutdown ();
429 return;
430 }
431 if (GNUNET_YES == verify) {
432 if (NULL == issuer_key)
433 {
434 fprintf (stderr,
435 _("Issuer public key not well-formed\n"));
436 GNUNET_SCHEDULER_shutdown ();
437 return;
438
439 }
440 if (GNUNET_OK !=
441 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
442 strlen (issuer_key),
443 &issuer_pkey))
444 {
445 fprintf (stderr,
446 _("Issuer public key `%s' is not well-formed\n"),
447 issuer_key);
448 GNUNET_SCHEDULER_shutdown ();
449 }
450 credential = GNUNET_CREDENTIAL_connect (cfg);
451
452 if (NULL == credential)
453 {
454 fprintf (stderr,
455 _("Failed to connect to CREDENTIAL\n"));
456 GNUNET_SCHEDULER_shutdown ();
457 }
458 if (NULL == issuer_attr || NULL == subject_credential)
459 {
460 fprintf (stderr,
461 _("You must provide issuer and subject attributes\n"));
462 GNUNET_SCHEDULER_shutdown ();
463 }
464
465 //Subject credentials are comma separated
466 char *tmp = GNUNET_strdup (subject_credential);
467 char *tok = strtok (tmp, ",");
468 if (NULL == tok)
469 {
470 fprintf (stderr,
471 "Invalid subject credentials\n");
472 GNUNET_free (tmp);
473 GNUNET_SCHEDULER_shutdown ();
474 }
475 int count = 1;
476 int i;
477 while (NULL != (tok = strtok(NULL, ",")))
478 count++;
479 struct GNUNET_CREDENTIAL_Credential credentials[count];
480 struct GNUNET_CREDENTIAL_Credential *cred;
481 GNUNET_free (tmp);
482 tmp = GNUNET_strdup (subject_credential);
483 tok = strtok (tmp, ",");
484 for (i=0;i<count;i++)
485 {
486 cred = GNUNET_CREDENTIAL_credential_from_string (tok);
487 GNUNET_memcpy (&credentials[i],
488 cred,
489 sizeof (struct GNUNET_CREDENTIAL_Credential));
490 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
491 tok = strtok(NULL, ",");
492 GNUNET_free (cred);
493 }
494
495 verify_request = GNUNET_CREDENTIAL_verify(credential,
496 &issuer_pkey,
497 issuer_attr, //TODO argument
498 &subject_pkey,
499 count,
500 credentials,
501 &handle_verify_result,
502 NULL);
503 for (i=0;i<count;i++)
504 {
505 GNUNET_free ((char*)credentials[i].issuer_attribute);
506 }
507 } else if (GNUNET_YES == create_cred) {
508 if (NULL == ego_name)
509 {
510 fprintf (stderr,
511 _("Issuer ego required\n"));
512 GNUNET_SCHEDULER_shutdown ();
513 return;
514
515 }
516 el = GNUNET_IDENTITY_ego_lookup (cfg,
517 ego_name,
518 &identity_cb,
519 (void *) cfg);
520 return;
521 } else {
522 fprintf (stderr,
523 _("Please specify name to lookup, subject key and issuer key!\n"));
524 GNUNET_SCHEDULER_shutdown ();
525 }
526 return;
527}
528
529
530/**
531 * The main function for gnunet-gns.
532 *
533 * @param argc number of arguments from the command line
534 * @param argv command line arguments
535 * @return 0 ok, 1 on error
536 */
537int
538main (int argc, char *const *argv)
539{
540 struct GNUNET_GETOPT_CommandLineOption options[] = {
541 GNUNET_GETOPT_option_flag ('I',
542 "issue",
543 gettext_noop ("create credential"),
544 &create_cred),
545 GNUNET_GETOPT_option_flag ('V',
546 "verify",
547 gettext_noop ("verify credential against attribute"),
548 &verify),
549 GNUNET_GETOPT_option_string ('s',
550 "subject",
551 "PKEY",
552 gettext_noop ("The public key of the subject to lookup the credential for"),
553 &subject_key),
554 GNUNET_GETOPT_option_string ('b',
555 "credential",
556 "CRED",
557 gettext_noop ("The name of the credential presented by the subject"),
558 &subject_credential),
559 GNUNET_GETOPT_option_string ('i',
560 "issuer",
561 "PKEY",
562 gettext_noop ("The public key of the authority to verify the credential against"),
563 &issuer_key),
564 GNUNET_GETOPT_option_string ('e',
565 "ego",
566 "EGO",
567 gettext_noop ("The ego to use"),
568 &ego_name),
569 GNUNET_GETOPT_option_string ('a',
570 "attribute",
571 "ATTR",
572 gettext_noop ("The issuer attribute to verify against or to issue"),
573 &issuer_attr),
574 GNUNET_GETOPT_option_string ('T',
575 "ttl",
576 "EXP",
577 gettext_noop ("The time to live for the credential"),
578 &expiration),
579 GNUNET_GETOPT_option_flag ('g',
580 "collect",
581 gettext_noop ("collect credentials"),
582 &collect),
583 GNUNET_GETOPT_OPTION_END
584 };
585 int ret;
586
587 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
588 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
589 return 2;
590
591 GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
592 ret =
593 (GNUNET_OK ==
594 GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
595 _("GNUnet credential resolver tool"),
596 options,
597 &run, NULL)) ? 0 : 1;
598 GNUNET_free ((void*) argv);
599 return ret;
600}
601
602/* 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..be75e485e
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1238 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file gns/gnunet-service-credential.c
22 * @brief GNU Credential Service (main service)
23 * @author Adnan Husain
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_credential_service.h"
28#include "gnunet_statistics_service.h"
29#include "credential.h"
30#include "credential_serialization.h"
31#include "gnunet_protocols.h"
32#include "gnunet_signatures.h"
33
34#include <gnunet_dnsparser_lib.h>
35#include <gnunet_identity_service.h>
36#include <gnunet_gnsrecord_lib.h>
37#include <gnunet_namestore_service.h>
38#include <gnunet_gns_service.h>
39
40
41#define GNUNET_CREDENTIAL_MAX_LENGTH 255
42
43struct VerifyRequestHandle;
44
45struct DelegationSetQueueEntry;
46
47
48struct DelegationChainEntry
49{
50 /**
51 * DLL
52 */
53 struct DelegationChainEntry *next;
54
55 /**
56 * DLL
57 */
58 struct DelegationChainEntry *prev;
59
60 /**
61 * The issuer
62 */
63 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
64
65 /**
66 * The subject
67 */
68 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
69
70 /**
71 * The issued attribute
72 */
73 char *issuer_attribute;
74
75 /**
76 * The delegated attribute
77 */
78 char *subject_attribute;
79};
80
81/**
82 * DLL for record
83 */
84struct CredentialRecordEntry
85{
86 /**
87 * DLL
88 */
89 struct CredentialRecordEntry *next;
90
91 /**
92 * DLL
93 */
94 struct CredentialRecordEntry *prev;
95
96 /**
97 * Number of references in delegation chains
98 */
99 uint32_t refcount;
100
101 /**
102 * Payload
103 */
104 struct GNUNET_CREDENTIAL_Credential *credential;
105};
106
107/**
108 * DLL used for delegations
109 * Used for OR delegations
110 */
111struct DelegationQueueEntry
112{
113 /**
114 * DLL
115 */
116 struct DelegationQueueEntry *next;
117
118 /**
119 * DLL
120 */
121 struct DelegationQueueEntry *prev;
122
123 /**
124 * Sets under this Queue
125 */
126 struct DelegationSetQueueEntry *set_entries_head;
127
128 /**
129 * Sets under this Queue
130 */
131 struct DelegationSetQueueEntry *set_entries_tail;
132
133 /**
134 * Parent set
135 */
136 struct DelegationSetQueueEntry *parent_set;
137
138 /**
139 * Required solutions
140 */
141 uint32_t required_solutions;
142};
143
144/**
145 * DLL for delegation sets
146 * Used for AND delegation set
147 */
148struct DelegationSetQueueEntry
149{
150 /**
151 * DLL
152 */
153 struct DelegationSetQueueEntry *next;
154
155 /**
156 * DLL
157 */
158 struct DelegationSetQueueEntry *prev;
159
160 /**
161 * GNS handle
162 */
163 struct GNUNET_GNS_LookupRequest *lookup_request;
164
165 /**
166 * Verify handle
167 */
168 struct VerifyRequestHandle *handle;
169
170 /**
171 * Parent attribute delegation
172 */
173 struct DelegationQueueEntry *parent;
174
175 /**
176 * Issuer key
177 */
178 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
179
180 /**
181 * Queue entries of this set
182 */
183 struct DelegationQueueEntry *queue_entries_head;
184
185 /**
186 * Queue entries of this set
187 */
188 struct DelegationQueueEntry *queue_entries_tail;
189
190 /**
191 * Parent QueueEntry
192 */
193 struct DelegationQueueEntry *parent_queue_entry;
194
195 /**
196 * Issuer attribute delegated to
197 */
198 char *issuer_attribute;
199
200 /**
201 * The current attribute to look up
202 */
203 char *lookup_attribute;
204
205 /**
206 * Trailing attribute context
207 */
208 char *attr_trailer;
209
210 /**
211 * Still to resolve delegation as string
212 */
213 char *unresolved_attribute_delegation;
214
215 /**
216 * The delegation chain entry
217 */
218 struct DelegationChainEntry *delegation_chain_entry;
219
220};
221
222
223/**
224 * Handle to a lookup operation from api
225 */
226struct VerifyRequestHandle
227{
228
229 /**
230 * We keep these in a DLL.
231 */
232 struct VerifyRequestHandle *next;
233
234 /**
235 * We keep these in a DLL.
236 */
237 struct VerifyRequestHandle *prev;
238
239 /**
240 * Handle to the requesting client
241 */
242 struct GNUNET_SERVICE_Client *client;
243
244 /**
245 * GNS handle
246 */
247 struct GNUNET_GNS_LookupRequest *lookup_request;
248
249 /**
250 * Size of delegation tree
251 */
252 uint32_t delegation_chain_size;
253
254 /**
255 * Children of this attribute
256 */
257 struct DelegationChainEntry *delegation_chain_head;
258
259 /**
260 * Children of this attribute
261 */
262 struct DelegationChainEntry *delegation_chain_tail;
263
264 /**
265 * Issuer public key
266 */
267 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
268
269 /**
270 * Issuer attribute
271 */
272 char *issuer_attribute;
273
274 /**
275 * Subject public key
276 */
277 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
278
279 /**
280 * Credential DLL
281 */
282 struct CredentialRecordEntry *cred_chain_head;
283
284 /**
285 * Credential DLL
286 */
287 struct CredentialRecordEntry *cred_chain_tail;
288
289 /**
290 * Credential DLL size
291 */
292 uint32_t cred_chain_size;
293
294 /**
295 * Root Delegation Set
296 */
297 struct DelegationSetQueueEntry *root_set;
298
299 /**
300 * Current Delegation Pointer
301 */
302 struct DelegationQueueEntry *current_delegation;
303
304 /**
305 * request id
306 */
307 uint32_t request_id;
308
309 /**
310 * Pending lookups
311 */
312 uint64_t pending_lookups;
313
314 /**
315 * Credential iterator
316 */
317 struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
318
319 /**
320 * Collect task
321 */
322 struct GNUNET_SCHEDULER_Task *collect_next_task;
323
324};
325
326
327/**
328 * Head of the DLL.
329 */
330static struct VerifyRequestHandle *vrh_head;
331
332/**
333 * Tail of the DLL.
334 */
335static struct VerifyRequestHandle *vrh_tail;
336
337/**
338 * Handle to the statistics service
339 */
340static struct GNUNET_STATISTICS_Handle *statistics;
341
342/**
343 * Handle to GNS service.
344 */
345static struct GNUNET_GNS_Handle *gns;
346
347
348/**
349 * Handle to namestore service
350 */
351static struct GNUNET_NAMESTORE_Handle *namestore;
352
353static void
354cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
355{
356 struct DelegationQueueEntry *dq_entry;
357 struct DelegationSetQueueEntry *child;
358
359 if (NULL == ds_entry)
360 return;
361
362 for (dq_entry = ds_entry->queue_entries_head;
363 NULL != dq_entry;
364 dq_entry = ds_entry->queue_entries_head)
365 {
366 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
367 ds_entry->queue_entries_tail,
368 dq_entry);
369 for (child = dq_entry->set_entries_head;
370 NULL != child;
371 child = dq_entry->set_entries_head)
372 {
373 GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
374 dq_entry->set_entries_tail,
375 child);
376 cleanup_delegation_set (child);
377 }
378 GNUNET_free (dq_entry);
379 }
380 if (NULL != ds_entry->issuer_key)
381 GNUNET_free (ds_entry->issuer_key);
382 if (NULL != ds_entry->lookup_attribute)
383 GNUNET_free (ds_entry->lookup_attribute);
384 if (NULL != ds_entry->issuer_attribute)
385 GNUNET_free (ds_entry->issuer_attribute);
386 if (NULL != ds_entry->unresolved_attribute_delegation)
387 GNUNET_free (ds_entry->unresolved_attribute_delegation);
388 if (NULL != ds_entry->attr_trailer)
389 GNUNET_free (ds_entry->attr_trailer);
390 if (NULL != ds_entry->lookup_request)
391 {
392 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
393 ds_entry->lookup_request = NULL;
394 }
395 if (NULL != ds_entry->delegation_chain_entry)
396 {
397 if (NULL != ds_entry->delegation_chain_entry->subject_attribute)
398 GNUNET_free (ds_entry->delegation_chain_entry->subject_attribute);
399 if (NULL != ds_entry->delegation_chain_entry->issuer_attribute)
400 GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
401 GNUNET_free (ds_entry->delegation_chain_entry);
402 }
403 GNUNET_free (ds_entry);
404}
405
406static void
407cleanup_handle (struct VerifyRequestHandle *vrh)
408{
409 struct CredentialRecordEntry *cr_entry;
410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
411 "Cleaning up...\n");
412 if (NULL != vrh->lookup_request)
413 {
414 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
415 vrh->lookup_request = NULL;
416 }
417 cleanup_delegation_set (vrh->root_set);
418 if (NULL != vrh->issuer_attribute)
419 GNUNET_free (vrh->issuer_attribute);
420 for (cr_entry = vrh->cred_chain_head;
421 NULL != vrh->cred_chain_head;
422 cr_entry = vrh->cred_chain_head)
423 {
424 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
425 vrh->cred_chain_tail,
426 cr_entry);
427 if (NULL != cr_entry->credential);
428 GNUNET_free (cr_entry->credential);
429 GNUNET_free (cr_entry);
430 }
431 GNUNET_free (vrh);
432}
433
434/**
435 * Task run during shutdown.
436 *
437 * @param cls unused
438 * @param tc unused
439 */
440static void
441shutdown_task (void *cls)
442{
443 struct VerifyRequestHandle *vrh;
444
445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
446 "Shutting down!\n");
447
448 while (NULL != (vrh = vrh_head))
449 {
450 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
451 GNUNET_CONTAINER_DLL_remove (vrh_head,
452 vrh_tail,
453 vrh);
454 cleanup_handle (vrh);
455 }
456
457 if (NULL != gns)
458 {
459 GNUNET_GNS_disconnect (gns);
460 gns = NULL;
461 }
462 if (NULL != namestore)
463 {
464 GNUNET_NAMESTORE_disconnect (namestore);
465 namestore = NULL;
466 }
467 if (NULL != statistics)
468 {
469 GNUNET_STATISTICS_destroy (statistics,
470 GNUNET_NO);
471 statistics = NULL;
472 }
473
474}
475
476
477
478/**
479 * Send.
480 *
481 * @param handle the handle to the request
482 */
483static void
484send_lookup_response (struct VerifyRequestHandle *vrh)
485{
486 struct GNUNET_MQ_Envelope *env;
487 struct DelegationChainResultMessage *rmsg;
488 struct DelegationChainEntry *dce;
489 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
490 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
491 struct CredentialRecordEntry *cd;
492 struct CredentialRecordEntry *tmp;
493 size_t size;
494 int i;
495
496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
497 "Sending response\n");
498 dce = vrh->delegation_chain_head;
499 for (i=0;i<vrh->delegation_chain_size;i++)
500 {
501 dd[i].issuer_key = dce->issuer_key;
502 dd[i].subject_key = dce->subject_key;
503 dd[i].issuer_attribute = dce->issuer_attribute;
504 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
505 dd[i].subject_attribute_len = 0;
506 dd[i].subject_attribute = NULL;
507 if (NULL != dce->subject_attribute)
508 {
509 dd[i].subject_attribute = dce->subject_attribute;
510 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
511 }
512 dce = dce->next;
513 }
514
515 /**
516 * Remove all credentials not needed
517 */
518 for (cd = vrh->cred_chain_head; NULL != cd;)
519 {
520 if (cd->refcount > 0)
521 {
522 cd = cd->next;
523 continue;
524 }
525 tmp = cd;
526 cd = cd->next;
527 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
528 vrh->cred_chain_tail,
529 tmp);
530 GNUNET_free (tmp->credential);
531 GNUNET_free (tmp);
532 vrh->cred_chain_size--;
533 }
534
535 /**
536 * Get serialized record data
537 * Append at the end of rmsg
538 */
539 cd = vrh->cred_chain_head;
540 for (i=0;i<vrh->cred_chain_size;i++)
541 {
542 cred[i].issuer_key = cd->credential->issuer_key;
543 cred[i].subject_key = cd->credential->subject_key;
544 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
545 cred[i].issuer_attribute = cd->credential->issuer_attribute;
546 cred[i].expiration = cd->credential->expiration;
547 cred[i].signature = cd->credential->signature;
548 cd = cd->next;
549 }
550 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
551 dd,
552 vrh->cred_chain_size,
553 cred);
554 env = GNUNET_MQ_msg_extra (rmsg,
555 size,
556 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
557 //Assign id so that client can find associated request
558 rmsg->id = vrh->request_id;
559 rmsg->d_count = htonl (vrh->delegation_chain_size);
560 rmsg->c_count = htonl (vrh->cred_chain_size);
561
562 if (0 < vrh->cred_chain_size)
563 rmsg->cred_found = htonl (GNUNET_YES);
564 else
565 rmsg->cred_found = htonl (GNUNET_NO);
566
567 GNUNET_assert (-1 !=
568 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
569 dd,
570 vrh->cred_chain_size,
571 cred,
572 size,
573 (char*)&rmsg[1]));
574
575 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
576 env);
577 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
578 cleanup_handle(vrh);
579
580 GNUNET_STATISTICS_update (statistics,
581 "Completed verifications", 1,
582 GNUNET_NO);
583}
584
585
586static void
587backward_resolution (void* cls,
588 uint32_t rd_count,
589 const struct GNUNET_GNSRECORD_Data *rd)
590{
591
592 struct VerifyRequestHandle *vrh;
593 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
594 struct CredentialRecordEntry *cred_pointer;
595 struct DelegationSetQueueEntry *current_set;
596 struct DelegationSetQueueEntry *ds_entry;
597 struct DelegationSetQueueEntry *tmp_set;
598 struct DelegationQueueEntry *dq_entry;
599 char *expanded_attr;
600 char *lookup_attribute;
601 int i;
602 int j;
603
604
605 current_set = cls;
606 current_set->lookup_request = NULL;
607 vrh = current_set->handle;
608 vrh->pending_lookups--;
609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
610 "Got %d attrs\n", rd_count);
611
612 // Each OR
613 for (i=0; i < rd_count; i++)
614 {
615 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
616 continue;
617
618 sets = rd[i].data;
619 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
621 "Found new attribute delegation with %d sets. Creating new Job...\n",
622 ntohl (sets->set_count));
623
624 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
625 (const char*)&sets[1],
626 ntohl(sets->set_count),
627 set))
628 {
629 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
630 "Failed to deserialize!\n");
631 continue;
632 }
633 dq_entry = GNUNET_new (struct DelegationQueueEntry);
634 dq_entry->required_solutions = ntohl(sets->set_count);
635 dq_entry->parent_set = current_set;
636 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
637 current_set->queue_entries_tail,
638 dq_entry);
639 // Each AND
640 for (j=0; j<ntohl(sets->set_count); j++)
641 {
642 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
643 if (NULL != current_set->attr_trailer)
644 {
645 if (0 == set[j].subject_attribute_len)
646 {
647 GNUNET_asprintf (&expanded_attr,
648 "%s",
649 current_set->attr_trailer);
650
651 } else {
652 GNUNET_asprintf (&expanded_attr,
653 "%s.%s",
654 set[j].subject_attribute,
655 current_set->attr_trailer);
656 }
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658 "Expanded to %s\n", expanded_attr);
659 ds_entry->unresolved_attribute_delegation = expanded_attr;
660 } else {
661 if (0 != set[j].subject_attribute_len)
662 {
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
664 "Not Expanding %s\n", set[j].subject_attribute);
665 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
666 }
667 }
668
669 //Add a credential chain entry
670 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
671 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
672 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
673 GNUNET_memcpy (ds_entry->issuer_key,
674 &set[j].subject_key,
675 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
676 if (0 < set[j].subject_attribute_len)
677 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
678 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
679 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
680
681 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
682 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
683 dq_entry->set_entries_tail,
684 ds_entry);
685
686 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
687 "Checking for cred match\n");
688 /**
689 * Check if this delegation already matches one of our credentials
690 */
691 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
692 cred_pointer = cred_pointer->next)
693 {
694 if(0 != memcmp (&set->subject_key,
695 &cred_pointer->credential->issuer_key,
696 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
697 continue;
698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
699 "Checking if %s matches %s\n",
700 ds_entry->unresolved_attribute_delegation,
701 cred_pointer->credential->issuer_attribute);
702
703 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
704 cred_pointer->credential->issuer_attribute))
705 continue;
706
707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
708 "Found issuer\n");
709 cred_pointer->refcount++;
710 //Backtrack
711 for (tmp_set = ds_entry;
712 NULL != tmp_set->parent_queue_entry;
713 tmp_set = tmp_set->parent_queue_entry->parent_set)
714 {
715 tmp_set->parent_queue_entry->required_solutions--;
716 if (NULL != tmp_set->delegation_chain_entry)
717 {
718 vrh->delegation_chain_size++;
719 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
720 vrh->delegation_chain_tail,
721 tmp_set->delegation_chain_entry);
722 }
723 if (0 < tmp_set->parent_queue_entry->required_solutions)
724 break;
725 }
726
727 if (NULL == tmp_set->parent_queue_entry)
728 {
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "All solutions found\n");
731 //Found match
732 send_lookup_response (vrh);
733 return;
734 }
735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
736 "Not all solutions found yet.\n");
737 continue;
738
739 }
740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
741 "Building new lookup request from %s\n",
742 ds_entry->unresolved_attribute_delegation);
743 //Continue with backward resolution
744 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
745 strcpy (issuer_attribute_name,
746 ds_entry->unresolved_attribute_delegation);
747 char *next_attr = strtok (issuer_attribute_name, ".");
748 GNUNET_asprintf (&lookup_attribute,
749 "%s.gnu",
750 next_attr);
751 GNUNET_asprintf (&ds_entry->lookup_attribute,
752 "%s",
753 next_attr);
754 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
755 {
756 ds_entry->attr_trailer = NULL;
757 } else {
758 next_attr += strlen (next_attr) + 1;
759 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
760 }
761
762 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
763 "Looking up %s\n", ds_entry->lookup_attribute);
764 if (NULL != ds_entry->attr_trailer)
765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
766 "%s still to go...\n", ds_entry->attr_trailer);
767
768 vrh->pending_lookups++;
769 ds_entry->handle = vrh;
770 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
771 lookup_attribute,
772 ds_entry->issuer_key, //issuer_key,
773 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
774 GNUNET_GNS_LO_DEFAULT,
775 &backward_resolution,
776 ds_entry);
777 GNUNET_free (lookup_attribute);
778 }
779 }
780
781 if(0 == vrh->pending_lookups)
782 {
783 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
784 "We are all out of attributes...\n");
785 send_lookup_response (vrh);
786 return;
787
788 }
789}
790
791
792/**
793 * Result from GNS lookup.
794 *
795 * @param cls the closure (our client lookup handle)
796 * @param rd_count the number of records in @a rd
797 * @param rd the record data
798 */
799static void
800delegation_chain_resolution_start (void* cls)
801{
802 struct VerifyRequestHandle *vrh = cls;
803 struct DelegationSetQueueEntry *ds_entry;
804 struct CredentialRecordEntry *cr_entry;
805 vrh->lookup_request = NULL;
806
807 if (0 == vrh->cred_chain_size)
808 {
809 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
810 "No credentials found\n");
811 send_lookup_response (vrh);
812 return;
813 }
814
815 for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
816 {
817 if (0 != memcmp (&cr_entry->credential->issuer_key,
818 &vrh->issuer_key,
819 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
820 continue;
821 if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
822 continue;
823 cr_entry->refcount++;
824 //Found match prematurely
825 send_lookup_response (vrh);
826 return;
827
828 }
829
830 /**
831 * Check for attributes from the issuer and follow the chain
832 * till you get the required subject's attributes
833 */
834 char issuer_attribute_name[strlen (vrh->issuer_attribute)];
835 strcpy (issuer_attribute_name,
836 vrh->issuer_attribute);
837 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
838 ".gnu");
839 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
840 "Looking up %s\n", issuer_attribute_name);
841 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
842 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
843 memcpy (ds_entry->issuer_key,
844 &vrh->issuer_key,
845 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
846 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
847 ds_entry->handle = vrh;
848 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
849 vrh->root_set = ds_entry;
850 vrh->pending_lookups = 1;
851 //Start with backward resolution
852 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
853 issuer_attribute_name,
854 &vrh->issuer_key, //issuer_key,
855 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
856 GNUNET_GNS_LO_DEFAULT,
857 &backward_resolution,
858 ds_entry);
859}
860
861/**
862 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
863 *
864 * @param cls client sending the message
865 * @param v_msg message of type `struct VerifyMessage`
866 * @return #GNUNET_OK if @a v_msg is well-formed
867 */
868static int
869check_verify (void *cls,
870 const struct VerifyMessage *v_msg)
871{
872 size_t msg_size;
873 const char* attr;
874
875 msg_size = ntohs (v_msg->header.size);
876 if (msg_size < sizeof (struct VerifyMessage))
877 {
878 GNUNET_break (0);
879 return GNUNET_SYSERR;
880 }
881 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
882 {
883 GNUNET_break (0);
884 return GNUNET_SYSERR;
885 }
886 attr = (const char *) &v_msg[1];
887
888 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
889 {
890 GNUNET_break (0);
891 return GNUNET_SYSERR;
892 }
893 return GNUNET_OK;
894}
895
896/**
897 * Handle Credential verification requests from client
898 *
899 * @param cls the closure
900 * @param client the client
901 * @param message the message
902 */
903static void
904handle_verify (void *cls,
905 const struct VerifyMessage *v_msg)
906{
907 struct VerifyRequestHandle *vrh;
908 struct GNUNET_SERVICE_Client *client = cls;
909 struct CredentialRecordEntry *cr_entry;
910 uint32_t credentials_count;
911 uint32_t credential_data_size;
912 int i;
913 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
914 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
915 char *attrptr = attr;
916 char *credential_data;
917 const char *utf_in;
918
919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
920 "Received VERIFY message\n");
921 utf_in = (const char *) &v_msg[1];
922 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
923 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
924 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
925 vrh = GNUNET_new (struct VerifyRequestHandle);
926 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
927 vrh->client = client;
928 vrh->request_id = v_msg->id;
929 vrh->issuer_key = v_msg->issuer_key;
930 vrh->subject_key = v_msg->subject_key;
931 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
932 if (NULL == issuer_attribute)
933 {
934 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
935 "No issuer attribute provided!\n");
936 send_lookup_response (vrh);
937 return;
938 }
939 /**
940 * First, collect credentials
941 * TODO: cleanup!
942 */
943 credentials_count = ntohl(v_msg->c_count);
944 credential_data_size = ntohs (v_msg->header.size)
945 - sizeof (struct VerifyMessage)
946 - ntohs (v_msg->issuer_attribute_len)
947 - 1;
948 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
949 credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
950 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
951 credential_data,
952 credentials_count,
953 credentials))
954 {
955 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
956 "Cannot deserialize credentials!\n");
957 send_lookup_response (vrh);
958 return;
959 }
960
961 for (i=0;i<credentials_count;i++) {
962 cr_entry = GNUNET_new (struct CredentialRecordEntry);
963 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
964 credentials[i].issuer_attribute_len);
965 GNUNET_memcpy (cr_entry->credential,
966 &credentials[i],
967 sizeof (struct GNUNET_CREDENTIAL_Credential));
968 GNUNET_memcpy (&cr_entry->credential[1],
969 credentials[i].issuer_attribute,
970 credentials[i].issuer_attribute_len);
971 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
972 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
973 vrh->cred_chain_tail,
974 cr_entry);
975 vrh->cred_chain_size++;
976 }
977
978 delegation_chain_resolution_start (vrh);
979
980}
981
982/**
983 * We encountered an error while collecting
984 */
985static void
986handle_cred_collection_error_cb (void *cls)
987{
988 struct VerifyRequestHandle *vrh = cls;
989 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
990 "Got disconnected from namestore database.\n");
991 vrh->cred_collection_iter = NULL;
992 send_lookup_response (vrh);
993}
994
995static void
996collect_next (void *cls)
997{
998 struct VerifyRequestHandle *vrh = cls;
999 vrh->collect_next_task = NULL;
1000 GNUNET_assert (NULL != vrh->cred_collection_iter);
1001 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
1002}
1003
1004/**
1005 * Store credential
1006 */
1007static void
1008handle_cred_collection_cb (void *cls,
1009 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
1010 const char *label,
1011 unsigned int rd_count,
1012 const struct GNUNET_GNSRECORD_Data *rd)
1013{
1014 struct VerifyRequestHandle *vrh = cls;
1015 struct GNUNET_CREDENTIAL_Credential *crd;
1016 struct CredentialRecordEntry *cr_entry;
1017 int cred_record_count;
1018 int i;
1019
1020 cred_record_count = 0;
1021 for (i=0; i < rd_count; i++)
1022 {
1023 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
1024 continue;
1025 cred_record_count++;
1026 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
1027 rd[i].data_size);
1028 if (NULL == crd)
1029 {
1030 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1031 "Invalid credential found\n");
1032 continue;
1033 }
1034 cr_entry = GNUNET_new (struct CredentialRecordEntry);
1035 cr_entry->credential = crd;
1036 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
1037 vrh->cred_chain_tail,
1038 cr_entry);
1039 vrh->cred_chain_size++;
1040 }
1041 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
1042 vrh);
1043}
1044
1045/**
1046 * We encountered an error while collecting
1047 */
1048static void
1049handle_cred_collection_finished_cb (void *cls)
1050{
1051 struct VerifyRequestHandle *vrh = cls;
1052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1053 "Done collecting credentials.\n");
1054 vrh->cred_collection_iter = NULL;
1055 delegation_chain_resolution_start (vrh);
1056}
1057
1058/**
1059 * Handle Credential collection requests from client
1060 *
1061 * @param cls the closure
1062 * @param client the client
1063 * @param message the message
1064 */
1065static void
1066handle_collect (void *cls,
1067 const struct CollectMessage *c_msg)
1068{
1069 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1070 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1071 struct VerifyRequestHandle *vrh;
1072 struct GNUNET_SERVICE_Client *client = cls;
1073 char *attrptr = attr;
1074 const char *utf_in;
1075
1076 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1077 "Received COLLECT message\n");
1078
1079 utf_in = (const char *) &c_msg[1];
1080 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1081
1082 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1083 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1084 vrh = GNUNET_new (struct VerifyRequestHandle);
1085 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1086 vrh->client = client;
1087 vrh->request_id = c_msg->id;
1088 vrh->issuer_key = c_msg->issuer_key;
1089 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1090 &vrh->subject_key);
1091 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1092
1093 if (NULL == issuer_attribute)
1094 {
1095 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1096 "No issuer attribute provided!\n");
1097 send_lookup_response (vrh);
1098 return;
1099 }
1100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1101 "Getting credentials for subject\n");
1102 /**
1103 * First, get attribute from subject
1104 */
1105 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
1106 &c_msg->subject_key,
1107 &handle_cred_collection_error_cb,
1108 vrh,
1109 &handle_cred_collection_cb,
1110 vrh,
1111 &handle_cred_collection_finished_cb,
1112 vrh);
1113}
1114
1115
1116/**
1117 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT message
1118 *
1119 * @param cls client sending the message
1120 * @param v_msg message of type `struct CollectMessage`
1121 * @return #GNUNET_OK if @a v_msg is well-formed
1122 */
1123static int
1124check_collect (void *cls,
1125 const struct CollectMessage *c_msg)
1126{
1127 size_t msg_size;
1128 const char* attr;
1129
1130 msg_size = ntohs (c_msg->header.size);
1131 if (msg_size < sizeof (struct CollectMessage))
1132 {
1133 GNUNET_break (0);
1134 return GNUNET_SYSERR;
1135 }
1136 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1137 {
1138 GNUNET_break (0);
1139 return GNUNET_SYSERR;
1140 }
1141 attr = (const char *) &c_msg[1];
1142
1143 if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
1144 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1145 {
1146 GNUNET_break (0);
1147 return GNUNET_SYSERR;
1148 }
1149 return GNUNET_OK;
1150}
1151
1152/**
1153 * One of our clients disconnected, clean up after it.
1154 *
1155 * @param cls NULL
1156 * @param client the client that disconnected
1157 */
1158static void
1159client_disconnect_cb (void *cls,
1160 struct GNUNET_SERVICE_Client *client,
1161 void *app_ctx)
1162{
1163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1164 "Client %p disconnected\n",
1165 client);
1166}
1167
1168/**
1169 * Add a client to our list of active clients.
1170 *
1171 * @param cls NULL
1172 * @param client client to add
1173 * @param mq message queue for @a client
1174 * @return this client
1175 */
1176static void *
1177client_connect_cb (void *cls,
1178 struct GNUNET_SERVICE_Client *client,
1179 struct GNUNET_MQ_Handle *mq)
1180{
1181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1182 "Client %p connected\n",
1183 client);
1184 return client;
1185}
1186
1187/**
1188 * Process Credential requests.
1189 *
1190 * @param cls closure
1191 * @param server the initialized server
1192 * @param c configuration to use
1193 */
1194static void
1195run (void *cls,
1196 const struct GNUNET_CONFIGURATION_Handle *c,
1197 struct GNUNET_SERVICE_Handle *handle)
1198{
1199
1200 gns = GNUNET_GNS_connect (c);
1201 if (NULL == gns)
1202 {
1203 fprintf (stderr,
1204 _("Failed to connect to GNS\n"));
1205 }
1206 namestore = GNUNET_NAMESTORE_connect (c);
1207 if (NULL == namestore)
1208 {
1209 fprintf (stderr,
1210 _("Failed to connect to namestore\n"));
1211 }
1212
1213 statistics = GNUNET_STATISTICS_create ("credential", c);
1214 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1215}
1216
1217
1218/**
1219 * Define "main" method using service macro
1220 */
1221GNUNET_SERVICE_MAIN
1222("credential",
1223 GNUNET_SERVICE_OPTION_NONE,
1224 &run,
1225 &client_connect_cb,
1226 &client_disconnect_cb,
1227 NULL,
1228 GNUNET_MQ_hd_var_size (verify,
1229 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1230 struct VerifyMessage,
1231 NULL),
1232 GNUNET_MQ_hd_var_size (collect,
1233 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1234 struct CollectMessage,
1235 NULL),
1236 GNUNET_MQ_handler_end());
1237
1238/* 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..72d6b53f5
--- /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 Adnan Husain
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_credential_service.h"
31#include "gnunet_gnsrecord_plugin.h"
32#include "gnunet_signatures.h"
33#include "credential_serialization.h"
34#include "credential_misc.h"
35
36/**
37 * Convert the 'value' of a record to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the record
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46credential_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51
52 const char *cdata;
53
54 switch (type)
55 {
56 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
57 {
58 struct GNUNET_CREDENTIAL_DelegationRecord sets;
59 char *attr_str;
60 char *subject_pkey;
61 char *tmp_str;
62 int i;
63 if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
64 return NULL; /* malformed */
65 memcpy (&sets,
66 data,
67 sizeof (sets));
68 cdata = data;
69 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
70 if (GNUNET_OK != GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll (sets.data_size),
71 &cdata[sizeof (sets)],
72 ntohl (sets.set_count),
73 set))
74 return NULL;
75
76 for (i=0;i<ntohl(sets.set_count);i++)
77 {
78 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key);
79 GNUNET_log (GNUNET_ERROR_TYPE_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..48d48fba0
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,1179 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file gns/plugin_rest_credential.c
23 * @brief GNUnet CREDENTIAL REST plugin
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_rest_plugin.h"
29#include <gnunet_identity_service.h>
30#include <gnunet_gnsrecord_lib.h>
31#include <gnunet_namestore_service.h>
32#include <gnunet_credential_service.h>
33#include <gnunet_rest_lib.h>
34#include <gnunet_jsonapi_lib.h>
35#include <gnunet_jsonapi_util.h>
36#include <jansson.h>
37
38#define GNUNET_REST_API_NS_CREDENTIAL "/credential"
39
40#define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
41
42#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
43
44#define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
45
46#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
47
48#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
49
50#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
51
52#define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
53
54#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
55
56#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
57
58#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
59
60#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
61
62/**
63 * @brief struct returned by the initialization function of the plugin
64 */
65struct Plugin
66{
67 const struct GNUNET_CONFIGURATION_Handle *cfg;
68};
69
70const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72struct RequestHandle
73{
74 /**
75 * Handle to Credential service.
76 */
77 struct GNUNET_CREDENTIAL_Handle *credential;
78
79 /**
80 * Handle to lookup request
81 */
82 struct GNUNET_CREDENTIAL_Request *verify_request;
83
84 /**
85 * Handle to issue request
86 */
87 struct GNUNET_CREDENTIAL_Request *issue_request;
88
89 /**
90 * Handle to identity
91 */
92 struct GNUNET_IDENTITY_Handle *identity;
93
94 /**
95 * Handle to identity operation
96 */
97 struct GNUNET_IDENTITY_Operation *id_op;
98
99 /**
100 * Handle to ego lookup
101 */
102 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
103
104 /**
105 * Handle to rest request
106 */
107 struct GNUNET_REST_RequestHandle *rest_handle;
108
109 /**
110 * ID of a task associated with the resolution process.
111 */
112 struct GNUNET_SCHEDULER_Task * timeout_task;
113
114 /**
115 * The root of the received JSON or NULL
116 */
117 json_t *json_root;
118
119 /**
120 * The plugin result processor
121 */
122 GNUNET_REST_ResultProcessor proc;
123
124 /**
125 * The closure of the result processor
126 */
127 void *proc_cls;
128
129 /**
130 * The issuer attribute to verify
131 */
132 char *issuer_attr;
133
134 /**
135 * The subject attribute
136 */
137 char *subject_attr;
138
139 /**
140 * The public key of the issuer
141 */
142 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
143
144 /**
145 * The public key of the subject
146 */
147 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
148
149 /**
150 * HTTP response code
151 */
152 int response_code;
153
154 /**
155 * Timeout
156 */
157 struct GNUNET_TIME_Relative timeout;
158
159};
160
161
162/**
163 * Cleanup lookup handle.
164 *
165 * @param handle Handle to clean up
166 */
167static void
168cleanup_handle (struct RequestHandle *handle)
169{
170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
171 "Cleaning up\n");
172 if (NULL != handle->json_root)
173 json_decref (handle->json_root);
174
175 if (NULL != handle->issuer_attr)
176 GNUNET_free (handle->issuer_attr);
177 if (NULL != handle->subject_attr)
178 GNUNET_free (handle->subject_attr);
179 if (NULL != handle->verify_request)
180 GNUNET_CREDENTIAL_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
197/**
198 * Task run on shutdown. Cleans up everything.
199 *
200 * @param cls unused
201 * @param tc scheduler context
202 */
203static void
204do_error (void *cls)
205{
206 struct RequestHandle *handle = cls;
207 struct MHD_Response *resp;
208
209 resp = GNUNET_REST_create_response (NULL);
210 handle->proc (handle->proc_cls, resp, handle->response_code);
211 cleanup_handle (handle);
212}
213
214/**
215 * Attribute delegation to JSON
216 * @param attr the attribute
217 * @return JSON, NULL if failed
218 */
219static json_t*
220attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
221{
222 char *subject;
223 char *issuer;
224 json_t *attr_obj;
225
226 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
227 if (NULL == issuer)
228 {
229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
230 "Issuer in delegation malformed\n");
231 return NULL;
232 }
233 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
234 if (NULL == subject)
235 {
236 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
237 "Subject in credential malformed\n");
238 GNUNET_free (issuer);
239 return NULL;
240 }
241 attr_obj = json_object ();
242
243 json_object_set_new (attr_obj, "issuer", json_string (issuer));
244 json_object_set_new (attr_obj, "issuer_attribute",
245 json_string (delegation_chain_entry->issuer_attribute));
246
247 json_object_set_new (attr_obj, "subject", json_string (subject));
248 if (0 < delegation_chain_entry->subject_attribute_len)
249 {
250 json_object_set_new (attr_obj, "subject_attribute",
251 json_string (delegation_chain_entry->subject_attribute));
252 }
253 GNUNET_free (issuer);
254 GNUNET_free (subject);
255 return attr_obj;
256}
257
258/**
259 * JSONAPI resource to Credential
260 * @param res the JSONAPI resource
261 * @return the resulting credential, NULL if failed
262 */
263static struct GNUNET_CREDENTIAL_Credential*
264json_to_credential (json_t *res)
265{
266 struct GNUNET_CREDENTIAL_Credential *cred;
267 json_t *tmp;
268 const char *attribute;
269 const char *signature;
270 char *sig;
271
272 tmp = json_object_get (res, "attribute");
273 if (0 == json_is_string (tmp))
274 {
275 return NULL;
276 }
277 attribute = json_string_value (tmp);
278 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
279 + strlen (attribute));
280 cred->issuer_attribute = attribute;
281 cred->issuer_attribute_len = strlen (attribute);
282 tmp = json_object_get (res, "issuer");
283 if (0 == json_is_string (tmp))
284 {
285 GNUNET_free (cred);
286 return NULL;
287 }
288
289 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
290 strlen (json_string_value(tmp)),
291 &cred->issuer_key);
292 tmp = json_object_get (res, "subject");
293 if (0 == json_is_string (tmp))
294 {
295 GNUNET_free (cred);
296 return NULL;
297 }
298 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
299 strlen (json_string_value(tmp)),
300 &cred->subject_key);
301
302 tmp = json_object_get (res, "signature");
303 if (0 == json_is_string (tmp))
304 {
305 GNUNET_free (cred);
306 return NULL;
307 }
308 signature = json_string_value (tmp);
309 GNUNET_STRINGS_base64_decode (signature,
310 strlen (signature),
311 (char**)&sig);
312 GNUNET_memcpy (&cred->signature,
313 sig,
314 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
315 GNUNET_free (sig);
316
317 tmp = json_object_get (res, "expiration");
318 if (0 == json_is_integer (tmp))
319 {
320 GNUNET_free (cred);
321 return NULL;
322 }
323 cred->expiration.abs_value_us = json_integer_value (tmp);
324 return cred;
325}
326
327
328/**
329 * Credential to JSON
330 * @param cred the credential
331 * @return the resulting json, NULL if failed
332 */
333static json_t*
334credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
335{
336 char *issuer;
337 char *subject;
338 char *signature;
339 char attribute[cred->issuer_attribute_len + 1];
340 json_t *cred_obj;
341
342 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
343 if (NULL == issuer)
344 {
345 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
346 "Issuer in credential malformed\n");
347 return NULL;
348 }
349 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
350 if (NULL == subject)
351 {
352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
353 "Subject in credential malformed\n");
354 GNUNET_free (issuer);
355 return NULL;
356 }
357 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
358 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
359 &signature);
360 memcpy (attribute,
361 cred->issuer_attribute,
362 cred->issuer_attribute_len);
363 attribute[cred->issuer_attribute_len] = '\0';
364 cred_obj = json_object ();
365 json_object_set_new (cred_obj, "issuer", json_string (issuer));
366 json_object_set_new (cred_obj, "subject", json_string (subject));
367 json_object_set_new (cred_obj, "attribute", json_string (attribute));
368 json_object_set_new (cred_obj, "signature", json_string (signature));
369 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
370 GNUNET_free (issuer);
371 GNUNET_free (subject);
372 GNUNET_free (signature);
373 return cred_obj;
374}
375
376/**
377 * Function called with the result of a Credential lookup.
378 *
379 * @param cls the 'const char *' name that was resolved
380 * @param cd_count number of records returned
381 * @param cd array of @a cd_count records with the results
382 */
383static void
384handle_collect_response (void *cls,
385 unsigned int d_count,
386 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
387 unsigned int c_count,
388 struct GNUNET_CREDENTIAL_Credential *cred)
389{
390 struct RequestHandle *handle = cls;
391 struct MHD_Response *resp;
392 struct GNUNET_JSONAPI_Document *json_document;
393 struct GNUNET_JSONAPI_Resource *json_resource;
394 json_t *cred_obj;
395 json_t *cred_array;
396 char *result;
397 char *issuer;
398 char *id;
399 uint32_t i;
400
401 handle->verify_request = NULL;
402 if (NULL == cred) {
403 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
404 "Verify failed.\n");
405 handle->response_code = MHD_HTTP_NOT_FOUND;
406 GNUNET_SCHEDULER_add_now (&do_error, handle);
407 return;
408 }
409 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
410 if (NULL == issuer)
411 {
412 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
413 "Issuer in delegation malformed\n");
414 return;
415 }
416 GNUNET_asprintf (&id,
417 "%s.%s",
418 issuer,
419 handle->issuer_attr);
420 GNUNET_free (issuer);
421 json_document = GNUNET_JSONAPI_document_new ();
422 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
423 id);
424 GNUNET_free (id);
425 cred_array = json_array ();
426 for (i=0;i<c_count;i++)
427 {
428 cred_obj = credential_to_json (&cred[i]);
429 json_array_append_new (cred_array, cred_obj);
430 }
431 GNUNET_JSONAPI_resource_add_attr (json_resource,
432 GNUNET_REST_JSONAPI_CREDENTIAL,
433 cred_array);
434 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
435 GNUNET_JSONAPI_document_serialize (json_document, &result);
436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
437 "Result %s\n",
438 result);
439 json_decref (cred_array);
440 GNUNET_JSONAPI_document_delete (json_document);
441 resp = GNUNET_REST_create_response (result);
442 GNUNET_free(result);
443 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
444 cleanup_handle (handle);
445}
446
447static void
448subject_ego_lookup (void *cls,
449 const struct GNUNET_IDENTITY_Ego *ego)
450{
451 struct RequestHandle *handle = cls;
452 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
453 handle->ego_lookup = NULL;
454
455 if (NULL == ego)
456 {
457 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
458 "Subject not found\n");
459 GNUNET_SCHEDULER_add_now (&do_error, handle);
460 return;
461 }
462 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
463 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
464 &handle->issuer_key,
465 handle->issuer_attr,
466 sub_key,
467 &handle_collect_response,
468 handle);
469}
470
471
472
473/**
474 * Function called with the result of a Credential lookup.
475 *
476 * @param cls the 'const char *' name that was resolved
477 * @param cd_count number of records returned
478 * @param cd array of @a cd_count records with the results
479 */
480static void
481handle_verify_response (void *cls,
482 unsigned int d_count,
483 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
484 unsigned int c_count,
485 struct GNUNET_CREDENTIAL_Credential *cred)
486{
487
488 struct RequestHandle *handle = cls;
489 struct MHD_Response *resp;
490 struct GNUNET_JSONAPI_Document *json_document;
491 struct GNUNET_JSONAPI_Resource *json_resource;
492 json_t *cred_obj;
493 json_t *attr_obj;
494 json_t *cred_array;
495 json_t *attr_array;
496 char *result;
497 char *issuer;
498 char *id;
499 uint32_t i;
500
501 handle->verify_request = NULL;
502 if (NULL == cred) {
503 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
504 "Verify failed.\n");
505 handle->response_code = MHD_HTTP_NOT_FOUND;
506 GNUNET_SCHEDULER_add_now (&do_error, handle);
507 return;
508 }
509 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
510 if (NULL == issuer)
511 {
512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
513 "Issuer in delegation malformed\n");
514 return;
515 }
516 GNUNET_asprintf (&id,
517 "%s.%s",
518 issuer,
519 handle->issuer_attr);
520 GNUNET_free (issuer);
521 json_document = GNUNET_JSONAPI_document_new ();
522 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
523 id);
524 GNUNET_free (id);
525 attr_array = json_array ();
526 for (i = 0; i < d_count; i++)
527 {
528 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
529 json_array_append_new (attr_array, attr_obj);
530 }
531 cred_array = json_array ();
532 for (i=0;i<c_count;i++)
533 {
534 cred_obj = credential_to_json (&cred[i]);
535 json_array_append_new (cred_array, cred_obj);
536 }
537 GNUNET_JSONAPI_resource_add_attr (json_resource,
538 GNUNET_REST_JSONAPI_CREDENTIAL,
539 cred_array);
540 GNUNET_JSONAPI_resource_add_attr (json_resource,
541 GNUNET_REST_JSONAPI_DELEGATIONS,
542 attr_array);
543 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
544 GNUNET_JSONAPI_document_serialize (json_document, &result);
545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
546 "Result %s\n",
547 result);
548 json_decref (attr_array);
549 json_decref (cred_array);
550 GNUNET_JSONAPI_document_delete (json_document);
551 resp = GNUNET_REST_create_response (result);
552 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
553 GNUNET_free (result);
554 cleanup_handle (handle);
555}
556
557static void
558collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
559 const char* url,
560 void *cls)
561{
562 struct RequestHandle *handle = cls;
563 struct GNUNET_HashCode key;
564 char *tmp;
565 char *entity_attr;
566
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
568 "Connecting...\n");
569 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
570 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
571 &do_error, handle);
572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
573 "Connected\n");
574 if (NULL == handle->credential)
575 {
576 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
577 "Connecting to CREDENTIAL failed\n");
578 GNUNET_SCHEDULER_add_now (&do_error, handle);
579 return;
580 }
581 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
582 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
583 &key);
584 if ( GNUNET_NO ==
585 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
586 &key) )
587 {
588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
589 "Missing issuer attribute\n");
590 GNUNET_SCHEDULER_add_now (&do_error, handle);
591 return;
592 }
593 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
594 &key);
595 entity_attr = GNUNET_strdup (tmp);
596 tmp = strtok(entity_attr, ".");
597 if (NULL == tmp)
598 {
599 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
600 "Malformed issuer or attribute\n");
601 GNUNET_free (entity_attr);
602 GNUNET_SCHEDULER_add_now (&do_error, handle);
603 return;
604 }
605 if (GNUNET_OK !=
606 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
607 strlen (tmp),
608 &handle->issuer_key))
609 {
610 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
611 "Malformed issuer key\n");
612 GNUNET_free (entity_attr);
613 GNUNET_SCHEDULER_add_now (&do_error, handle);
614 return;
615 }
616 tmp = strtok (NULL, "."); //Issuer attribute
617 if (NULL == tmp)
618 {
619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
620 "Malformed attribute\n");
621 GNUNET_free (entity_attr);
622 GNUNET_SCHEDULER_add_now (&do_error, handle);
623 return;
624 }
625 handle->issuer_attr = GNUNET_strdup (tmp);
626 GNUNET_free (entity_attr);
627
628 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
629 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
630 &key);
631 if ( GNUNET_NO ==
632 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
633 &key) )
634 {
635 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
636 "Missing subject\n");
637 GNUNET_free (entity_attr);
638 GNUNET_SCHEDULER_add_now (&do_error, handle);
639 return;
640 }
641 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
642 &key);
643 if (NULL == tmp)
644 {
645 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
646 "Malformed subject\n");
647 GNUNET_free (entity_attr);
648 GNUNET_SCHEDULER_add_now (&do_error, handle);
649 return;
650 }
651 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
652 tmp,
653 &subject_ego_lookup,
654 handle);
655}
656
657
658
659static void
660verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
661 const char* url,
662 void *cls)
663{
664 struct RequestHandle *handle = cls;
665 struct GNUNET_HashCode key;
666 struct GNUNET_JSONAPI_Document *json_obj;
667 struct GNUNET_JSONAPI_Resource *res;
668 struct GNUNET_CREDENTIAL_Credential *cred;
669 char *tmp;
670 char *entity_attr;
671 int i;
672 uint32_t credential_count;
673 uint32_t resource_count;
674 json_t *cred_json;
675 json_t *data_js;
676 json_error_t err;
677
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
679 "Connecting...\n");
680 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
681 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
682 &do_error, handle);
683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
684 "Connected\n");
685 if (NULL == handle->credential)
686 {
687 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
688 "Connecting to CREDENTIAL failed\n");
689 GNUNET_SCHEDULER_add_now (&do_error, handle);
690 return;
691 }
692 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
693 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
694 &key);
695 if ( GNUNET_NO ==
696 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
697 &key) )
698 {
699 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
700 "Missing issuer attribute\n");
701 GNUNET_SCHEDULER_add_now (&do_error, handle);
702 return;
703 }
704 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
705 &key);
706 entity_attr = GNUNET_strdup (tmp);
707 tmp = strtok(entity_attr, ".");
708 if (NULL == tmp)
709 {
710 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
711 "Malformed issuer or attribute\n");
712 GNUNET_free (entity_attr);
713 GNUNET_SCHEDULER_add_now (&do_error, handle);
714 return;
715 }
716 if (GNUNET_OK !=
717 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
718 strlen (tmp),
719 &handle->issuer_key))
720 {
721 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
722 "Malformed issuer key\n");
723 GNUNET_free (entity_attr);
724 GNUNET_SCHEDULER_add_now (&do_error, handle);
725 return;
726 }
727 tmp = strtok (NULL, "."); //Issuer attribute
728 if (NULL == tmp)
729 {
730 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
731 "Malformed attribute\n");
732 GNUNET_free (entity_attr);
733 GNUNET_SCHEDULER_add_now (&do_error, handle);
734 return;
735 }
736 handle->issuer_attr = GNUNET_strdup (tmp);
737 GNUNET_free (entity_attr);
738
739 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
740 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
741 &key);
742 if ( GNUNET_NO ==
743 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
744 &key) )
745 {
746 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
747 "Missing subject key\n");
748 GNUNET_free (entity_attr);
749 GNUNET_SCHEDULER_add_now (&do_error, handle);
750 return;
751 }
752 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
753 &key);
754 if (NULL == tmp)
755 {
756 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
757 "Malformed subject\n");
758 GNUNET_free (entity_attr);
759 GNUNET_SCHEDULER_add_now (&do_error, handle);
760 return;
761 }
762 if (GNUNET_OK !=
763 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
764 strlen (tmp),
765 &handle->subject_key)) {
766 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
767 "Malformed subject key\n");
768 GNUNET_free (entity_attr);
769 GNUNET_SCHEDULER_add_now (&do_error, handle);
770 return;
771 }
772
773 if (0 >= handle->rest_handle->data_size)
774 {
775 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
776 "Missing credentials\n");
777 GNUNET_SCHEDULER_add_now (&do_error, handle);
778 return;
779 }
780
781 struct GNUNET_JSON_Specification docspec[] = {
782 GNUNET_JSON_spec_jsonapi_document (&json_obj),
783 GNUNET_JSON_spec_end()
784 };
785 char term_data[handle->rest_handle->data_size+1];
786 term_data[handle->rest_handle->data_size] = '\0';
787 credential_count = 0;
788 GNUNET_memcpy (term_data,
789 handle->rest_handle->data,
790 handle->rest_handle->data_size);
791 data_js = json_loads (term_data,
792 JSON_DECODE_ANY,
793 &err);
794 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
795 NULL, NULL));
796 json_decref (data_js);
797 if (NULL == json_obj)
798 {
799 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
800 "Unable to parse JSONAPI Object from %s\n",
801 term_data);
802 GNUNET_SCHEDULER_add_now (&do_error, handle);
803 return;
804 }
805
806 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
807 GNUNET_assert (1 == resource_count);
808 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
809 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
810 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
811 {
812 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
813 "Resource not a credential!\n");
814 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
815 "Unable to parse JSONAPI Object from %s\n",
816 term_data);
817 GNUNET_JSONAPI_document_delete (json_obj);
818 GNUNET_SCHEDULER_add_now (&do_error, handle);
819 return;
820 }
821 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
822 GNUNET_REST_JSONAPI_CREDENTIAL);
823
824 GNUNET_assert (json_is_array (cred_json));
825
826 credential_count = json_array_size(cred_json);
827
828 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
829 for (i=0;i<credential_count;i++)
830 {
831 cred = json_to_credential (json_array_get (cred_json, i));
832 if (NULL == cred)
833 {
834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
835 "Unable to parse credential!\n");
836 continue;
837 }
838 GNUNET_memcpy (&credentials[i],
839 cred,
840 sizeof (struct GNUNET_CREDENTIAL_Credential));
841 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
842 GNUNET_free (cred);
843 }
844 GNUNET_JSONAPI_document_delete(json_obj);
845 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
846 &handle->issuer_key,
847 handle->issuer_attr,
848 &handle->subject_key,
849 credential_count,
850 credentials,
851 &handle_verify_response,
852 handle);
853 for (i=0;i<credential_count;i++)
854 GNUNET_free ((char*)credentials[i].issuer_attribute);
855
856}
857
858void
859send_cred_response (struct RequestHandle *handle,
860 struct GNUNET_CREDENTIAL_Credential *cred)
861{
862 struct MHD_Response *resp;
863 struct GNUNET_JSONAPI_Document *json_document;
864 struct GNUNET_JSONAPI_Resource *json_resource;
865 json_t *cred_obj;
866 char *result;
867 char *issuer;
868 char *subject;
869 char *signature;
870 char *id;
871
872 GNUNET_assert (NULL != cred);
873 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
874 if (NULL == issuer)
875 {
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
877 "Subject malformed\n");
878 return;
879 }
880 GNUNET_asprintf (&id,
881 "%s.%s",
882 issuer,
883 (char*)&cred[1]);
884 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
885 if (NULL == subject)
886 {
887 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
888 "Subject malformed\n");
889 return;
890 }
891 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
892 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
893 &signature);
894 json_document = GNUNET_JSONAPI_document_new ();
895 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
896 id);
897 GNUNET_free (id);
898 cred_obj = json_object();
899 json_object_set_new (cred_obj, "issuer", json_string (issuer));
900 json_object_set_new (cred_obj, "subject", json_string (subject));
901 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
902 json_object_set_new (cred_obj, "signature", json_string (signature));
903 GNUNET_JSONAPI_resource_add_attr (json_resource,
904 GNUNET_REST_JSONAPI_CREDENTIAL,
905 cred_obj);
906 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
907 GNUNET_JSONAPI_document_serialize (json_document, &result);
908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
909 "Result %s\n",
910 result);
911 json_decref (cred_obj);
912 GNUNET_JSONAPI_document_delete (json_document);
913 resp = GNUNET_REST_create_response (result);
914 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
915 GNUNET_free (result);
916 GNUNET_free (signature);
917 GNUNET_free (issuer);
918 GNUNET_free (subject);
919 cleanup_handle (handle);
920}
921
922void
923get_cred_issuer_cb (void *cls,
924 struct GNUNET_IDENTITY_Ego *ego,
925 void **ctx,
926 const char *name)
927{
928 struct RequestHandle *handle = cls;
929 struct GNUNET_TIME_Absolute etime_abs;
930 struct GNUNET_TIME_Relative etime_rel;
931 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
932 struct GNUNET_HashCode key;
933 struct GNUNET_CREDENTIAL_Credential *cred;
934 char* expiration_str;
935 char* tmp;
936
937 handle->id_op = NULL;
938
939 if (NULL == name)
940 {
941 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
942 "Issuer not configured!\n");
943 GNUNET_SCHEDULER_add_now (&do_error, handle);
944 return;
945 }
946
947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
948 "Connecting to credential service...\n");
949 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
951 "Connected\n");
952 if (NULL == handle->credential)
953 {
954 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
955 "Connecting to CREDENTIAL failed\n");
956 GNUNET_SCHEDULER_add_now (&do_error, handle);
957 return;
958 }
959 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
960 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
961 &key);
962 if ( GNUNET_NO ==
963 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
964 &key) )
965 {
966 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
967 "Missing expiration\n");
968 GNUNET_SCHEDULER_add_now (&do_error, handle);
969 return;
970 }
971 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
972 &key);
973 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
974 &etime_rel))
975 {
976 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
977 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
978 &etime_abs))
979 {
980 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
981 "Malformed expiration: %s\n", expiration_str);
982 GNUNET_SCHEDULER_add_now (&do_error, handle);
983 return;
984 }
985 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
986 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
987 &key);
988 if ( GNUNET_NO ==
989 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
990 &key) )
991 {
992 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
993 "Missing issuer attribute\n");
994 GNUNET_SCHEDULER_add_now (&do_error, handle);
995 return;
996 }
997 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
998 (handle->rest_handle->url_param_map,
999 &key));
1000 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
1001 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
1002 &key);
1003 if ( GNUNET_NO ==
1004 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
1005 &key) )
1006 {
1007 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1008 "Missing subject\n");
1009 GNUNET_SCHEDULER_add_now (&do_error, handle);
1010 return;
1011 }
1012 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1013 &key);
1014 if (NULL == tmp)
1015 {
1016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1017 "Malformed subject\n");
1018 GNUNET_SCHEDULER_add_now (&do_error, handle);
1019 return;
1020 }
1021 if (GNUNET_OK !=
1022 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1023 strlen (tmp),
1024 &handle->subject_key)) {
1025 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1026 "Malformed subject key\n");
1027 GNUNET_SCHEDULER_add_now (&do_error, handle);
1028 return;
1029 }
1030 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1031 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1032 &handle->subject_key,
1033 handle->issuer_attr,
1034 &etime_abs);
1035 if (NULL == cred)
1036 {
1037 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1038 "Failed to create credential\n");
1039 GNUNET_SCHEDULER_add_now (&do_error, handle);
1040 return;
1041 }
1042 send_cred_response (handle, cred);
1043}
1044
1045
1046static void
1047issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1048 const char* url,
1049 void *cls)
1050{
1051 struct RequestHandle *handle = cls;
1052
1053 handle->identity = GNUNET_IDENTITY_connect (cfg,
1054 NULL,
1055 NULL);
1056 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1057 "credential-issuer",
1058 &get_cred_issuer_cb,
1059 handle);
1060 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1061 &do_error,
1062 handle);
1063}
1064
1065/**
1066 * Handle rest request
1067 *
1068 * @param handle the lookup handle
1069 */
1070static void
1071options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1072 const char* url,
1073 void *cls)
1074{
1075 struct MHD_Response *resp;
1076 struct RequestHandle *handle = cls;
1077
1078 //For GNS, independent of path return all options
1079 resp = GNUNET_REST_create_response (NULL);
1080 MHD_add_response_header (resp,
1081 "Access-Control-Allow-Methods",
1082 MHD_HTTP_METHOD_GET);
1083 handle->proc (handle->proc_cls,
1084 resp,
1085 MHD_HTTP_OK);
1086 cleanup_handle (handle);
1087}
1088
1089
1090/**
1091 * Function processing the REST call
1092 *
1093 * @param method HTTP method
1094 * @param url URL of the HTTP request
1095 * @param data body of the HTTP request (optional)
1096 * @param data_size length of the body
1097 * @param proc callback function for the result
1098 * @param proc_cls closure for callback function
1099 * @return GNUNET_OK if request accepted
1100 */
1101static void
1102rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1103 GNUNET_REST_ResultProcessor proc,
1104 void *proc_cls)
1105{
1106 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1107 struct GNUNET_REST_RequestHandlerError err;
1108
1109 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1110 handle->proc_cls = proc_cls;
1111 handle->proc = proc;
1112 handle->rest_handle = conndata_handle;
1113
1114 static const struct GNUNET_REST_RequestHandler handlers[] = {
1115 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1116 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1117 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1118 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1119 GNUNET_REST_HANDLER_END
1120 };
1121
1122 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1123 handlers,
1124 &err,
1125 handle))
1126 {
1127 handle->response_code = err.error_code;
1128 GNUNET_SCHEDULER_add_now (&do_error, handle);
1129 }
1130}
1131
1132
1133/**
1134 * Entry point for the plugin.
1135 *
1136 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1137 * @return NULL on error, otherwise the plugin context
1138 */
1139void *
1140libgnunet_plugin_rest_credential_init (void *cls)
1141{
1142 static struct Plugin plugin;
1143 cfg = cls;
1144 struct GNUNET_REST_Plugin *api;
1145
1146 if (NULL != plugin.cfg)
1147 return NULL; /* can only initialize once! */
1148 memset (&plugin, 0, sizeof (struct Plugin));
1149 plugin.cfg = cfg;
1150 api = GNUNET_new (struct GNUNET_REST_Plugin);
1151 api->cls = &plugin;
1152 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1153 api->process_request = &rest_credential_process_request;
1154 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1155 _("GNS REST API initialized\n"));
1156 return api;
1157}
1158
1159
1160/**
1161 * Exit point from the plugin.
1162 *
1163 * @param cls the plugin context (as returned by "init")
1164 * @return always NULL
1165 */
1166void *
1167libgnunet_plugin_rest_credential_done (void *cls)
1168{
1169 struct GNUNET_REST_Plugin *api = cls;
1170 struct Plugin *plugin = api->cls;
1171
1172 plugin->cfg = NULL;
1173 GNUNET_free (api);
1174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1175 "GNS REST plugin is finished\n");
1176 return NULL;
1177}
1178
1179/* end of plugin_rest_gns.c */
diff --git a/src/credential/test_credential_collect.sh b/src/credential/test_credential_collect.sh
new file mode 100755
index 000000000..6c713063f
--- /dev/null
+++ b/src/credential/test_credential_collect.sh
@@ -0,0 +1,47 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26TEST_ATTR2="test2"
27gnunet-arm -s -c test_credential_lookup.conf
28gnunet-identity -C testissuer -c test_credential_lookup.conf
29gnunet-identity -C testsubject -c test_credential_lookup.conf
30SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
31ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
32#TODO1 Get credential and store it with subject (3)
33CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
34$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
35CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c test_credential_lookup.conf`
36$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
37CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste -d, -s`
38echo $CREDS
39RES=$?
40gnunet-arm -e -c test_credential_lookup.conf
41
42if test $? != 0
43then
44 echo "Error collecting..."
45 exit 1
46fi
47
diff --git a/src/credential/test_credential_collect_rest.sh b/src/credential/test_credential_collect_rest.sh
new file mode 100755
index 000000000..0b31f85bc
--- /dev/null
+++ b/src/credential/test_credential_collect_rest.sh
@@ -0,0 +1,90 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60# (5) GNUnet issues Alice the credential "developer"
61CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
62
63# Alice stores the credential under "mygnunetcreds"
64gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
65
66#TODO2 Add -z swich like in gnunet-gns
67#RES_CRED=`gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY -c test_credential_lookup.conf`
68
69gnunet-arm -i rest -c test_credential_lookup.conf
70
71sleep 5
72
73curl -v "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"
74
75#TODO cleanup properly
76gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
77gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
78gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
79gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
80echo "Stopping arm..."
81gnunet-arm -e -c test_credential_lookup.conf
82echo "Done"
83if [ "$RES_CRED" != "Failed." ]
84then
85 echo -e "${RES_CRED}"
86 exit 0
87else
88 echo "FAIL: Failed to verify credential $RES_CRED."
89 exit 1
90fi
diff --git a/src/credential/test_credential_defaults.conf b/src/credential/test_credential_defaults.conf
new file mode 100644
index 000000000..d157ddd43
--- /dev/null
+++ b/src/credential/test_credential_defaults.conf
@@ -0,0 +1,24 @@
1@INLINE@ ../../contrib/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-credential-testing/
5
6[namestore-sqlite]
7FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
8
9[namecache-sqlite]
10FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
11
12[identity]
13# Directory where we store information about our egos
14EGODIR = $GNUNET_TEST_HOME/identity/egos/
15
16[dhtcache]
17DATABASE = heap
18
19[transport]
20PLUGINS = tcp
21
22[transport-tcp]
23BINDTO = 127.0.0.1
24
diff --git a/src/credential/test_credential_issue.sh b/src/credential/test_credential_issue.sh
new file mode 100755
index 000000000..158d91c5b
--- /dev/null
+++ b/src/credential/test_credential_issue.sh
@@ -0,0 +1,44 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C testissuer -c test_credential_lookup.conf
28gnunet-identity -C testsubject -c test_credential_lookup.conf
29SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
30ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
31#TODO1 Get credential and store it with subject (3)
32CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
33STATUS=$?
34
35if test $? != 0
36then
37 echo "Error issuing..."
38 exit 1
39fi
40#Try import
41$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
42RES=$?
43gnunet-arm -e -c test_credential_lookup.conf
44exit $RES
diff --git a/src/credential/test_credential_issue_rest.sh b/src/credential/test_credential_issue_rest.sh
new file mode 100755
index 000000000..15cd55083
--- /dev/null
+++ b/src/credential/test_credential_issue_rest.sh
@@ -0,0 +1,53 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-arm -i gns
28gnunet-arm -i credential
29gnunet-arm -i identity
30gnunet-arm -i rest -c test_credential_lookup.conf
31
32gnunet-arm -I -c test_credential_lookup.conf
33gnunet-identity -C testissuer -c test_credential_lookup.conf
34gnunet-identity -C testsubject -c test_credential_lookup.conf
35gnunet-identity -s credential-issuer -e testissuer
36SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
37ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
38#TODO1 Get credential and store it with subject (3)
39sleep 5
40curl "localhost:7776/credential/issue?subject_key=$SUBJECT_KEY&attribute=$TEST_ATTR&expiration=1d"
41#CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
42STATUS=$?
43
44if test $? != 0
45then
46 echo "Error issuing..."
47 exit 1
48fi
49#Try import
50#$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
51RES=$?
52gnunet-arm -e -c test_credential_lookup.conf
53exit $RES
diff --git a/src/credential/test_credential_lookup.conf b/src/credential/test_credential_lookup.conf
new file mode 100644
index 000000000..3684063b1
--- /dev/null
+++ b/src/credential/test_credential_lookup.conf
@@ -0,0 +1,28 @@
1@INLINE@ test_credential_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-credential-peer-1/
5
6[dht]
7AUTOSTART = YES
8
9[transport]
10PLUGINS =
11
12[credential]
13AUTOSTART = YES
14PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
15
16[rest]
17PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
18
19[gns]
20#PREFIX = valgrind --leak-check=full --track-origins=yes
21AUTOSTART = YES
22AUTO_IMPORT_PKEY = YES
23MAX_PARALLEL_BACKGROUND_QUERIES = 10
24DEFAULT_LOOKUP_TIMEOUT = 15 s
25RECORD_PUT_INTERVAL = 1 h
26ZONE_PUBLISH_TIME_WINDOW = 1 h
27DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
28
diff --git a/src/credential/test_credential_verify.sh b/src/credential/test_credential_verify.sh
new file mode 100755
index 000000000..d042bcfe6
--- /dev/null
+++ b/src/credential/test_credential_verify.sh
@@ -0,0 +1,81 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
61
62echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf
63#TODO2 Add -z swich like in gnunet-gns
64gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf
65
66
67#TODO cleanup properly
68gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
69gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
70gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
71gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
72gnunet-arm -e -c test_credential_lookup.conf
73
74if [ "$RES_CRED" != "Failed." ]
75then
76 echo -e "${RES_CRED}"
77 exit 0
78else
79 echo "FAIL: Failed to verify credential $RES_CRED."
80 exit 1
81fi
diff --git a/src/credential/test_credential_verify_and.sh b/src/credential/test_credential_verify_and.sh
new file mode 100755
index 000000000..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..a8aae6ced
--- /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-provider/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 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 attr_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 = attr_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..046321807
--- /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-provider/identity_attribute.h
23 * @brief GNUnet Identity Provider library
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..0ff44d199
--- /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-provider/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..5c5ddaa57 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,50 @@ 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/credential/libgnunetcredential.la \
74 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
75 libgnunetidentityprovider.la \
45 $(top_builddir)/src/gns/libgnunetgns.la \ 76 $(top_builddir)/src/gns/libgnunetgns.la \
46 $(GN_LIBINTL) \ 77 $(GN_LIBINTL)
47 -ljansson
48 78
49libgnunetidentityprovider_la_SOURCES = \ 79libgnunetidentityprovider_la_SOURCES = \
50 identity_provider_api.c \ 80 identity_provider_api.c \
@@ -57,22 +87,37 @@ libgnunetidentityprovider_la_LDFLAGS = \
57 -version-info 0:0:0 87 -version-info 0:0:0
58 88
59libgnunet_plugin_rest_identity_provider_la_SOURCES = \ 89libgnunet_plugin_rest_identity_provider_la_SOURCES = \
60 plugin_rest_identity_provider.c 90 plugin_rest_identity_provider.c \
91 jwt.c
61libgnunet_plugin_rest_identity_provider_la_LIBADD = \ 92libgnunet_plugin_rest_identity_provider_la_LIBADD = \
62 $(top_builddir)/src/identity/libgnunetidentity.la \ 93 $(top_builddir)/src/identity/libgnunetidentity.la \
63 libgnunetidentityprovider.la \ 94 libgnunetidentityprovider.la \
64 $(top_builddir)/src/rest/libgnunetrest.la \ 95 $(top_builddir)/src/rest/libgnunetrest.la \
65 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ 96 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
97 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
66 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 98 $(top_builddir)/src/namestore/libgnunetnamestore.la \
67 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ 99 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
68 $(LTLIBINTL) -ljansson -lmicrohttpd 100 $(LTLIBINTL) -ljansson -lmicrohttpd
69libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \ 101libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \
70 $(GN_PLUGIN_LDFLAGS) 102 $(GN_PLUGIN_LDFLAGS)
71 103
72 104gnunet_idp_SOURCES = \
73gnunet_identity_token_SOURCES = \ 105 gnunet-idp.c
74 gnunet-identity-token.c 106gnunet_idp_LDADD = \
75gnunet_identity_token_LDADD = \
76 $(top_builddir)/src/util/libgnunetutil.la \ 107 $(top_builddir)/src/util/libgnunetutil.la \
77 -ljansson -lmicrohttpd \ 108 $(top_builddir)/src/namestore/libgnunetnamestore.la \
109 libgnunetidentityprovider.la \
110 $(top_builddir)/src/identity/libgnunetidentity.la \
111 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
78 $(GN_LIBINTL) 112 $(GN_LIBINTL)
113
114check_SCRIPTS = \
115 test_idp_attribute.sh \
116 test_idp_issue.sh \
117 test_idp_consume.sh \
118 test_idp_revoke.sh
119
120if ENABLE_TEST_RUN
121 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
122 TESTS = $(check_SCRIPTS)
123endif
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..a5c178aa5 100644
--- a/src/identity-provider/gnunet-service-identity-provider.c
+++ b/src/identity-provider/gnunet-service-identity-provider.c
@@ -30,12 +30,13 @@
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_credential_service.h"
33#include "gnunet_statistics_service.h" 34#include "gnunet_statistics_service.h"
34#include "gnunet_gns_service.h" 35#include "gnunet_gns_service.h"
36#include "gnunet_identity_provider_plugin.h"
37#include "gnunet_identity_attribute_lib.h"
35#include "gnunet_signatures.h" 38#include "gnunet_signatures.h"
36#include "identity_provider.h" 39#include "identity_provider.h"
37#include "identity_token.h"
38#include <inttypes.h>
39 40
40/** 41/**
41 * First pass state 42 * First pass state
@@ -58,24 +59,19 @@
58#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS 59#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
59 60
60/** 61/**
61 * Service state (to detect initial update pass) 62 * Identity handle
62 */
63static int state;
64
65/**
66 * Head of ego entry DLL
67 */ 63 */
68static struct EgoEntry *ego_head; 64static struct GNUNET_IDENTITY_Handle *identity_handle;
69 65
70/** 66/**
71 * Tail of ego entry DLL 67 * Database handle
72 */ 68 */
73static struct EgoEntry *ego_tail; 69static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
74 70
75/** 71/**
76 * Identity handle 72 * Name of DB plugin
77 */ 73 */
78static struct GNUNET_IDENTITY_Handle *identity_handle; 74static char *db_lib_name;
79 75
80/** 76/**
81 * Token expiration interval 77 * Token expiration interval
@@ -93,6 +89,16 @@ static struct GNUNET_NAMESTORE_Handle *ns_handle;
93static struct GNUNET_GNS_Handle *gns_handle; 89static struct GNUNET_GNS_Handle *gns_handle;
94 90
95/** 91/**
92 * Credential handle
93 */
94static struct GNUNET_CREDENTIAL_Handle *credential_handle;
95
96/**
97 * Stats handle
98 */
99static struct GNUNET_STATISTICS_Handle *stats_handle;
100
101/**
96 * Namestore qe 102 * Namestore qe
97 */ 103 */
98static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 104static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
@@ -112,11 +118,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task;
112 */ 118 */
113static struct GNUNET_SCHEDULER_Task *update_task; 119static struct GNUNET_SCHEDULER_Task *update_task;
114 120
115/**
116 * Timeout for next update pass
117 */
118static struct GNUNET_TIME_Relative min_rel_exp;
119
120 121
121/** 122/**
122 * Currently processed token 123 * Currently processed token
@@ -134,43 +135,260 @@ static char* label;
134static char* scopes; 135static char* scopes;
135 136
136/** 137/**
137 * Expiration for processed token 138 * Handle to the statistics service.
138 */ 139 */
139static uint64_t rd_exp; 140static struct GNUNET_STATISTICS_Handle *stats;
140 141
141/** 142/**
142 * ECDHE Privkey for processed token metadata 143 * Our configuration.
143 */ 144 */
144static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey; 145static const struct GNUNET_CONFIGURATION_Handle *cfg;
145 146
146/** 147/**
147 * Handle to the statistics service. 148 * An idp client
148 */ 149 */
149static struct GNUNET_STATISTICS_Handle *stats; 150struct IdpClient;
150 151
151/** 152/**
152 * Our configuration. 153 * A ticket iteration operation.
153 */ 154 */
154static const struct GNUNET_CONFIGURATION_Handle *cfg; 155struct TicketIteration
156{
157 /**
158 * DLL
159 */
160 struct TicketIteration *next;
161
162 /**
163 * DLL
164 */
165 struct TicketIteration *prev;
166
167 /**
168 * Client which intiated this zone iteration
169 */
170 struct IdpClient *client;
171
172 /**
173 * Key of the identity we are iterating over.
174 */
175 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
176
177 /**
178 * Identity is audience
179 */
180 uint32_t is_audience;
181
182 /**
183 * The operation id fot the iteration in the response for the client
184 */
185 uint32_t r_id;
186
187 /**
188 * Offset of the iteration used to address next result of the
189 * iteration in the store
190 *
191 * Initialy set to 0 in handle_iteration_start
192 * Incremented with by every call to handle_iteration_next
193 */
194 uint32_t offset;
195
196};
197
198
199
200/**
201 * Callback after an ABE bootstrap
202 *
203 * @param cls closure
204 * @param abe_key the ABE key that exists or was created
205 */
206typedef void
207(*AbeBootstrapResult) (void *cls,
208 struct GNUNET_CRYPTO_AbeMasterKey *abe_key);
155 209
156 210
157struct ExchangeHandle 211struct AbeBootstrapHandle
158{ 212{
213 /**
214 * Function to call when finished
215 */
216 AbeBootstrapResult proc;
159 217
160 /** 218 /**
161 * Client connection 219 * Callback closure
220 */
221 char *proc_cls;
222
223 /**
224 * Key of the zone we are iterating over.
225 */
226 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
227
228 /**
229 * Namestore Queue Entry
230 */
231 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
232
233 /**
234 * The issuer egos ABE master key
235 */
236 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
237};
238
239/**
240 * An attribute iteration operation.
241 */
242struct AttributeIterator
243{
244 /**
245 * Next element in the DLL
246 */
247 struct AttributeIterator *next;
248
249 /**
250 * Previous element in the DLL
251 */
252 struct AttributeIterator *prev;
253
254 /**
255 * IDP client which intiated this zone iteration
256 */
257 struct IdpClient *client;
258
259 /**
260 * Key of the zone we are iterating over.
261 */
262 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
263
264 /**
265 * The issuer egos ABE master key
266 */
267 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
268
269 /**
270 * Namestore iterator
271 */
272 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
273
274 /**
275 * The operation id fot the zone iteration in the response for the client
276 */
277 uint32_t request_id;
278
279};
280
281
282
283/**
284 * An idp client
285 */
286struct IdpClient
287{
288
289 /**
290 * The client
162 */ 291 */
163 struct GNUNET_SERVICE_Client *client; 292 struct GNUNET_SERVICE_Client *client;
164 293
165 /** 294 /**
166 * Ticket 295 * Message queue for transmission to @e client
296 */
297 struct GNUNET_MQ_Handle *mq;
298
299 /**
300 * Head of the DLL of
301 * Attribute iteration operations in
302 * progress initiated by this client
303 */
304 struct AttributeIterator *op_head;
305
306 /**
307 * Tail of the DLL of
308 * Attribute iteration operations
309 * in progress initiated by this client
310 */
311 struct AttributeIterator *op_tail;
312
313 /**
314 * Head of DLL of ticket iteration ops
315 */
316 struct TicketIteration *ticket_iter_head;
317
318 /**
319 * Tail of DLL of ticket iteration ops
320 */
321 struct TicketIteration *ticket_iter_tail;
322
323
324 /**
325 * Head of DLL of ticket revocation ops
326 */
327 struct TicketRevocationHandle *revocation_list_head;
328
329 /**
330 * Tail of DLL of ticket revocation ops
331 */
332 struct TicketRevocationHandle *revocation_list_tail;
333};
334
335
336
337struct AttributeStoreHandle
338{
339
340 /**
341 * Client connection
342 */
343 struct IdpClient *client;
344
345 /**
346 * Identity
347 */
348 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
349
350 /**
351 * Identity pubkey
352 */
353 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
354
355 /**
356 * The issuer egos ABE master key
357 */
358 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
359
360 /**
361 * QueueEntry
362 */
363 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
364
365 /**
366 * The attribute to store
367 */
368 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
369
370 /**
371 * request id
372 */
373 uint32_t r_id;
374};
375
376
377/* Prototype */
378struct ParallelLookup;
379
380struct ConsumeTicketHandle
381{
382
383 /**
384 * Client connection
167 */ 385 */
168 struct TokenTicket *ticket; 386 struct IdpClient *client;
169 387
170 /** 388 /**
171 * Token returned 389 * Ticket
172 */ 390 */
173 struct IdentityToken *token; 391 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
174 392
175 /** 393 /**
176 * LookupRequest 394 * LookupRequest
@@ -180,86 +398,173 @@ struct ExchangeHandle
180 /** 398 /**
181 * Audience Key 399 * Audience Key
182 */ 400 */
183 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey; 401 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
402
403 /**
404 * Audience Key
405 */
406 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
184 407
185 /** 408 /**
186 * Label to return 409 * Lookup DLL
187 */ 410 */
188 char *label; 411 struct ParallelLookup *parallel_lookups_head;
412
413 /**
414 * Lookup DLL
415 */
416 struct ParallelLookup *parallel_lookups_tail;
417
418 /**
419 * Kill task
420 */
421 struct GNUNET_SCHEDULER_Task *kill_task;
189 422
190 /** 423 /**
424 * The ABE key
425 */
426 struct GNUNET_CRYPTO_AbeKey *key;
427
428 /**
429 * Attributes
430 */
431 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
432
433 /**
434 * Lookup time
435 */
436 struct GNUNET_TIME_Absolute lookup_start_time;
437
438 /**
191 * request id 439 * request id
192 */ 440 */
193 uint32_t r_id; 441 uint32_t r_id;
194}; 442};
195 443
196struct IssueHandle 444/**
445 * Handle for a parallel GNS lookup job
446 */
447struct ParallelLookup
448{
449 /* DLL */
450 struct ParallelLookup *next;
451
452 /* DLL */
453 struct ParallelLookup *prev;
454
455 /* The GNS request */
456 struct GNUNET_GNS_LookupRequest *lookup_request;
457
458 /* The handle the return to */
459 struct ConsumeTicketHandle *handle;
460
461 /**
462 * Lookup time
463 */
464 struct GNUNET_TIME_Absolute lookup_start_time;
465
466 /* The label to look up */
467 char *label;
468};
469
470/**
471 * Ticket revocation request handle
472 */
473struct TicketRevocationHandle
197{ 474{
475 /**
476 * DLL
477 */
478 struct TicketRevocationHandle *next;
479
480 /**
481 * DLL
482 */
483 struct TicketRevocationHandle *prev;
198 484
199 /** 485 /**
200 * Client connection 486 * Client connection
201 */ 487 */
202 struct GNUNET_SERVICE_Client *client; 488 struct IdpClient *client;
489
490 /**
491 * Attributes to reissue
492 */
493 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
494
495 /**
496 * Attributes to revoke
497 */
498 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs;
203 499
204 /** 500 /**
205 * Issuer Key 501 * Issuer Key
206 */ 502 */
207 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key; 503 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
208 504
209 /** 505 /**
210 * Issue pubkey 506 * Ticket to issue
211 */ 507 */
212 struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey; 508 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
213 509
214 /** 510 /**
215 * Audience Key 511 * QueueEntry
216 */ 512 */
217 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 513 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
218 514
219 /** 515 /**
220 * Expiration 516 * Namestore iterator
221 */ 517 */
222 struct GNUNET_TIME_Absolute expiration; 518 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
223 519
224 /** 520 /**
225 * Scopes 521 * The ABE master key
226 */ 522 */
227 char *scopes; 523 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
228 524
229 /** 525 /**
230 * nonce 526 * Offset
231 */ 527 */
232 uint64_t nonce; 528 uint32_t offset;
233 529
234 /** 530 /**
235 * NS iterator 531 * request id
236 */ 532 */
237 struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 533 uint32_t r_id;
534};
535
536
537
538/**
539 * Ticket issue request handle
540 */
541struct TicketIssueHandle
542{
238 543
239 /** 544 /**
240 * Attribute map 545 * Client connection
241 */ 546 */
242 struct GNUNET_CONTAINER_MultiHashMap *attr_map; 547 struct IdpClient *client;
243 548
244 /** 549 /**
245 * Token 550 * Attributes to issue
246 */ 551 */
247 struct IdentityToken *token; 552 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
248 553
249 /** 554 /**
250 * Ticket 555 * Issuer Key
251 */ 556 */
252 struct TokenTicket *ticket; 557 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
253 558
254 /** 559 /**
255 * QueueEntry 560 * Ticket to issue
256 */ 561 */
257 struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 562 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
258 563
259 /** 564 /**
260 * The label the token is stored under 565 * QueueEntry
261 */ 566 */
262 char *label; 567 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
263 568
264 /** 569 /**
265 * request id 570 * request id
@@ -267,6 +572,7 @@ struct IssueHandle
267 uint32_t r_id; 572 uint32_t r_id;
268}; 573};
269 574
575
270/** 576/**
271 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format 577 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
272 * 578 *
@@ -293,988 +599,1362 @@ struct EgoEntry
293 */ 599 */
294 struct GNUNET_CONTAINER_MultiHashMap *attr_map; 600 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
295 601
296 /**
297 * Attributes are old and should be updated if GNUNET_YES
298 */
299 int attributes_dirty;
300}; 602};
301 603
302/** 604/**
303 * Continuation for token store call 605 * Cleanup task
606 */
607static void
608cleanup()
609{
610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
611 "Cleaning up\n");
612 if (NULL != stats)
613 {
614 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
615 stats = NULL;
616 }
617 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
618 TKT_database));
619 GNUNET_free (db_lib_name);
620 db_lib_name = NULL;
621 if (NULL != timeout_task)
622 GNUNET_SCHEDULER_cancel (timeout_task);
623 if (NULL != update_task)
624 GNUNET_SCHEDULER_cancel (update_task);
625 if (NULL != identity_handle)
626 GNUNET_IDENTITY_disconnect (identity_handle);
627 if (NULL != gns_handle)
628 GNUNET_GNS_disconnect (gns_handle);
629 if (NULL != credential_handle)
630 GNUNET_CREDENTIAL_disconnect (credential_handle);
631 if (NULL != ns_it)
632 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
633 if (NULL != ns_qe)
634 GNUNET_NAMESTORE_cancel (ns_qe);
635 if (NULL != ns_handle)
636 GNUNET_NAMESTORE_disconnect (ns_handle);
637 if (NULL != stats_handle)
638 GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO);
639 if (NULL != token)
640 GNUNET_free (token);
641 if (NULL != label)
642 GNUNET_free (label);
643
644}
645
646/**
647 * Shutdown task
304 * 648 *
305 * @param cls NULL 649 * @param cls NULL
306 * @param success error code 650 * @param tc task context
307 * @param emsg error message 651 */
652static void
653do_shutdown (void *cls)
654{
655 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
656 "Shutting down...\n");
657 cleanup();
658}
659
660/**
661 * Finished storing newly bootstrapped ABE key
308 */ 662 */
309static void 663static void
310store_token_cont (void *cls, 664bootstrap_store_cont (void *cls,
311 int32_t success, 665 int32_t success,
312 const char *emsg) 666 const char *emsg)
313{ 667{
314 ns_qe = NULL; 668 struct AbeBootstrapHandle *abh = cls;
315 if (GNUNET_SYSERR == success) 669 if (GNUNET_SYSERR == success)
316 { 670 {
317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 671 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
318 "Failed to update token: %s\n", 672 "Failed to bootstrap ABE master %s\n",
319 emsg); 673 emsg);
674 abh->proc (abh->proc_cls, NULL);
675 GNUNET_free (abh->abe_key);
676 GNUNET_free (abh);
320 return; 677 return;
321 } 678 }
322 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 679 abh->proc (abh->proc_cls, abh->abe_key);
680 GNUNET_free (abh);
323} 681}
324 682
683/**
684 * Generates and stores a new ABE key
685 */
686static void
687bootstrap_store_task (void *cls)
688{
689 struct AbeBootstrapHandle *abh = cls;
690 struct GNUNET_GNSRECORD_Data rd[1];
691 char *key;
692
693 rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
694 (void**)&key);
695 rd[0].data = key;
696 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
697 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
698 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
699 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
700 &abh->identity,
701 "+",
702 1,
703 rd,
704 &bootstrap_store_cont,
705 abh);
706 GNUNET_free (key);
707}
325 708
326/** 709/**
327 * This function updates the old token with new attributes, 710 * Error checking for ABE master
328 * removes deleted attributes and expiration times.
329 *
330 * @param cls the ego entry
331 */ 711 */
332static void 712static void
333handle_token_update (void *cls) 713bootstrap_abe_error (void *cls)
334{ 714{
335 char *token_metadata; 715 struct AbeBootstrapHandle *abh = cls;
336 char *write_ptr; 716 GNUNET_free (abh);
337 char *enc_token_str; 717 abh->proc (abh->proc_cls, NULL);
338 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 718 GNUNET_free (abh);
339 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 719}
340 struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey;
341 struct EgoEntry *ego_entry = cls;
342 struct GNUNET_GNSRECORD_Data token_record[2];
343 struct GNUNET_HashCode key_hash;
344 struct GNUNET_TIME_Relative token_rel_exp;
345 struct GNUNET_TIME_Relative token_ttl;
346 struct GNUNET_TIME_Absolute token_exp;
347 struct GNUNET_TIME_Absolute token_nbf;
348 struct GNUNET_TIME_Absolute new_exp;
349 struct GNUNET_TIME_Absolute new_iat;
350 struct GNUNET_TIME_Absolute new_nbf;
351 struct IdentityToken *new_token;
352 struct TokenAttr *cur_value;
353 struct TokenAttr *attr;
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 720
384 token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp); 721
385 if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us) 722/**
386 { 723 * Handle ABE lookup in namestore
387 //This token is not yet expired! Save and skip 724 */
388 if (min_rel_exp.rel_value_us > token_ttl.rel_value_us) 725static void
389 { 726bootstrap_abe_result (void *cls,
390 min_rel_exp = token_ttl; 727 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
391 } 728 const char *label,
392 GNUNET_free (token); 729 unsigned int rd_count,
393 token = NULL; 730 const struct GNUNET_GNSRECORD_Data *rd)
394 GNUNET_free (label); 731{
395 label = NULL; 732 struct AbeBootstrapHandle *abh = cls;
396 GNUNET_free (scopes); 733 struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
397 scopes = NULL; 734 int i;
398 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 735
736 for (i=0;i<rd_count;i++) {
737 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
738 continue;
739 abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key (rd[i].data,
740 rd[i].data_size);
741 abh->proc (abh->proc_cls, abe_key);
742 GNUNET_free (abh);
399 return; 743 return;
400 } 744 }
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 745
402 "Token is expired. Create a new one\n"); 746 //No ABE master found, bootstrapping...
403 new_token = token_create (&pub_key, 747 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
404 &token->aud_key); 748 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
405 new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp); 749}
406 new_nbf = GNUNET_TIME_absolute_get (); 750
407 new_iat = new_nbf; 751/**
408 for (attr = token->attr_head; NULL != attr; attr = attr->next) 752 * Bootstrap ABE master if it does not yet exists.
753 * Will call the AbeBootstrapResult processor when done.
754 * will always recreate the ABE key of GNUNET_YES == recreate
755 */
756static void
757bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
758 AbeBootstrapResult proc,
759 void* cls,
760 int recreate)
761{
762 struct AbeBootstrapHandle *abh;
763
764 abh = GNUNET_new (struct AbeBootstrapHandle);
765 abh->proc = proc;
766 abh->proc_cls = cls;
767 abh->identity = *identity;
768 if (GNUNET_YES == recreate)
409 { 769 {
410 if (0 == strcmp (attr->name, "exp")) 770 abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
411 { 771 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
412 token_add_attr_int (new_token, attr->name, new_exp.abs_value_us); 772 } else {
413 } 773 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
414 else if (0 == strcmp (attr->name, "nbf")) 774 identity,
415 { 775 "+",
416 token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us); 776 &bootstrap_abe_error,
417 } 777 abh,
418 else if (0 == strcmp (attr->name, "iat")) 778 &bootstrap_abe_result,
419 { 779 abh);
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 } 780 }
452
453 // reassemble and set
454 GNUNET_assert (token_serialize (new_token,
455 priv_key,
456 &new_ecdhe_privkey,
457 &enc_token_str));
458
459 token_record[0].data = enc_token_str;
460 token_record[0].data_size = strlen (enc_token_str) + 1;
461 token_record[0].expiration_time = rd_exp; //Old expiration time
462 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
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} 781}
500 782
501 783
784
785static int
786create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
787 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
788 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
789{
790 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
791
792 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
793 &new_key_hash_str);
794 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
795 static const char ctx_key[] = "gnuid-aes-ctx-key";
796 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
797 new_key_hash, sizeof (struct GNUNET_HashCode),
798 ctx_key, strlen (ctx_key),
799 NULL, 0);
800 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
801 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
802 new_key_hash, sizeof (struct GNUNET_HashCode),
803 ctx_iv, strlen (ctx_iv),
804 NULL, 0);
805 return GNUNET_OK;
806}
807
502static void 808static void
503update_identities(void *cls); 809cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
810{
811 if (NULL != handle->attrs)
812 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
813 if (NULL != handle->ns_qe)
814 GNUNET_NAMESTORE_cancel (handle->ns_qe);
815 GNUNET_free (handle);
816}
504 817
505 818
506/** 819static void
507 * 820send_ticket_result (struct IdpClient *client,
508 * Cleanup attr_map 821 uint32_t r_id,
509 * 822 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
510 * @param cls NULL 823 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
511 * @param key the key 824{
512 * @param value the json_t attribute value 825 struct TicketResultMessage *irm;
513 * @return #GNUNET_YES 826 struct GNUNET_MQ_Envelope *env;
514 */ 827 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
515static int 828
516clear_ego_attrs (void *cls, 829 /* store ticket in DB */
517 const struct GNUNET_HashCode *key, 830 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
518 void *value) 831 ticket,
519{ 832 attrs))
520 struct TokenAttr *attr = value;
521 struct TokenAttrValue *val;
522 struct TokenAttrValue *tmp_val;
523 for (val = attr->val_head; NULL != val;)
524 { 833 {
525 tmp_val = val->next; 834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
526 GNUNET_CONTAINER_DLL_remove (attr->val_head, 835 "Unable to store ticket after issue\n");
527 attr->val_tail, 836 GNUNET_break (0);
528 val);
529 GNUNET_free (val->value);
530 GNUNET_free (val);
531 val = tmp_val;
532 } 837 }
533 GNUNET_free (attr->name);
534 GNUNET_free (attr);
535 838
536 return GNUNET_YES; 839 env = GNUNET_MQ_msg_extra (irm,
840 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
841 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
842 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
843 *ticket_buf = *ticket;
844 irm->id = htonl (r_id);
845 GNUNET_MQ_send (client->mq,
846 env);
537} 847}
538 848
539
540static void 849static void
541token_collect_error_cb (void *cls) 850store_ticket_issue_cont (void *cls,
851 int32_t success,
852 const char *emsg)
542{ 853{
543 struct EgoEntry *ego_entry = cls; 854 struct TicketIssueHandle *handle = cls;
855
856 handle->ns_qe = NULL;
857 if (GNUNET_SYSERR == success)
858 {
859 cleanup_ticket_issue_handle (handle);
860 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
861 "Unknown Error\n");
862 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
863 return;
864 }
865 send_ticket_result (handle->client,
866 handle->r_id,
867 &handle->ticket,
868 handle->attrs);
869 cleanup_ticket_issue_handle (handle);
870}
871
872
873
874int
875serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
876 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
877 const struct GNUNET_CRYPTO_AbeKey *rp_key,
878 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
879 char **result)
880{
881 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
882 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
883 char *enc_keyinfo;
884 char *serialized_key;
885 char *buf;
886 char *write_ptr;
887 char attrs_str_len;
888 ssize_t size;
889
890 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
891 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
892 struct GNUNET_HashCode new_key_hash;
893 ssize_t enc_size;
894
895 size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
896 (void**)&serialized_key);
897 attrs_str_len = 0;
898 for (le = attrs->list_head; NULL != le; le = le->next) {
899 attrs_str_len += strlen (le->claim->name) + 1;
900 }
901 buf = GNUNET_malloc (attrs_str_len + size);
902 write_ptr = buf;
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904 "Writing attributes\n");
905 for (le = attrs->list_head; NULL != le; le = le->next) {
906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
907 "%s\n", le->claim->name);
544 908
545 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
546 ">>> Updating Ego failed!\n");
547 //Clear attribute map for ego
548 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
549 &clear_ego_attrs,
550 ego_entry);
551 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
552 update_task = GNUNET_SCHEDULER_add_now (&update_identities,
553 ego_entry->next);
554 909
910 GNUNET_memcpy (write_ptr,
911 le->claim->name,
912 strlen (le->claim->name));
913 write_ptr[strlen (le->claim->name)] = ',';
914 write_ptr += strlen (le->claim->name) + 1;
915 }
916 write_ptr--;
917 write_ptr[0] = '\0'; //replace last , with a 0-terminator
918 write_ptr++;
919 GNUNET_memcpy (write_ptr,
920 serialized_key,
921 size);
922 GNUNET_free (serialized_key);
923 // ECDH keypair E = eG
924 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
925 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
926 &ecdh_pubkey);
927 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
928 // Derived key K = H(eB)
929 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
930 &ticket->audience,
931 &new_key_hash));
932 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
933 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
934 size + attrs_str_len,
935 &skey, &iv,
936 enc_keyinfo);
937 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
938 enc_size);
939 GNUNET_memcpy (*result,
940 &ecdh_pubkey,
941 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
942 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
943 enc_keyinfo,
944 enc_size);
945 GNUNET_free (enc_keyinfo);
946 GNUNET_free (buf);
947 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
555} 948}
556 949
557 950
951
558static void 952static void
559token_collect_finished_cb (void *cls) 953issue_ticket_after_abe_bootstrap (void *cls,
954 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
560{ 955{
561 struct EgoEntry *ego_entry = cls; 956 struct TicketIssueHandle *ih = cls;
957 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
958 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
959 struct GNUNET_GNSRECORD_Data code_record[1];
960 struct GNUNET_CRYPTO_AbeKey *rp_key;
961 char *code_record_data;
962 char **attrs;
963 char *label;
964 char *policy;
965 int attrs_len;
966 int i;
967 size_t code_record_len;
562 968
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 969 //Create new ABE key for RP
564 ">>> Updating Ego finished\n"); 970 attrs_len = 0;
565 //Clear attribute map for ego 971 for (le = ih->attrs->list_head; NULL != le; le = le->next)
566 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, 972 attrs_len++;
567 &clear_ego_attrs, 973 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
568 ego_entry); 974 i = 0;
569 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); 975 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
570 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 976 GNUNET_asprintf (&policy, "%s_%lu",
571 ego_entry->next); 977 le->claim->name,
978 le->claim->version);
979 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
980 "Adding attribute to key: %s\n",
981 policy);
982 attrs[i] = policy;
983 i++;
984 }
985 attrs[i] = NULL;
986 rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
987 attrs);
988
989 //TODO review this wireformat
990 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
991 ih->attrs,
992 rp_key,
993 &ecdhe_privkey,
994 &code_record_data);
995 code_record[0].data = code_record_data;
996 code_record[0].data_size = code_record_len;
997 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
998 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
999 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1000
1001 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
1002 sizeof (uint64_t));
1003 //Publish record
1004 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1005 &ih->identity,
1006 label,
1007 1,
1008 code_record,
1009 &store_ticket_issue_cont,
1010 ih);
1011 //for (; i > 0; i--)
1012 // GNUNET_free (attrs[i-1]);
1013 GNUNET_free (ecdhe_privkey);
1014 GNUNET_free (label);
1015 GNUNET_free (attrs);
1016 GNUNET_free (code_record_data);
1017 GNUNET_CRYPTO_cpabe_delete_key (rp_key,
1018 GNUNET_YES);
1019 GNUNET_CRYPTO_cpabe_delete_master_key (abe_key);
572} 1020}
573 1021
574 1022
575/** 1023/**
1024 * Checks a ticket issue message
576 * 1025 *
577 * Update all ID_TOKEN records for an identity and store them 1026 * @param cls client sending the message
578 * 1027 * @param im message of type `struct TicketIssueMessage`
579 * @param cls the identity entry 1028 * @return #GNUNET_OK if @a im is well-formed
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 */ 1029 */
585static void 1030static int
586token_collect (void *cls, 1031check_issue_ticket_message(void *cls,
587 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1032 const struct IssueTicketMessage *im)
588 const char *lbl, 1033{
589 unsigned int rd_count, 1034 uint16_t size;
590 const struct GNUNET_GNSRECORD_Data *rd)
591{
592 struct EgoEntry *ego_entry = cls;
593 const struct GNUNET_GNSRECORD_Data *token_record;
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 {
601 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
602 return;
603 }
604 1035
605 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 1036 size = ntohs (im->header.size);
606 { 1037 if (size <= sizeof (struct IssueTicketMessage))
607 token_metadata_record = &rd[0];
608 token_record = &rd[1];
609 }
610 else
611 {
612 token_record = &rd[0];
613 token_metadata_record = &rd[1];
614 }
615 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
616 {
617 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
618 return;
619 }
620 if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
621 { 1038 {
622 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1039 GNUNET_break (0);
623 return; 1040 return GNUNET_SYSERR;
624 } 1041 }
1042 return GNUNET_OK;
1043}
1044
625 1045
626 //Get metadata and decrypt token 1046/**
627 priv_key = (struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data; 1047 *
628 ecdhe_privkey = *priv_key; 1048 * Handler for ticket issue message
629 aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&priv_key[1]; 1049 *
630 scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 1050 * @param cls unused
1051 * @param client who sent the message
1052 * @param message the message
1053 */
1054static void
1055handle_issue_ticket_message (void *cls,
1056 const struct IssueTicketMessage *im)
1057{
1058 struct TicketIssueHandle *ih;
1059 struct IdpClient *idp = cls;
1060 size_t attrs_len;
1061
1062 ih = GNUNET_new (struct TicketIssueHandle);
1063 attrs_len = ntohs (im->attr_len);
1064 ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
1065 ih->r_id = ntohl (im->id);
1066 ih->client = idp;
1067 ih->identity = im->identity;
1068 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1069 &ih->ticket.identity);
1070 ih->ticket.audience = im->rp;
1071 ih->ticket.rnd =
1072 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1073 UINT64_MAX);
1074 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1075 GNUNET_SERVICE_client_continue (idp->client);
631 1076
632 token_parse2 (token_record->data, 1077}
633 &ecdhe_privkey,
634 aud_key,
635 &token);
636 1078
637 label = GNUNET_strdup (lbl); 1079/**********************************************************
638 rd_exp = token_record->expiration_time; 1080 * Revocation
1081 **********************************************************/
639 1082
640 GNUNET_SCHEDULER_add_now (&handle_token_update, 1083/**
641 ego_entry); 1084 * Cleanup revoke handle
1085 */
1086static void
1087cleanup_revoke_ticket_handle (struct TicketRevocationHandle *handle)
1088{
1089 if (NULL != handle->attrs)
1090 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
1091 if (NULL != handle->rvk_attrs)
1092 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->rvk_attrs);
1093 if (NULL != handle->abe_key)
1094 GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key);
1095 if (NULL != handle->ns_qe)
1096 GNUNET_NAMESTORE_cancel (handle->ns_qe);
1097 if (NULL != handle->ns_it)
1098 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
1099 GNUNET_free (handle);
642} 1100}
643 1101
644 1102
1103/**
1104 * Send revocation result
1105 */
645static void 1106static void
646attribute_collect_error_cb (void *cls) 1107send_revocation_finished (struct TicketRevocationHandle *rh,
1108 uint32_t success)
647{ 1109{
648 struct EgoEntry *ego_entry = cls; 1110 struct GNUNET_MQ_Envelope *env;
1111 struct RevokeTicketResultMessage *trm;
649 1112
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1113 env = GNUNET_MQ_msg (trm,
651 ">>> Updating Attributes failed!\n"); 1114 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
652 ego_entry->attributes_dirty = GNUNET_NO; 1115 trm->id = htonl (rh->r_id);
653 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1116 trm->success = htonl (success);
654 ego_entry); 1117 GNUNET_MQ_send (rh->client->mq,
1118 env);
1119 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1120 rh->client->revocation_list_tail,
1121 rh);
655} 1122}
656 1123
657 1124
1125/**
1126 * Process ticket from database
1127 *
1128 * @param cls struct TicketIterationProcResult
1129 * @param ticket the ticket
1130 * @param attrs the attributes
1131 */
1132static void
1133ticket_reissue_proc (void *cls,
1134 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1135 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
1136
658static void 1137static void
659attribute_collect_finished_cb (void *cls) 1138revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1139
1140
1141static void reissue_next (void *cls)
660{ 1142{
661 struct EgoEntry *ego_entry = cls; 1143 struct TicketRevocationHandle *rh = cls;
1144 revocation_reissue_tickets (rh);
1145}
662 1146
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1147
664 ">>> Updating Attributes finished\n"); 1148static void
665 ego_entry->attributes_dirty = GNUNET_NO; 1149reissue_ticket_cont (void *cls,
666 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1150 int32_t success,
667 ego_entry); 1151 const char *emsg)
1152{
1153 struct TicketRevocationHandle *rh = cls;
1154
1155 rh->ns_qe = NULL;
1156 if (GNUNET_SYSERR == success)
1157 {
1158 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1159 "Unknown Error\n");
1160 send_revocation_finished (rh, GNUNET_SYSERR);
1161 cleanup_revoke_ticket_handle (rh);
1162 return;
1163 }
1164 rh->offset++;
1165 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
668} 1166}
669 1167
670 1168
671/** 1169/**
1170 * Process ticket from database
672 * 1171 *
673 * Collect all ID_ATTR records for an identity and store them 1172 * @param cls struct TicketIterationProcResult
674 * 1173 * @param ticket the ticket
675 * @param cls the identity entry 1174 * @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 */ 1175 */
682static void 1176static void
683attribute_collect (void *cls, 1177ticket_reissue_proc (void *cls,
684 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1178 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
685 const char *lbl, 1179 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
686 unsigned int rd_count, 1180{
687 const struct GNUNET_GNSRECORD_Data *rd) 1181 struct TicketRevocationHandle *rh = cls;
688{ 1182 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
689 struct EgoEntry *ego_entry = cls; 1183 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover;
690 struct GNUNET_HashCode key; 1184 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
691 struct TokenAttr *attr; 1185 struct GNUNET_GNSRECORD_Data code_record[1];
692 struct TokenAttrValue *val; 1186 struct GNUNET_CRYPTO_AbeKey *rp_key;
693 char *val_str; 1187 char *code_record_data;
1188 char **attr_arr;
1189 char *label;
1190 char *policy;
1191 int attrs_len;
694 int i; 1192 int i;
1193 int reissue_ticket;
1194 size_t code_record_len;
1195
695 1196
696 if (0 == rd_count) 1197 if (NULL == ticket)
697 { 1198 {
698 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1200 "Iteration done\n");
699 return; 1201 return;
700 } 1202 }
701 GNUNET_CRYPTO_hash (lbl, 1203
702 strlen (lbl), 1204 if (0 == memcmp (&ticket->audience,
703 &key); 1205 &rh->ticket.audience,
704 if (1 == rd_count) 1206 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
705 { 1207 {
706 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 { 1209 "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 1210
725 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1211 rh->offset++;
1212 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
726 return; 1213 return;
727 } 1214 }
728 1215
729 attr = GNUNET_malloc (sizeof (struct TokenAttr)); 1216 /*
730 attr->name = GNUNET_strdup (lbl); 1217 * Check if any attribute of this ticket intersects with a rollover attribute
731 for (i = 0; i < rd_count; i++) 1218 */
1219 reissue_ticket = GNUNET_NO;
1220 for (le = attrs->list_head; NULL != le; le = le->next)
732 { 1221 {
733 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1222 for (le_rollover = rh->rvk_attrs->list_head;
1223 NULL != le_rollover;
1224 le_rollover = le_rollover->next)
734 { 1225 {
735 val_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, 1226 if (0 == strcmp (le_rollover->claim->name,
736 rd[i].data, 1227 le->claim->name))
737 rd[i].data_size); 1228 {
738 val = GNUNET_malloc (sizeof (struct TokenAttrValue)); 1229 reissue_ticket = GNUNET_YES;
739 val->value = val_str; 1230 le->claim->version = le_rollover->claim->version;
740 GNUNET_CONTAINER_DLL_insert (attr->val_head, 1231 }
741 attr->val_tail,
742 val);
743 } 1232 }
744 } 1233 }
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 1234
765 update_task = NULL; 1235 if (GNUNET_NO == reissue_ticket)
766 if (NULL == next_ego)
767 { 1236 {
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, 1237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
771 ">>> Finished. Rescheduling in %"SCNu64"\n", 1238 "Skipping ticket.\n");
772 min_rel_exp.rel_value_us); 1239
773 ns_it = NULL; 1240 rh->offset++;
774 //finished -> reschedule 1241 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
775 update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, 1242
776 &update_identities, 1243
777 ego_head);
778 min_rel_exp.rel_value_us = 0;
779 return; 1244 return;
780 } 1245 }
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 1246
1247 //Create new ABE key for RP
1248 attrs_len = 0;
1249
1250 /* If this is the RP we want to revoke attributes of, the do so */
1251
1252 for (le = attrs->list_head; NULL != le; le = le->next)
1253 attrs_len++;
1254 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1255 i = 0;
1256 for (le = attrs->list_head; NULL != le; le = le->next) {
1257 GNUNET_asprintf (&policy, "%s_%lu",
1258 le->claim->name,
1259 le->claim->version);
1260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1261 "Recreating key with %s\n", policy);
1262 attr_arr[i] = policy;
1263 i++;
1264 }
1265 attr_arr[i] = NULL;
1266 rp_key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
1267 attr_arr);
1268
1269 //TODO review this wireformat
1270 code_record_len = serialize_abe_keyinfo2 (ticket,
1271 attrs,
1272 rp_key,
1273 &ecdhe_privkey,
1274 &code_record_data);
1275 code_record[0].data = code_record_data;
1276 code_record[0].data_size = code_record_len;
1277 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1278 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1279 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1280
1281 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1282 sizeof (uint64_t));
1283 //Publish record
1284 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1285 &rh->identity,
1286 label,
1287 1,
1288 code_record,
1289 &reissue_ticket_cont,
1290 rh);
1291 //for (; i > 0; i--)
1292 // GNUNET_free (attr_arr[i-1]);
1293 GNUNET_free (ecdhe_privkey);
1294 GNUNET_free (label);
1295 GNUNET_free (attr_arr);
1296 GNUNET_free (code_record_data);
1297 GNUNET_CRYPTO_cpabe_delete_key (rp_key, GNUNET_YES);
1298}
1299
1300
1301/* Prototype for below function */
1302static void
1303attr_reenc_cont (void *cls,
1304 int32_t success,
1305 const char *emsg);
1306
1307static void
1308revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1309{
1310 int ret;
1311 /* Done, issue new keys */
1312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1313 "Revocation Phase III: Reissuing Tickets\n");
1314 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1315 &rh->ticket.identity,
1316 GNUNET_NO,
1317 rh->offset,
1318 &ticket_reissue_proc,
1319 rh)))
1320 {
1321 GNUNET_break (0);
794 } 1322 }
795 else 1323 if (GNUNET_NO == ret)
796 { 1324 {
797 //Ego will be dirty next time 1325 send_revocation_finished (rh, GNUNET_OK);
798 next_ego->attributes_dirty = GNUNET_YES; 1326 cleanup_revoke_ticket_handle (rh);
799 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, 1327 return;
800 priv_key,
801 &token_collect_error_cb,
802 next_ego,
803 &token_collect,
804 next_ego,
805 &token_collect_finished_cb,
806 next_ego);
807 } 1328 }
808} 1329}
809 1330
810
811/** 1331/**
812 * Function called initially to start update task 1332 * Revoke next attribte by reencryption with
1333 * new ABE master
813 */ 1334 */
814static void 1335static void
815init_cont () 1336reenc_next_attribute (struct TicketRevocationHandle *rh)
816{ 1337{
817 GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n"); 1338 struct GNUNET_GNSRECORD_Data rd[1];
818 //Initially iterate all itenties and refresh all tokens 1339 char* buf;
819 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1340 char* enc_buf;
820 ego_head); 1341 size_t enc_size;
1342 char* rd_buf;
1343 size_t buf_size;
1344 char* policy;
1345 uint32_t attr_ver;
1346
1347 if (NULL == rh->attrs->list_head)
1348 {
1349 revocation_reissue_tickets (rh);
1350 return;
1351 }
1352 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1353 buf = GNUNET_malloc (buf_size);
1354 GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1355 buf);
1356 rh->attrs->list_head->claim->version++;
1357 GNUNET_asprintf (&policy, "%s_%lu",
1358 rh->attrs->list_head->claim->name,
1359 rh->attrs->list_head->claim->version);
1360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1361 "Encrypting with policy %s\n", policy);
1362 /**
1363 * Encrypt the attribute value and store in namestore
1364 */
1365 enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1366 buf_size,
1367 policy, //Policy
1368 rh->abe_key,
1369 (void**)&enc_buf);
1370 GNUNET_free (buf);
1371 GNUNET_free (policy);
1372 rd[0].data_size = enc_size + sizeof (uint32_t);
1373 rd_buf = GNUNET_malloc (rd[0].data_size);
1374 attr_ver = htonl (rh->attrs->list_head->claim->version);
1375 GNUNET_memcpy (rd_buf,
1376 &attr_ver,
1377 sizeof (uint32_t));
1378 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1379 enc_buf,
1380 enc_size);
1381 rd[0].data = rd_buf;
1382 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1383 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1384 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1385 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1386 &rh->identity,
1387 rh->attrs->list_head->claim->name,
1388 1,
1389 rd,
1390 &attr_reenc_cont,
1391 rh);
1392 GNUNET_free (enc_buf);
1393 GNUNET_free (rd_buf);
821} 1394}
822 1395
823
824/** 1396/**
825 * Initial ego collection function. 1397 * Namestore callback after revoked attribute
826 * 1398 * is stored
827 * @param cls NULL
828 * @param ego ego
829 * @param ctx context
830 * @param identifier ego name
831 */ 1399 */
832static void 1400static void
833list_ego (void *cls, 1401attr_reenc_cont (void *cls,
834 struct GNUNET_IDENTITY_Ego *ego, 1402 int32_t success,
835 void **ctx, 1403 const char *emsg)
836 const char *identifier)
837{ 1404{
838 struct EgoEntry *new_entry; 1405 struct TicketRevocationHandle *rh = cls;
839 if ((NULL == ego) && (STATE_INIT == state)) 1406 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
1407
1408 if (GNUNET_SYSERR == success)
840 { 1409 {
841 state = STATE_POST_INIT; 1410 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
842 init_cont (); 1411 "Failed to reencrypt attribute %s\n",
1412 emsg);
1413 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
843 return; 1414 return;
844 } 1415 }
845 if (STATE_INIT == state) { 1416 if (NULL == rh->attrs->list_head)
846 new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); 1417 {
847 new_entry->ego = ego; 1418 revocation_reissue_tickets (rh);
848 new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5, 1419 return;
849 GNUNET_NO);
850 new_entry->attributes_dirty = GNUNET_YES;
851 GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
852 } 1420 }
1421 le = rh->attrs->list_head;
1422 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1423 rh->attrs->list_tail,
1424 le);
1425 GNUNET_assert (NULL != rh->rvk_attrs);
1426 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1427 rh->rvk_attrs->list_tail,
1428 le);
1429
1430
1431 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1432 "Re-encrypting next attribute\n");
1433 reenc_next_attribute (rh);
853} 1434}
854 1435
855/** 1436
856 * Cleanup task
857 */
858static void 1437static void
859cleanup() 1438process_attributes_to_update (void *cls,
1439 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1440 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
860{ 1441{
861 struct EgoEntry *ego_entry; 1442 struct TicketRevocationHandle *rh = cls;
862 struct EgoEntry *ego_tmp;
863 1443
1444 rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs);
864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
865 "Cleaning up\n"); 1446 "Revocation Phase I: Collecting attributes\n");
866 if (NULL != stats) 1447 /* Reencrypt all attributes with new key */
1448 if (NULL == rh->attrs->list_head)
867 { 1449 {
868 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 1450 /* No attributes to reencrypt */
869 stats = NULL; 1451 send_revocation_finished (rh, GNUNET_OK);
1452 cleanup_revoke_ticket_handle (rh);
1453 return;
1454 } else {
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1456 "Revocation Phase II: Re-encrypting attributes\n");
1457 reenc_next_attribute (rh);
870 } 1458 }
871 1459
872 if (NULL != timeout_task) 1460}
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 1461
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 1462
901 } 1463
902 GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map); 1464static void
903 ego_entry = ego_entry->next; 1465get_ticket_after_abe_bootstrap (void *cls,
904 GNUNET_free (ego_tmp); 1466 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
905 } 1467{
1468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1469 "Finished ABE bootstrap\n");
1470 struct TicketRevocationHandle *rh = cls;
1471 rh->abe_key = abe_key;
1472 TKT_database->get_ticket_attributes (TKT_database->cls,
1473 &rh->ticket,
1474 &process_attributes_to_update,
1475 rh);
906} 1476}
907 1477
908/** 1478/**
909 * Shutdown task 1479 * Checks a ticket revocation message
910 * 1480 *
911 * @param cls NULL 1481 * @param cls client sending the message
912 * @param tc task context 1482 * @param im message of type `struct RevokeTicketMessage`
1483 * @return #GNUNET_OK if @a im is well-formed
913 */ 1484 */
914static void 1485static int
915do_shutdown (void *cls) 1486check_revoke_ticket_message(void *cls,
1487 const struct RevokeTicketMessage *im)
916{ 1488{
917 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1489 uint16_t size;
918 "Shutting down...\n");
919 cleanup();
920}
921
922 1490
923static struct GNUNET_MQ_Envelope* 1491 size = ntohs (im->header.size);
924create_exchange_result_message (const char* token, 1492 if (size <= sizeof (struct RevokeTicketMessage))
925 const char* label, 1493 {
926 uint64_t ticket_nonce, 1494 GNUNET_break (0);
927 uint64_t id) 1495 return GNUNET_SYSERR;
928{ 1496 }
929 struct GNUNET_MQ_Envelope *env; 1497 return GNUNET_OK;
930 struct ExchangeResultMessage *erm;
931 uint16_t token_len = strlen (token) + 1;
932
933 env = GNUNET_MQ_msg_extra (erm,
934 token_len,
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} 1498}
941 1499/**
942 1500 *
943static struct GNUNET_MQ_Envelope* 1501 * Handler for ticket revocation message
944create_issue_result_message (const char* label, 1502 *
945 const char* ticket, 1503 * @param cls unused
946 const char* token, 1504 * @param client who sent the message
947 uint64_t id) 1505 * @param message the message
1506 */
1507static void
1508handle_revoke_ticket_message (void *cls,
1509 const struct RevokeTicketMessage *rm)
948{ 1510{
949 struct GNUNET_MQ_Envelope *env; 1511 struct TicketRevocationHandle *rh;
950 struct IssueResultMessage *irm; 1512 struct IdpClient *idp = cls;
951 char *tmp_str; 1513 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
952 size_t len; 1514
1515 rh = GNUNET_new (struct TicketRevocationHandle);
1516 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1517 rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1518 rh->ticket = *ticket;
1519 rh->r_id = ntohl (rm->id);
1520 rh->client = idp;
1521 rh->identity = rm->identity;
1522 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1523 &rh->ticket.identity);
1524 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1525 idp->revocation_list_tail,
1526 rh);
1527 bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1528 GNUNET_SERVICE_client_continue (idp->client);
953 1529
954 GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token);
955 len = strlen (tmp_str) + 1;
956 env = GNUNET_MQ_msg_extra (irm,
957 len,
958 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
959 irm->id = id;
960 GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1);
961 GNUNET_free (tmp_str);
962 return env;
963} 1530}
964 1531
965static void
966cleanup_issue_handle (struct IssueHandle *handle)
967{
968 if (NULL != handle->attr_map)
969 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
970 if (NULL != handle->scopes)
971 GNUNET_free (handle->scopes);
972 if (NULL != handle->token)
973 token_destroy (handle->token);
974 if (NULL != handle->ticket)
975 ticket_destroy (handle->ticket);
976 if (NULL != handle->label)
977 GNUNET_free (handle->label);
978 GNUNET_free (handle);
979}
980 1532
981static void 1533static void
982store_token_issue_cont (void *cls, 1534cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
983 int32_t success,
984 const char *emsg)
985{ 1535{
986 struct IssueHandle *handle = cls; 1536 if (NULL != handle->key)
987 struct GNUNET_MQ_Envelope *env; 1537 GNUNET_CRYPTO_cpabe_delete_key (handle->key,
988 char *ticket_str; 1538 GNUNET_YES);
989 char *token_str; 1539 if (NULL != handle->attrs)
990 1540 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
991 handle->ns_qe = NULL; 1541 GNUNET_free (handle);
992 if (GNUNET_SYSERR == success)
993 {
994 cleanup_issue_handle (handle);
995 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
996 "Unknown Error\n");
997 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
998 return;
999 }
1000 if (GNUNET_OK != ticket_serialize (handle->ticket,
1001 &handle->iss_key,
1002 &ticket_str))
1003 {
1004 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1005 "Error serializing ticket\n");
1006 cleanup_issue_handle (handle);
1007 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1008 return;
1009 }
1010 if (GNUNET_OK != token_to_string (handle->token,
1011 &handle->iss_key,
1012 &token_str))
1013 {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1015 "Error serializing token\n");
1016 GNUNET_free (ticket_str);
1017 cleanup_issue_handle (handle);
1018 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1019 return;
1020 }
1021 env = create_issue_result_message (handle->label,
1022 ticket_str,
1023 token_str,
1024 handle->r_id);
1025 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
1026 env);
1027 cleanup_issue_handle (handle);
1028 GNUNET_free (ticket_str);
1029 GNUNET_free (token_str);
1030} 1542}
1031 1543
1032 1544
1545
1033/** 1546/**
1034 * Build a token and store it 1547 * Checks a ticket consume message
1035 * 1548 *
1036 * @param cls the IssueHandle 1549 * @param cls client sending the message
1550 * @param im message of type `struct ConsumeTicketMessage`
1551 * @return #GNUNET_OK if @a im is well-formed
1037 */ 1552 */
1038static void 1553static int
1039sign_and_return_token (void *cls) 1554check_consume_ticket_message(void *cls,
1555 const struct ConsumeTicketMessage *cm)
1040{ 1556{
1041 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 1557 uint16_t size;
1042 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
1043 struct IssueHandle *handle = cls;
1044 struct GNUNET_GNSRECORD_Data token_record[2];
1045 char *nonce_str;
1046 char *enc_token_str;
1047 char *token_metadata;
1048 char* write_ptr;
1049 uint64_t time;
1050 uint64_t exp_time;
1051 size_t token_metadata_len;
1052
1053 //Remote nonce
1054 nonce_str = NULL;
1055 GNUNET_asprintf (&nonce_str, "%lu", handle->nonce);
1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
1057
1058 GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
1059 &pub_key);
1060 handle->ticket = ticket_create (handle->nonce,
1061 &pub_key,
1062 handle->label,
1063 &handle->aud_key);
1064
1065 time = GNUNET_TIME_absolute_get().abs_value_us;
1066 exp_time = time + token_expiration_interval.rel_value_us;
1067
1068 token_add_attr_int (handle->token, "nbf", time);
1069 token_add_attr_int (handle->token, "iat", time);
1070 token_add_attr_int (handle->token, "exp", exp_time);
1071 token_add_attr (handle->token, "nonce", nonce_str);
1072
1073 //Token in a serialized encrypted format
1074 GNUNET_assert (token_serialize (handle->token,
1075 &handle->iss_key,
1076 &ecdhe_privkey,
1077 &enc_token_str));
1078
1079 //Token record E,E_K (Token)
1080 token_record[0].data = enc_token_str;
1081 token_record[0].data_size = strlen (enc_token_str) + 1;
1082 token_record[0].expiration_time = exp_time;
1083 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
1084 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
1085
1086
1087 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
1088 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
1089 + strlen (handle->scopes) + 1; //With 0-Terminator
1090 token_metadata = GNUNET_malloc (token_metadata_len);
1091 write_ptr = token_metadata;
1092 GNUNET_memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
1093 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
1094 GNUNET_memcpy (write_ptr, &handle->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1095 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
1096 GNUNET_memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); //with 0-Terminator;
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}
1117 1558
1559 size = ntohs (cm->header.size);
1560 if (size <= sizeof (struct ConsumeTicketMessage))
1561 {
1562 GNUNET_break (0);
1563 return GNUNET_SYSERR;
1564 }
1565 return GNUNET_OK;
1566}
1118 1567
1119static void 1568static void
1120attr_collect_error (void *cls) 1569process_parallel_lookup2 (void *cls, uint32_t rd_count,
1570 const struct GNUNET_GNSRECORD_Data *rd)
1121{ 1571{
1122 struct IssueHandle *handle = cls; 1572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1573 "Parallel lookup finished (count=%u)\n", rd_count);
1574 struct ParallelLookup *parallel_lookup = cls;
1575 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
1576 struct ConsumeTicketResultMessage *crm;
1577 struct GNUNET_MQ_Envelope *env;
1578 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le;
1579 struct GNUNET_TIME_Absolute decrypt_duration;
1580 char *data;
1581 char *data_tmp;
1582 ssize_t attr_len;
1583 size_t attrs_len;
1584
1585 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1586 handle->parallel_lookups_tail,
1587 parallel_lookup);
1588 GNUNET_free (parallel_lookup->label);
1589
1590 GNUNET_STATISTICS_update (stats_handle,
1591 "attribute_lookup_time_total",
1592 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
1593 GNUNET_YES);
1594 GNUNET_STATISTICS_update (stats_handle,
1595 "attribute_lookups_count",
1596 1,
1597 GNUNET_YES);
1598
1599
1600 GNUNET_free (parallel_lookup);
1601 if (1 != rd_count)
1602 GNUNET_break(0);//TODO
1603 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1604 {
1605 decrypt_duration = GNUNET_TIME_absolute_get ();
1606 attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data + sizeof (uint32_t),
1607 rd->data_size - sizeof (uint32_t),
1608 handle->key,
1609 (void**)&data);
1610 if (GNUNET_SYSERR != attr_len)
1611 {
1612 GNUNET_STATISTICS_update (stats_handle,
1613 "abe_decrypt_time_total",
1614 GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
1615 GNUNET_YES);
1616 GNUNET_STATISTICS_update (stats_handle,
1617 "abe_decrypt_count",
1618 1,
1619 GNUNET_YES);
1620
1621 attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
1622 attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data,
1623 attr_len);
1624 attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
1625 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1626 handle->attrs->list_tail,
1627 attr_le);
1628 GNUNET_free (data);
1629 }
1630 }
1631 if (NULL != handle->parallel_lookups_head)
1632 return; //Wait for more
1633 /* Else we are done */
1634
1635 /* Store ticket in DB */
1636 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1637 &handle->ticket,
1638 handle->attrs))
1639 {
1640 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1641 "Unable to store ticket after consume\n");
1642 GNUNET_break (0);
1643 }
1123 1644
1124 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n"); 1645 GNUNET_SCHEDULER_cancel (handle->kill_task);
1125 handle->ns_it = NULL; 1646 attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs);
1126 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); 1647 env = GNUNET_MQ_msg_extra (crm,
1648 attrs_len,
1649 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1650 crm->id = htonl (handle->r_id);
1651 crm->attrs_len = htons (attrs_len);
1652 crm->identity = handle->ticket.identity;
1653 data_tmp = (char *) &crm[1];
1654 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs,
1655 data_tmp);
1656 GNUNET_MQ_send (handle->client->mq, env);
1657 cleanup_consume_ticket_handle (handle);
1127} 1658}
1128 1659
1129 1660void
1130static void 1661abort_parallel_lookups2 (void *cls)
1131attr_collect_finished (void *cls)
1132{ 1662{
1133 struct IssueHandle *handle = cls; 1663 struct ConsumeTicketHandle *handle = cls;
1664 struct ParallelLookup *lu;
1665 struct ParallelLookup *tmp;
1666 struct AttributeResultMessage *arm;
1667 struct GNUNET_MQ_Envelope *env;
1668
1669 for (lu = handle->parallel_lookups_head;
1670 NULL != lu;) {
1671 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1672 GNUNET_free (lu->label);
1673 tmp = lu->next;
1674 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1675 handle->parallel_lookups_tail,
1676 lu);
1677 GNUNET_free (lu);
1678 lu = tmp;
1679 }
1680 env = GNUNET_MQ_msg (arm,
1681 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1682 arm->id = htonl (handle->r_id);
1683 arm->attr_len = htons (0);
1684 GNUNET_MQ_send (handle->client->mq, env);
1134 1685
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
1136 handle->ns_it = NULL;
1137 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
1138} 1686}
1139 1687
1140 1688
1141/**
1142 * Collect attributes for token
1143 */
1144static void 1689static void
1145attr_collect (void *cls, 1690process_consume_abe_key (void *cls, uint32_t rd_count,
1146 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1691 const struct GNUNET_GNSRECORD_Data *rd)
1147 const char *label,
1148 unsigned int rd_count,
1149 const struct GNUNET_GNSRECORD_Data *rd)
1150{ 1692{
1151 struct IssueHandle *handle = cls; 1693 struct ConsumeTicketHandle *handle = cls;
1152 int i; 1694 struct GNUNET_HashCode new_key_hash;
1153 char* data; 1695 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1154 struct GNUNET_HashCode key; 1696 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1155 1697 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1156 GNUNET_CRYPTO_hash (label, 1698 struct ParallelLookup *parallel_lookup;
1157 strlen (label), 1699 size_t size;
1158 &key); 1700 char *buf;
1159 1701 char *scope;
1160 if (0 == rd_count || 1702 char *lookup_query;
1161 ( (NULL != handle->attr_map) && 1703
1162 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, 1704 handle->lookup_request = NULL;
1163 &key)) 1705 if (1 != rd_count)
1164 )
1165 )
1166 { 1706 {
1167 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 1707 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1708 "Number of keys %d != 1.",
1709 rd_count);
1710 cleanup_consume_ticket_handle (handle);
1711 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1168 return; 1712 return;
1169 } 1713 }
1170 1714
1171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label); 1715 //Decrypt
1716 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1717
1718 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1719
1720 //Calculate symmetric key from ecdh parameters
1721 GNUNET_assert (GNUNET_OK ==
1722 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1723 ecdh_key,
1724 &new_key_hash));
1725 create_sym_key_from_ecdh (&new_key_hash,
1726 &enc_key,
1727 &enc_iv);
1728 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1729 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1730 &enc_key,
1731 &enc_iv,
1732 buf);
1172 1733
1173 if (1 == rd_count) 1734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1174 { 1735 "Decrypted bytes: %zd Expected bytes: %zd\n",
1175 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1736 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1176 { 1737 GNUNET_STATISTICS_update (stats_handle,
1177 data = GNUNET_GNSRECORD_value_to_string (rd->record_type, 1738 "abe_key_lookup_time_total",
1178 rd->data, 1739 GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
1179 rd->data_size); 1740 GNUNET_YES);
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data); 1741 GNUNET_STATISTICS_update (stats_handle,
1181 token_add_attr (handle->token, 1742 "abe_key_lookups_count",
1182 label, 1743 1,
1183 data); 1744 GNUNET_YES);
1184 GNUNET_free (data); 1745 scopes = GNUNET_strdup (buf);
1185 } 1746 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1186 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 1747 "Scopes %s\n", scopes);
1187 return; 1748 handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1188 } 1749 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1750 - strlen (scopes) - 1);
1189 1751
1190 i = 0; 1752 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1191 for (; i < rd_count; i++)
1192 { 1753 {
1193 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1754 GNUNET_asprintf (&lookup_query,
1194 { 1755 "%s.gnu",
1195 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, 1756 scope);
1196 rd[i].data, 1757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1197 rd[i].data_size); 1758 "Looking up %s\n", lookup_query);
1198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data); 1759 parallel_lookup = GNUNET_new (struct ParallelLookup);
1199 token_add_attr (handle->token, label, data); 1760 parallel_lookup->handle = handle;
1200 GNUNET_free (data); 1761 parallel_lookup->label = GNUNET_strdup (scope);
1201 } 1762 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
1763 parallel_lookup->lookup_request
1764 = GNUNET_GNS_lookup (gns_handle,
1765 lookup_query,
1766 &handle->ticket.identity,
1767 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1768 GNUNET_GNS_LO_DEFAULT,
1769 &process_parallel_lookup2,
1770 parallel_lookup);
1771 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1772 handle->parallel_lookups_tail,
1773 parallel_lookup);
1774 GNUNET_free (lookup_query);
1202 } 1775 }
1776 GNUNET_free (scopes);
1777 GNUNET_free (buf);
1778 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1779 &abort_parallel_lookups2,
1780 handle);
1781}
1203 1782
1204 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 1783
1784/**
1785 *
1786 * Handler for ticket issue message
1787 *
1788 * @param cls unused
1789 * @param client who sent the message
1790 * @param message the message
1791 */
1792static void
1793handle_consume_ticket_message (void *cls,
1794 const struct ConsumeTicketMessage *cm)
1795{
1796 struct ConsumeTicketHandle *ch;
1797 struct IdpClient *idp = cls;
1798 char* lookup_query;
1799 char* rnd_label;
1800
1801 ch = GNUNET_new (struct ConsumeTicketHandle);
1802 ch->r_id = ntohl (cm->id);
1803 ch->client = idp;
1804 ch->identity = cm->identity;
1805 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1806 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1807 &ch->identity_pub);
1808 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1809 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1810 sizeof (uint64_t));
1811 GNUNET_asprintf (&lookup_query,
1812 "%s.gnu",
1813 rnd_label);
1814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1815 "Looking for ABE key under %s\n", lookup_query);
1816 ch->lookup_start_time = GNUNET_TIME_absolute_get ();
1817 ch->lookup_request
1818 = GNUNET_GNS_lookup (gns_handle,
1819 lookup_query,
1820 &ch->ticket.identity,
1821 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1822 GNUNET_GNS_LO_DEFAULT,
1823 &process_consume_abe_key,
1824 ch);
1825 GNUNET_free (rnd_label);
1826 GNUNET_free (lookup_query);
1827 GNUNET_SERVICE_client_continue (idp->client);
1205} 1828}
1206 1829
1207static void 1830static void
1208cleanup_exchange_handle (struct ExchangeHandle *handle) 1831cleanup_as_handle (struct AttributeStoreHandle *handle)
1209{ 1832{
1210 if (NULL != handle->ticket) 1833 if (NULL != handle->claim)
1211 ticket_destroy (handle->ticket); 1834 GNUNET_free (handle->claim);
1212 if (NULL != handle->token) 1835 if (NULL != handle->abe_key)
1213 token_destroy (handle->token); 1836 GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key);
1214 GNUNET_free (handle); 1837 GNUNET_free (handle);
1215} 1838}
1216 1839
1217static void 1840static void
1218process_lookup_result (void *cls, uint32_t rd_count, 1841attr_store_cont (void *cls,
1219 const struct GNUNET_GNSRECORD_Data *rd) 1842 int32_t success,
1843 const char *emsg)
1220{ 1844{
1221 struct ExchangeHandle *handle = cls; 1845 struct AttributeStoreHandle *as_handle = cls;
1222 struct GNUNET_MQ_Envelope *env; 1846 struct GNUNET_MQ_Envelope *env;
1223 char* token_str; 1847 struct AttributeStoreResultMessage *acr_msg;
1224 char* record_str;
1225 1848
1226 handle->lookup_request = NULL; 1849 if (GNUNET_SYSERR == success)
1227 if (2 != rd_count)
1228 { 1850 {
1229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1851 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1230 "Number of tokens %d != 2.", 1852 "Failed to store attribute %s\n",
1231 rd_count); 1853 emsg);
1232 cleanup_exchange_handle (handle); 1854 cleanup_as_handle (as_handle);
1233 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1855 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1234 return; 1856 return;
1235 } 1857 }
1236 1858
1237 record_str = 1859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1238 GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN, 1860 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1239 rd->data, 1861 env = GNUNET_MQ_msg (acr_msg,
1240 rd->data_size); 1862 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1241 1863 acr_msg->id = htonl (as_handle->r_id);
1242 //Decrypt and parse 1864 acr_msg->op_result = htonl (GNUNET_OK);
1243 GNUNET_assert (GNUNET_OK == token_parse (record_str, 1865 GNUNET_MQ_send (as_handle->client->mq,
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); 1866 env);
1258 cleanup_exchange_handle (handle); 1867 cleanup_as_handle (as_handle);
1259 GNUNET_free (record_str); 1868}
1260 GNUNET_free (token_str); 1869
1870static void
1871attr_store_task (void *cls)
1872{
1873 struct AttributeStoreHandle *as_handle = cls;
1874 struct GNUNET_GNSRECORD_Data rd[1];
1875 char* buf;
1876 char* policy;
1877 char* enc_buf;
1878 char* rd_buf;
1879 size_t enc_size;
1880 size_t buf_size;
1881 uint32_t attr_ver;
1882
1883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1884 "Storing attribute\n");
1885 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim);
1886 buf = GNUNET_malloc (buf_size);
1887
1888 GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim,
1889 buf);
1890
1891 GNUNET_asprintf (&policy,
1892 "%s_%lu",
1893 as_handle->claim->name,
1894 as_handle->claim->version);
1895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1896 "Encrypting with policy %s\n", policy);
1897 /**
1898 * Encrypt the attribute value and store in namestore
1899 */
1900 enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1901 buf_size,
1902 policy, //Policy
1903 as_handle->abe_key,
1904 (void**)&enc_buf);
1905 GNUNET_free (buf);
1906 GNUNET_free (policy);
1907 rd[0].data_size = enc_size + sizeof (uint32_t);
1908 rd_buf = GNUNET_malloc (rd[0].data_size);
1909 attr_ver = htonl (as_handle->claim->version);
1910 GNUNET_memcpy (rd_buf,
1911 &attr_ver,
1912 sizeof (uint32_t));
1913 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1914 enc_buf,
1915 enc_size);
1916 rd[0].data = rd_buf;
1917 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1918 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1919 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1920 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1921 &as_handle->identity,
1922 as_handle->claim->name,
1923 1,
1924 rd,
1925 &attr_store_cont,
1926 as_handle);
1927 GNUNET_free (enc_buf);
1928 GNUNET_free (rd_buf);
1929}
1930
1931
1932static void
1933store_after_abe_bootstrap (void *cls,
1934 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1935{
1936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1937 "Finished ABE bootstrap\n");
1938 struct AttributeStoreHandle *ash = cls;
1939 ash->abe_key = abe_key;
1940 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1261} 1941}
1262 1942
1263/** 1943/**
1264 * Checks a exchange message 1944 * Checks a store message
1265 * 1945 *
1266 * @param cls client sending the message 1946 * @param cls client sending the message
1267 * @param xm message of type `struct ExchangeMessage` 1947 * @param sam message of type `struct AttributeStoreMessage`
1268 * @return #GNUNET_OK if @a xm is well-formed 1948 * @return #GNUNET_OK if @a im is well-formed
1269 */ 1949 */
1270static int 1950static int
1271check_exchange_message (void *cls, 1951check_attribute_store_message(void *cls,
1272 const struct ExchangeMessage *xm) 1952 const struct AttributeStoreMessage *sam)
1273{ 1953{
1274 uint16_t size; 1954 uint16_t size;
1275 1955
1276 size = ntohs (xm->header.size); 1956 size = ntohs (sam->header.size);
1277 if (size <= sizeof (struct ExchangeMessage)) 1957 if (size <= sizeof (struct AttributeStoreMessage))
1278 { 1958 {
1279 GNUNET_break (0); 1959 GNUNET_break (0);
1280 return GNUNET_SYSERR; 1960 return GNUNET_SYSERR;
@@ -1282,301 +1962,492 @@ check_exchange_message (void *cls,
1282 return GNUNET_OK; 1962 return GNUNET_OK;
1283} 1963}
1284 1964
1965
1285/** 1966/**
1286 * 1967 *
1287 * Handler for exchange message 1968 * Handler for store message
1288 * 1969 *
1289 * @param cls unused 1970 * @param cls unused
1290 * @param client who sent the message 1971 * @param client who sent the message
1291 * @param message the message 1972 * @param message the message
1292 */ 1973 */
1293static void 1974static void
1294handle_exchange_message (void *cls, 1975handle_attribute_store_message (void *cls,
1295 const struct ExchangeMessage *xm) 1976 const struct AttributeStoreMessage *sam)
1296{ 1977{
1297 struct ExchangeHandle *xchange_handle; 1978 struct AttributeStoreHandle *as_handle;
1298 struct GNUNET_SERVICE_Client *client = cls; 1979 struct IdpClient *idp = cls;
1299 const char *ticket; 1980 size_t data_len;
1300 char *lookup_query;
1301
1302 ticket = (const char *) &xm[1];
1303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1304 "Received EXCHANGE of `%s' from client\n", 1982 "Received ATTRIBUTE_STORE message\n");
1305 ticket); 1983
1306 xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle)); 1984 data_len = ntohs (sam->attr_len);
1307 xchange_handle->aud_privkey = xm->aud_privkey; 1985
1308 xchange_handle->r_id = xm->id; 1986 as_handle = GNUNET_new (struct AttributeStoreHandle);
1309 if (GNUNET_SYSERR == ticket_parse (ticket, 1987 as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1],
1310 &xchange_handle->aud_privkey, 1988 data_len);
1311 &xchange_handle->ticket)) 1989
1312 { 1990 as_handle->r_id = ntohl (sam->id);
1313 GNUNET_free (xchange_handle); 1991 as_handle->identity = sam->identity;
1314 GNUNET_SERVICE_client_drop (client); 1992 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1315 return; 1993 &as_handle->identity_pkey);
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 1994
1995 GNUNET_SERVICE_client_continue (idp->client);
1996 as_handle->client = idp;
1997 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
1334} 1998}
1335 1999
2000static void
2001cleanup_iter_handle (struct AttributeIterator *ai)
2002{
2003 if (NULL != ai->abe_key)
2004 GNUNET_CRYPTO_cpabe_delete_master_key (ai->abe_key);
2005 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
2006 ai->client->op_tail,
2007 ai);
2008 GNUNET_free (ai);
2009}
1336 2010
1337static void 2011static void
1338find_existing_token_error (void *cls) 2012attr_iter_error (void *cls)
1339{ 2013{
1340 struct IssueHandle *handle = cls; 2014 struct AttributeIterator *ai = cls;
1341 cleanup_issue_handle (handle); 2015 //TODO
1342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error looking for existing token\n"); 2016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2017 "Failed to iterate over attributes\n");
2018 cleanup_iter_handle (ai);
1343 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 2019 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1344} 2020}
1345 2021
2022static void
2023attr_iter_finished (void *cls)
2024{
2025 struct AttributeIterator *ai = cls;
2026 struct GNUNET_MQ_Envelope *env;
2027 struct AttributeResultMessage *arm;
2028
2029 env = GNUNET_MQ_msg (arm,
2030 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2031 arm->id = htonl (ai->request_id);
2032 arm->attr_len = htons (0);
2033 GNUNET_MQ_send (ai->client->mq, env);
2034 cleanup_iter_handle (ai);
2035}
1346 2036
1347static void 2037static void
1348find_existing_token_finished (void *cls) 2038attr_iter_cb (void *cls,
2039 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
2040 const char *label,
2041 unsigned int rd_count,
2042 const struct GNUNET_GNSRECORD_Data *rd)
1349{ 2043{
1350 struct IssueHandle *handle = cls; 2044 struct AttributeIterator *ai = cls;
1351 uint64_t rnd_key; 2045 struct AttributeResultMessage *arm;
2046 struct GNUNET_CRYPTO_AbeKey *key;
2047 struct GNUNET_MQ_Envelope *env;
2048 ssize_t msg_extra_len;
2049 char* attr_ser;
2050 char* attrs[2];
2051 char* data_tmp;
2052 char* policy;
2053 uint32_t attr_ver;
2054
2055 if (rd_count != 1)
2056 {
2057 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2058 return;
2059 }
1352 2060
2061 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
2062 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2063 return;
2064 }
2065 attr_ver = ntohl(*((uint32_t*)rd->data));
2066 GNUNET_asprintf (&policy, "%s_%lu",
2067 label, attr_ver);
2068 attrs[0] = policy;
2069 attrs[1] = 0;
2070 key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
2071 attrs);
2072 msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data+sizeof (uint32_t),
2073 rd->data_size-sizeof (uint32_t),
2074 key,
2075 (void**)&attr_ser);
2076
2077 GNUNET_CRYPTO_cpabe_delete_key (key,
2078 GNUNET_YES);
2079 //GNUNET_free (policy);
1353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1354 ">>> No existing token found\n"); 2081 "Found attribute: %s\n", label);
1355 rnd_key = 2082 env = GNUNET_MQ_msg_extra (arm,
1356 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, 2083 msg_extra_len,
1357 UINT64_MAX); 2084 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1358 GNUNET_STRINGS_base64_encode ((char*)&rnd_key, 2085 arm->id = htonl (ai->request_id);
1359 sizeof (uint64_t), 2086 arm->attr_len = htons (msg_extra_len);
1360 &handle->label); 2087 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
1361 handle->ns_it = NULL; 2088 &arm->identity);
1362 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, 2089 data_tmp = (char *) &arm[1];
1363 &handle->iss_key, 2090 GNUNET_memcpy (data_tmp,
1364 &attr_collect_error, 2091 attr_ser,
1365 handle, 2092 msg_extra_len);
1366 &attr_collect, 2093 GNUNET_MQ_send (ai->client->mq, env);
1367 handle, 2094 GNUNET_free (attr_ser);
1368 &attr_collect_finished, 2095 GNUNET_CRYPTO_cpabe_delete_master_key (ai->abe_key);
1369 handle); 2096 ai->abe_key = NULL;
2097}
2098
2099
2100void
2101iterate_after_abe_bootstrap (void *cls,
2102 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
2103{
2104 struct AttributeIterator *ai = cls;
2105 ai->abe_key = abe_key;
2106 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2107 &ai->identity,
2108 &attr_iter_error,
2109 ai,
2110 &attr_iter_cb,
2111 ai,
2112 &attr_iter_finished,
2113 ai);
1370} 2114}
1371 2115
2116void
2117iterate_next_after_abe_bootstrap (void *cls,
2118 struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
2119{
2120 struct AttributeIterator *ai = cls;
2121 ai->abe_key = abe_key;
2122 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2123}
2124
2125
1372 2126
1373/** 2127/**
2128 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
1374 * 2129 *
1375 * Look for existing token 2130 * @param cls the client sending the message
1376 * 2131 * @param zis_msg message from the client
1377 * @param cls the identity entry 2132 */
1378 * @param zone the identity 2133static void
1379 * @param lbl the name of the record 2134handle_iteration_start (void *cls,
1380 * @param rd_count number of records 2135 const struct AttributeIterationStartMessage *ais_msg)
1381 * @param rd record data 2136{
2137 struct IdpClient *idp = cls;
2138 struct AttributeIterator *ai;
2139
2140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2141 "Received ATTRIBUTE_ITERATION_START message\n");
2142 ai = GNUNET_new (struct AttributeIterator);
2143 ai->request_id = ntohl (ais_msg->id);
2144 ai->client = idp;
2145 ai->identity = ais_msg->identity;
2146
2147 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2148 idp->op_tail,
2149 ai);
2150 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2151 GNUNET_SERVICE_client_continue (idp->client);
2152}
2153
2154
2155/**
2156 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
1382 * 2157 *
2158 * @param cls the client sending the message
2159 * @param ais_msg message from the client
1383 */ 2160 */
1384static void 2161static void
1385find_existing_token (void *cls, 2162handle_iteration_stop (void *cls,
1386 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 2163 const struct AttributeIterationStopMessage *ais_msg)
1387 const char *lbl, 2164{
1388 unsigned int rd_count, 2165 struct IdpClient *idp = cls;
1389 const struct GNUNET_GNSRECORD_Data *rd) 2166 struct AttributeIterator *ai;
1390{ 2167 uint32_t rid;
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 2168
1399 //There should be only a single record for a token under a label 2169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1400 if (2 != rd_count) 2170 "Received `%s' message\n",
2171 "ATTRIBUTE_ITERATION_STOP");
2172 rid = ntohl (ais_msg->id);
2173 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2174 if (ai->request_id == rid)
2175 break;
2176 if (NULL == ai)
1401 { 2177 {
1402 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2178 GNUNET_break (0);
2179 GNUNET_SERVICE_client_drop (idp->client);
1403 return; 2180 return;
1404 } 2181 }
2182 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2183 idp->op_tail,
2184 ai);
2185 GNUNET_free (ai);
2186 GNUNET_SERVICE_client_continue (idp->client);
2187}
1405 2188
1406 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 2189
1407 { 2190/**
1408 token_metadata_record = &rd[0]; 2191 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
1409 } 2192 *
1410 else 2193 * @param cls the client sending the message
1411 { 2194 * @param message message from the client
1412 token_metadata_record = &rd[1]; 2195 */
1413 } 2196static void
1414 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 2197handle_iteration_next (void *cls,
2198 const struct AttributeIterationNextMessage *ais_msg)
2199{
2200 struct IdpClient *idp = cls;
2201 struct AttributeIterator *ai;
2202 uint32_t rid;
2203
2204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2205 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2206 rid = ntohl (ais_msg->id);
2207 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2208 if (ai->request_id == rid)
2209 break;
2210 if (NULL == ai)
1415 { 2211 {
1416 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2212 GNUNET_break (0);
2213 GNUNET_SERVICE_client_drop (idp->client);
1417 return; 2214 return;
1418 } 2215 }
1419 ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data); 2216 bootstrap_abe (&ai->identity,
1420 aud_key = 2217 &iterate_next_after_abe_bootstrap,
1421 (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey)); 2218 ai,
1422 tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 2219 GNUNET_NO);
2220 GNUNET_SERVICE_client_continue (idp->client);
2221}
1423 2222
1424 if (0 != memcmp (aud_key, &handle->aud_key, 2223/**
1425 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) 2224 * Ticket iteration processor result
2225 */
2226enum ZoneIterationResult
2227{
2228 /**
2229 * Iteration start.
2230 */
2231 IT_START = 0,
2232
2233 /**
2234 * Found tickets,
2235 * Continue to iterate with next iteration_next call
2236 */
2237 IT_SUCCESS_MORE_AVAILABLE = 1,
2238
2239 /**
2240 * Iteration complete
2241 */
2242 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2243};
2244
2245
2246/**
2247 * Context for ticket iteration
2248 */
2249struct TicketIterationProcResult
2250{
2251 /**
2252 * The ticket iteration handle
2253 */
2254 struct TicketIteration *ti;
2255
2256 /**
2257 * Iteration result: iteration done?
2258 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2259 * we got one for now and have sent it to the client
2260 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2261 * #IT_START: if we are still trying to find a result.
2262 */
2263 int res_iteration_finished;
2264
2265};
2266
2267static void
2268cleanup_ticket_iter_handle (struct TicketIteration *ti)
2269{
2270 GNUNET_free (ti);
2271}
2272
2273/**
2274 * Process ticket from database
2275 *
2276 * @param cls struct TicketIterationProcResult
2277 * @param ticket the ticket
2278 * @param attrs the attributes
2279 */
2280static void
2281ticket_iterate_proc (void *cls,
2282 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
2283 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
2284{
2285 struct TicketIterationProcResult *proc = cls;
2286
2287 if (NULL == ticket)
1426 { 2288 {
1427 char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key,
1428 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1429 //Audience does not match!
1430 char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA,
1431 token_metadata_record->data,
1432 token_metadata_record->data_size);
1433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1434 "Token does not match audience %s vs %s. Moving on\n", 2290 "Iteration done\n");
1435 tmp2, 2291 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
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; 2292 return;
1442 } 2293 }
2294 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2295 send_ticket_result (proc->ti->client,
2296 proc->ti->r_id,
2297 ticket,
2298 attrs);
1443 2299
1444 scope = strtok (tmp_scopes, ","); 2300}
1445 scope_count_token = 0; 2301
1446 while (NULL != scope) 2302/**
1447 { 2303 * Perform ticket iteration step
1448 GNUNET_CRYPTO_hash (scope, 2304 *
1449 strlen (scope), 2305 * @param ti ticket iterator to process
1450 &key); 2306 */
2307static void
2308run_ticket_iteration_round (struct TicketIteration *ti)
2309{
2310 struct TicketIterationProcResult proc;
2311 struct GNUNET_MQ_Envelope *env;
2312 struct TicketResultMessage *trm;
2313 int ret;
1451 2314
1452 if ((NULL != handle->attr_map) && 2315 memset (&proc, 0, sizeof (proc));
1453 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key))) 2316 proc.ti = ti;
2317 proc.res_iteration_finished = IT_START;
2318 while (IT_START == proc.res_iteration_finished)
2319 {
2320 if (GNUNET_SYSERR ==
2321 (ret = TKT_database->iterate_tickets (TKT_database->cls,
2322 &ti->identity,
2323 ti->is_audience,
2324 ti->offset,
2325 &ticket_iterate_proc,
2326 &proc)))
1454 { 2327 {
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2328 GNUNET_break (0);
1456 "Issued token does not include `%s'. Moving on\n", scope); 2329 break;
1457 GNUNET_free (tmp_scopes);
1458 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1459 return;
1460 } 2330 }
1461 scope_count_token++; 2331 if (GNUNET_NO == ret)
1462 scope = strtok (NULL, ","); 2332 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2333 ti->offset++;
1463 } 2334 }
1464 GNUNET_free (tmp_scopes); 2335 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 { 2336 {
1470 //We have an existing token 2337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1471 handle->label = GNUNET_strdup (lbl); 2338 "More results available\n");
1472 handle->ns_it = NULL; 2339 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 } 2340 }
1484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2341 /* send empty response to indicate end of list */
1485 "Nuber of attributes in token do not match request\n"); 2342 env = GNUNET_MQ_msg (trm,
1486 //No luck 2343 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
1487 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2344 trm->id = htonl (ti->r_id);
2345 GNUNET_MQ_send (ti->client->mq,
2346 env);
2347 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2348 ti->client->ticket_iter_tail,
2349 ti);
2350 cleanup_ticket_iter_handle (ti);
1488} 2351}
1489 2352
1490/** 2353/**
1491 * Checks an issue message 2354 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message
1492 * 2355 *
1493 * @param cls client sending the message 2356 * @param cls the client sending the message
1494 * @param im message of type `struct IssueMessage` 2357 * @param tis_msg message from the client
1495 * @return #GNUNET_OK if @a im is well-formed
1496 */ 2358 */
1497static int 2359static void
1498check_issue_message(void *cls, 2360handle_ticket_iteration_start (void *cls,
1499 const struct IssueMessage *im) 2361 const struct TicketIterationStartMessage *tis_msg)
1500{ 2362{
1501 uint16_t size; 2363 struct IdpClient *client = cls;
2364 struct TicketIteration *ti;
1502 2365
1503 size = ntohs (im->header.size); 2366 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1504 if (size <= sizeof (struct IssueMessage)) 2367 "Received TICKET_ITERATION_START message\n");
1505 { 2368 ti = GNUNET_new (struct TicketIteration);
1506 GNUNET_break (0); 2369 ti->r_id = ntohl (tis_msg->id);
1507 return GNUNET_SYSERR; 2370 ti->offset = 0;
1508 } 2371 ti->client = client;
1509 scopes = (char *) &im[1]; 2372 ti->identity = tis_msg->identity;
1510 if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1]) 2373 ti->is_audience = ntohl (tis_msg->is_audience);
2374
2375 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2376 client->ticket_iter_tail,
2377 ti);
2378 run_ticket_iteration_round (ti);
2379 GNUNET_SERVICE_client_continue (client->client);
2380}
2381
2382
2383/**
2384 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message
2385 *
2386 * @param cls the client sending the message
2387 * @param tis_msg message from the client
2388 */
2389static void
2390handle_ticket_iteration_stop (void *cls,
2391 const struct TicketIterationStopMessage *tis_msg)
2392{
2393 struct IdpClient *client = cls;
2394 struct TicketIteration *ti;
2395 uint32_t rid;
2396
2397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2398 "Received `%s' message\n",
2399 "TICKET_ITERATION_STOP");
2400 rid = ntohl (tis_msg->id);
2401 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2402 if (ti->r_id == rid)
2403 break;
2404 if (NULL == ti)
1511 { 2405 {
1512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1513 "Malformed scopes received!\n");
1514 GNUNET_break (0); 2406 GNUNET_break (0);
1515 return GNUNET_SYSERR; 2407 GNUNET_SERVICE_client_drop (client->client);
2408 return;
1516 } 2409 }
1517 return GNUNET_OK; 2410 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2411 client->ticket_iter_tail,
2412 ti);
2413 cleanup_ticket_iter_handle (ti);
2414 GNUNET_SERVICE_client_continue (client->client);
1518} 2415}
1519 2416
2417
1520/** 2418/**
2419 * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message
1521 * 2420 *
1522 * Handler for issue message 2421 * @param cls the client sending the message
1523 * 2422 * @param message message from the client
1524 * @param cls unused
1525 * @param client who sent the message
1526 * @param message the message
1527 */ 2423 */
1528static void 2424static void
1529handle_issue_message (void *cls, 2425handle_ticket_iteration_next (void *cls,
1530 const struct IssueMessage *im) 2426 const struct TicketIterationNextMessage *tis_msg)
1531{ 2427{
1532 const char *scopes; 2428 struct IdpClient *client = cls;
1533 char *scopes_tmp; 2429 struct TicketIteration *ti;
1534 char *scope; 2430 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 2431
1545 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) 2432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2433 "Received TICKET_ITERATION_NEXT message\n");
2434 rid = ntohl (tis_msg->id);
2435 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2436 if (ti->r_id == rid)
2437 break;
2438 if (NULL == ti)
1546 { 2439 {
1547 GNUNET_CRYPTO_hash (scope, 2440 GNUNET_break (0);
1548 strlen (scope), 2441 GNUNET_SERVICE_client_drop (client->client);
1549 &key); 2442 return;
1550 GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1551 &key,
1552 scope,
1553 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1554 } 2443 }
1555 GNUNET_free (scopes_tmp); 2444 run_ticket_iteration_round (ti);
1556 issue_handle->r_id = im->id; 2445 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} 2446}
1578 2447
1579 2448
2449
2450
1580/** 2451/**
1581 * Main function that will be run 2452 * Main function that will be run
1582 * 2453 *
@@ -1590,6 +2461,7 @@ run (void *cls,
1590 const struct GNUNET_CONFIGURATION_Handle *c, 2461 const struct GNUNET_CONFIGURATION_Handle *c,
1591 struct GNUNET_SERVICE_Handle *server) 2462 struct GNUNET_SERVICE_Handle *server)
1592{ 2463{
2464 char *database;
1593 cfg = c; 2465 cfg = c;
1594 2466
1595 stats = GNUNET_STATISTICS_create ("identity-provider", cfg); 2467 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
@@ -1606,10 +2478,38 @@ run (void *cls,
1606 { 2478 {
1607 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); 2479 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1608 } 2480 }
1609 2481 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2482 if (NULL == credential_handle)
2483 {
2484 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2485 }
1610 identity_handle = GNUNET_IDENTITY_connect (cfg, 2486 identity_handle = GNUNET_IDENTITY_connect (cfg,
1611 &list_ego, 2487 NULL,
1612 NULL); 2488 NULL);
2489 stats_handle = GNUNET_STATISTICS_create ("identity-provider",
2490 cfg);
2491 /* Loading DB plugin */
2492 if (GNUNET_OK !=
2493 GNUNET_CONFIGURATION_get_value_string (cfg,
2494 "identity-provider",
2495 "database",
2496 &database))
2497 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2498 "No database backend configured\n");
2499 GNUNET_asprintf (&db_lib_name,
2500 "libgnunet_plugin_identity_provider_%s",
2501 database);
2502 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2503 (void *) cfg);
2504 GNUNET_free (database);
2505 if (NULL == TKT_database)
2506 {
2507 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2508 "Could not load database backend `%s'\n",
2509 db_lib_name);
2510 GNUNET_SCHEDULER_shutdown ();
2511 return;
2512 }
1613 2513
1614 if (GNUNET_OK == 2514 if (GNUNET_OK ==
1615 GNUNET_CONFIGURATION_get_value_time (cfg, 2515 GNUNET_CONFIGURATION_get_value_time (cfg,
@@ -1640,9 +2540,39 @@ client_disconnect_cb (void *cls,
1640 struct GNUNET_SERVICE_Client *client, 2540 struct GNUNET_SERVICE_Client *client,
1641 void *app_ctx) 2541 void *app_ctx)
1642{ 2542{
2543 struct IdpClient *idp = app_ctx;
2544 struct AttributeIterator *ai;
2545 struct TicketIteration *ti;
2546 struct TicketRevocationHandle *rh;
2547
2548 //TODO other operations
2549
1643 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1644 "Client %p disconnected\n", 2551 "Client %p disconnected\n",
1645 client); 2552 client);
2553
2554 while (NULL != (ai = idp->op_head))
2555 {
2556 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2557 idp->op_tail,
2558 ai);
2559 GNUNET_free (ai);
2560 }
2561 while (NULL != (rh = idp->revocation_list_head))
2562 {
2563 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2564 idp->revocation_list_tail,
2565 rh);
2566 cleanup_revoke_ticket_handle (rh);
2567 }
2568 while (NULL != (ti = idp->ticket_iter_head))
2569 {
2570 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2571 idp->ticket_iter_tail,
2572 ti);
2573 cleanup_ticket_iter_handle (ti);
2574 }
2575 GNUNET_free (idp);
1646} 2576}
1647 2577
1648 2578
@@ -1659,10 +2589,14 @@ client_connect_cb (void *cls,
1659 struct GNUNET_SERVICE_Client *client, 2589 struct GNUNET_SERVICE_Client *client,
1660 struct GNUNET_MQ_Handle *mq) 2590 struct GNUNET_MQ_Handle *mq)
1661{ 2591{
2592 struct IdpClient *idp;
1662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1663 "Client %p connected\n", 2594 "Client %p connected\n",
1664 client); 2595 client);
1665 return client; 2596 idp = GNUNET_new (struct IdpClient);
2597 idp->client = client;
2598 idp->mq = mq;
2599 return idp;
1666} 2600}
1667 2601
1668 2602
@@ -1677,13 +2611,45 @@ GNUNET_SERVICE_MAIN
1677 &client_connect_cb, 2611 &client_connect_cb,
1678 &client_disconnect_cb, 2612 &client_disconnect_cb,
1679 NULL, 2613 NULL,
1680 GNUNET_MQ_hd_var_size (issue_message, 2614 GNUNET_MQ_hd_var_size (attribute_store_message,
1681 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE, 2615 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
1682 struct IssueMessage, 2616 struct AttributeStoreMessage,
2617 NULL),
2618 GNUNET_MQ_hd_fixed_size (iteration_start,
2619 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2620 struct AttributeIterationStartMessage,
2621 NULL),
2622 GNUNET_MQ_hd_fixed_size (iteration_next,
2623 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2624 struct AttributeIterationNextMessage,
2625 NULL),
2626 GNUNET_MQ_hd_fixed_size (iteration_stop,
2627 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2628 struct AttributeIterationStopMessage,
2629 NULL),
2630 GNUNET_MQ_hd_var_size (issue_ticket_message,
2631 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2632 struct IssueTicketMessage,
2633 NULL),
2634 GNUNET_MQ_hd_var_size (consume_ticket_message,
2635 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2636 struct ConsumeTicketMessage,
1683 NULL), 2637 NULL),
1684 GNUNET_MQ_hd_var_size (exchange_message, 2638 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1685 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE, 2639 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
1686 struct ExchangeMessage, 2640 struct TicketIterationStartMessage,
2641 NULL),
2642 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2643 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2644 struct TicketIterationNextMessage,
2645 NULL),
2646 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2647 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2648 struct TicketIterationStopMessage,
2649 NULL),
2650 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2651 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2652 struct RevokeTicketMessage,
1687 NULL), 2653 NULL),
1688 GNUNET_MQ_handler_end()); 2654 GNUNET_MQ_handler_end());
1689/* end of gnunet-service-identity-provider.c */ 2655/* 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..be9fdc6f5 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_TICKET_ISSUE
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_TICKET_ISSUE
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_TICKET_ISSUE
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_TICKET_ISSUE
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..6fc8d228a 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;
@@ -197,6 +360,26 @@ force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
197} 360}
198 361
199/** 362/**
363 * Free @a it.
364 *
365 * @param it entry to free
366 */
367static void
368free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
369{
370 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
371
372 GNUNET_CONTAINER_DLL_remove (h->it_head,
373 h->it_tail,
374 it);
375 if (NULL != it->env)
376 GNUNET_MQ_discard (it->env);
377 GNUNET_free (it);
378}
379
380
381
382/**
200 * Generic error handler, called with the appropriate error code and 383 * Generic error handler, called with the appropriate error code and
201 * the same closure specified at the creation of the message queue. 384 * the same closure specified at the creation of the message queue.
202 * Not every message queue implementation supports an error handler. 385 * Not every message queue implementation supports an error handler.
@@ -213,22 +396,68 @@ mq_error_handler (void *cls,
213} 396}
214 397
215/** 398/**
216 * Check validity of message received from the service 399 * Handle an incoming message of type
400 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
401 *
402 * @param cls
403 * @param msg the message we received
404 */
405static void
406handle_attribute_store_response (void *cls,
407 const struct AttributeStoreResultMessage *msg)
408{
409 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
410 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
411 uint32_t r_id = ntohl (msg->id);
412 int res;
413 const char *emsg;
414
415 for (op = h->op_head; NULL != op; op = op->next)
416 if (op->r_id == r_id)
417 break;
418 if (NULL == op)
419 return;
420
421 res = ntohl (msg->op_result);
422 LOG (GNUNET_ERROR_TYPE_DEBUG,
423 "Received ATTRIBUTE_STORE_RESPONSE with result %d\n",
424 res);
425
426 /* TODO: add actual error message to response... */
427 if (GNUNET_SYSERR == res)
428 emsg = _("failed to store record\n");
429 else
430 emsg = NULL;
431 if (NULL != op->as_cb)
432 op->as_cb (op->cls,
433 res,
434 emsg);
435 GNUNET_CONTAINER_DLL_remove (h->op_head,
436 h->op_tail,
437 op);
438 GNUNET_free (op);
439
440}
441
442
443/**
444 * Handle an incoming message of type
445 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
217 * 446 *
218 * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` 447 * @param cls
219 * @param result_msg the incoming message 448 * @param msg the message we received
449 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
220 */ 450 */
221static int 451static int
222check_exchange_result (void *cls, 452check_consume_ticket_result (void *cls,
223 const struct ExchangeResultMessage *erm) 453 const struct ConsumeTicketResultMessage *msg)
224{ 454{
225 char *str; 455 size_t msg_len;
226 size_t size = ntohs (erm->header.size) - sizeof (*erm); 456 size_t attrs_len;
227
228 457
229 str = (char *) &erm[1]; 458 msg_len = ntohs (msg->header.size);
230 if ( (size > sizeof (struct ExchangeResultMessage)) && 459 attrs_len = ntohs (msg->attrs_len);
231 ('\0' != str[size - sizeof (struct ExchangeResultMessage) - 1]) ) 460 if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len)
232 { 461 {
233 GNUNET_break (0); 462 GNUNET_break (0);
234 return GNUNET_SYSERR; 463 return GNUNET_SYSERR;
@@ -238,20 +467,85 @@ check_exchange_result (void *cls,
238 467
239 468
240/** 469/**
241 * Check validity of message received from the service 470 * Handle an incoming message of type
471 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
472 *
473 * @param cls
474 * @param msg the message we received
475 */
476static void
477handle_consume_ticket_result (void *cls,
478 const struct ConsumeTicketResultMessage *msg)
479{
480 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
481 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
482 size_t attrs_len;
483 uint32_t r_id = ntohl (msg->id);
484
485 attrs_len = ntohs (msg->attrs_len);
486 LOG (GNUNET_ERROR_TYPE_DEBUG,
487 "Processing attribute result.\n");
488
489
490 for (op = h->op_head; NULL != op; op = op->next)
491 if (op->r_id == r_id)
492 break;
493 if (NULL == op)
494 return;
495
496 {
497 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
498 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
499 attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1],
500 attrs_len);
501 if (NULL != op->ar_cb)
502 {
503 if (NULL == attrs)
504 {
505 op->ar_cb (op->cls,
506 &msg->identity,
507 NULL);
508 }
509 else
510 {
511 for (le = attrs->list_head; NULL != le; le = le->next)
512 op->ar_cb (op->cls,
513 &msg->identity,
514 le->claim);
515 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
516 }
517 }
518 op->ar_cb (op->cls,
519 NULL,
520 NULL);
521 GNUNET_CONTAINER_DLL_remove (h->op_head,
522 h->op_tail,
523 op);
524 GNUNET_free (op);
525 return;
526 }
527 GNUNET_assert (0);
528}
529
530
531/**
532 * Handle an incoming message of type
533 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
242 * 534 *
243 * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` 535 * @param cls
244 * @param result_msg the incoming message 536 * @param msg the message we received
537 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
245 */ 538 */
246static int 539static int
247check_result (void *cls, 540check_attribute_result (void *cls,
248 const struct IssueResultMessage *irm) 541 const struct AttributeResultMessage *msg)
249{ 542{
250 char *str; 543 size_t msg_len;
251 size_t size = ntohs (irm->header.size) - sizeof (*irm); 544 size_t attr_len;
252 str = (char*) &irm[1]; 545
253 if ( (size > sizeof (struct IssueResultMessage)) && 546 msg_len = ntohs (msg->header.size);
254 ('\0' != str[size - sizeof (struct IssueResultMessage) - 1]) ) 547 attr_len = ntohs (msg->attr_len);
548 if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
255 { 549 {
256 GNUNET_break (0); 550 GNUNET_break (0);
257 return GNUNET_SYSERR; 551 return GNUNET_SYSERR;
@@ -259,102 +553,225 @@ check_result (void *cls,
259 return GNUNET_OK; 553 return GNUNET_OK;
260} 554}
261 555
556
262/** 557/**
263 * Handler for messages received from the GNS service 558 * Handle an incoming message of type
559 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
264 * 560 *
265 * @param cls the `struct GNUNET_GNS_Handle *` 561 * @param cls
266 * @param loookup_msg the incoming message 562 * @param msg the message we received
267 */ 563 */
268static void 564static void
269handle_exchange_result (void *cls, 565handle_attribute_result (void *cls,
270 const struct ExchangeResultMessage *erm) 566 const struct AttributeResultMessage *msg)
271{ 567{
272 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; 568 static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
569 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
570 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
273 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 571 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
274 struct GNUNET_IDENTITY_PROVIDER_Token token; 572 size_t attr_len;
275 uint64_t ticket_nonce; 573 uint32_t r_id = ntohl (msg->id);
276 uint32_t r_id = ntohl (erm->id); 574
277 char *str; 575 attr_len = ntohs (msg->attr_len);
278 576 LOG (GNUNET_ERROR_TYPE_DEBUG,
279 for (op = handle->op_head; NULL != op; op = op->next) 577 "Processing attribute result.\n");
578
579
580 for (it = h->it_head; NULL != it; it = it->next)
581 if (it->r_id == r_id)
582 break;
583 for (op = h->op_head; NULL != op; op = op->next)
280 if (op->r_id == r_id) 584 if (op->r_id == r_id)
281 break; 585 break;
282 if (NULL == op) 586 if ((NULL == it) && (NULL == op))
283 return; 587 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 588
589 if ( (0 == (memcmp (&msg->identity,
590 &identity_dummy,
591 sizeof (identity_dummy)))) )
592 {
593 if ((NULL == it) && (NULL == op))
594 {
595 GNUNET_break (0);
596 force_reconnect (h);
597 return;
598 }
599 if (NULL != it)
600 {
601 if (NULL != it->finish_cb)
602 it->finish_cb (it->finish_cb_cls);
603 free_it (it);
604 }
605 if (NULL != op)
606 {
607 if (NULL != op->ar_cb)
608 op->ar_cb (op->cls,
609 NULL,
610 NULL);
611 GNUNET_CONTAINER_DLL_remove (h->op_head,
612 h->op_tail,
613 op);
614 GNUNET_free (op);
615
616 }
617 return;
618 }
619
620 {
621 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
622 attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1],
623 attr_len);
624 if (NULL != it)
625 {
626 if (NULL != it->proc)
627 it->proc (it->proc_cls,
628 &msg->identity,
629 attr);
630 } else if (NULL != op)
631 {
632 if (NULL != op->ar_cb)
633 op->ar_cb (op->cls,
634 &msg->identity,
635 attr);
636
637 }
638 GNUNET_free (attr);
639 return;
640 }
641 GNUNET_assert (0);
296} 642}
297 643
298/** 644/**
299 * Handler for messages received from the GNS service 645 * Handle an incoming message of type
646 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
300 * 647 *
301 * @param cls the `struct GNUNET_GNS_Handle *` 648 * @param cls
302 * @param loookup_msg the incoming message 649 * @param msg the message we received
650 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
651 */
652static int
653check_ticket_result (void *cls,
654 const struct TicketResultMessage *msg)
655{
656 size_t msg_len;
657
658 msg_len = ntohs (msg->header.size);
659 if (msg_len < sizeof (struct TicketResultMessage))
660 {
661 GNUNET_break (0);
662 return GNUNET_SYSERR;
663 }
664 return GNUNET_OK;
665}
666
667
668
669/**
670 * Handle an incoming message of type
671 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
672 *
673 * @param cls
674 * @param msg the message we received
303 */ 675 */
304static void 676static void
305handle_result (void *cls, 677handle_ticket_result (void *cls,
306 const struct IssueResultMessage *irm) 678 const struct TicketResultMessage *msg)
307{ 679{
308 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; 680 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
309 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 681 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
310 struct GNUNET_IDENTITY_PROVIDER_Token token; 682 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
311 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; 683 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
312 uint32_t r_id = ntohl (irm->id); 684 uint32_t r_id = ntohl (msg->id);
313 char *str; 685 size_t msg_len;
314 char *label_str;
315 char *ticket_str;
316 char *token_str;
317 686
318 for (op = handle->op_head; NULL != op; op = op->next) 687 for (op = handle->op_head; NULL != op; op = op->next)
319 if (op->r_id == r_id) 688 if (op->r_id == r_id)
320 break; 689 break;
321 if (NULL == op) 690 for (it = handle->ticket_it_head; NULL != it; it = it->next)
691 if (it->r_id == r_id)
692 break;
693 if ((NULL == op) && (NULL == it))
322 return; 694 return;
323 str = GNUNET_strdup ((char*)&irm[1]); 695 msg_len = ntohs (msg->header.size);
324 label_str = strtok (str, ","); 696 if (NULL != op)
325
326 if (NULL == label_str)
327 { 697 {
328 GNUNET_free (str); 698 GNUNET_CONTAINER_DLL_remove (handle->op_head,
329 GNUNET_break (0); 699 handle->op_tail,
700 op);
701 if (msg_len == sizeof (struct TicketResultMessage))
702 {
703 if (NULL != op->tr_cb)
704 op->tr_cb (op->cls, NULL);
705 } else {
706 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
707 if (NULL != op->tr_cb)
708 op->tr_cb (op->cls, ticket);
709 }
710 GNUNET_free (op);
330 return; 711 return;
331 } 712 } else if (NULL != it) {
332 ticket_str = strtok (NULL, ","); 713 if (msg_len == sizeof (struct TicketResultMessage))
333 if (NULL == ticket_str) 714 {
334 { 715 if (NULL != it->tr_cb)
335 GNUNET_free (str); 716 GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
336 GNUNET_break (0); 717 handle->ticket_it_tail,
718 it);
719 it->finish_cb (it->finish_cb_cls);
720 GNUNET_free (it);
721 } else {
722 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
723 if (NULL != it->tr_cb)
724 it->tr_cb (it->cls, ticket);
725 }
337 return; 726 return;
338 } 727 }
339 token_str = strtok (NULL, ","); 728 GNUNET_break (0);
340 if (NULL == token_str) 729}
730
731/**
732 * Handle an incoming message of type
733 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
734 *
735 * @param cls
736 * @param msg the message we received
737 */
738static void
739handle_revoke_ticket_result (void *cls,
740 const struct RevokeTicketResultMessage *msg)
741{
742 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
743 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
744 uint32_t r_id = ntohl (msg->id);
745 int32_t success;
746
747 LOG (GNUNET_ERROR_TYPE_DEBUG,
748 "Processing revocation result.\n");
749
750
751 for (op = h->op_head; NULL != op; op = op->next)
752 if (op->r_id == r_id)
753 break;
754 if (NULL == op)
755 return;
756 success = ntohl (msg->success);
341 { 757 {
342 GNUNET_free (str); 758 if (NULL != op->rvk_cb)
343 GNUNET_break (0); 759 {
760 op->rvk_cb (op->cls,
761 success,
762 NULL);
763 }
764 GNUNET_CONTAINER_DLL_remove (h->op_head,
765 h->op_tail,
766 op);
767 GNUNET_free (op);
344 return; 768 return;
345 } 769 }
346 GNUNET_CONTAINER_DLL_remove (handle->op_head, 770 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} 771}
357 772
773
774
358/** 775/**
359 * Try again to connect to the service. 776 * Try again to connect to the service.
360 * 777 *
@@ -364,14 +781,26 @@ static void
364reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) 781reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
365{ 782{
366 struct GNUNET_MQ_MessageHandler handlers[] = { 783 struct GNUNET_MQ_MessageHandler handlers[] = {
367 GNUNET_MQ_hd_var_size (result, 784 GNUNET_MQ_hd_fixed_size (attribute_store_response,
368 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT, 785 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE,
369 struct IssueResultMessage, 786 struct AttributeStoreResultMessage,
787 h),
788 GNUNET_MQ_hd_var_size (attribute_result,
789 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT,
790 struct AttributeResultMessage,
370 h), 791 h),
371 GNUNET_MQ_hd_var_size (exchange_result, 792 GNUNET_MQ_hd_var_size (ticket_result,
372 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT, 793 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT,
373 struct ExchangeResultMessage, 794 struct TicketResultMessage,
374 h), 795 h),
796 GNUNET_MQ_hd_var_size (consume_ticket_result,
797 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT,
798 struct ConsumeTicketResultMessage,
799 h),
800 GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
801 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT,
802 struct RevokeTicketResultMessage,
803 h),
375 GNUNET_MQ_handler_end () 804 GNUNET_MQ_handler_end ()
376 }; 805 };
377 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 806 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
@@ -417,111 +846,6 @@ GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
417 846
418 847
419/** 848/**
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 849 * Cancel an operation. Note that the operation MAY still
526 * be executed; this merely cancels the continuation; if the request 850 * be executed; this merely cancels the continuation; if the request
527 * was already transmitted, the service may still choose to complete 851 * was already transmitted, the service may still choose to complete
@@ -566,80 +890,483 @@ GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
566} 890}
567 891
568/** 892/**
569 * Convenience API 893 * Store an attribute. If the attribute is already present,
894 * it is replaced with the new attribute.
895 *
896 * @param h handle to the identity provider
897 * @param pkey private key of the identity
898 * @param name the attribute name
899 * @param value the attribute value
900 * @param cont continuation to call when done
901 * @param cont_cls closure for @a cont
902 * @return handle to abort the request
903 */
904struct GNUNET_IDENTITY_PROVIDER_Operation *
905GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
906 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
907 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
908 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
909 void *cont_cls)
910{
911 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
912 struct AttributeStoreMessage *sam;
913 size_t attr_len;
914
915 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
916 op->h = h;
917 op->as_cb = cont;
918 op->cls = cont_cls;
919 op->r_id = h->r_id_gen++;
920 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
921 h->op_tail,
922 op);
923 attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr);
924 op->env = GNUNET_MQ_msg_extra (sam,
925 attr_len,
926 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE);
927 sam->identity = *pkey;
928 sam->id = htonl (op->r_id);
929
930 GNUNET_IDENTITY_ATTRIBUTE_serialize (attr,
931 (char*)&sam[1]);
932
933 sam->attr_len = htons (attr_len);
934 if (NULL != h->mq)
935 GNUNET_MQ_send_copy (h->mq,
936 op->env);
937 return op;
938
939}
940
941
942/**
943 * List all attributes for a local identity.
944 * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
945 * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
946 * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
947 * immediately, and then again after
948 * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
949 *
950 * On error (disconnect), @a error_cb will be invoked.
951 * On normal completion, @a finish_cb proc will be
952 * invoked.
953 *
954 * @param h handle to the idp
955 * @param identity identity to access
956 * @param error_cb function to call on error (i.e. disconnect),
957 * the handle is afterwards invalid
958 * @param error_cb_cls closure for @a error_cb
959 * @param proc function to call on each attribute; it
960 * will be called repeatedly with a value (if available)
961 * @param proc_cls closure for @a proc
962 * @param finish_cb function to call on completion
963 * the handle is afterwards invalid
964 * @param finish_cb_cls closure for @a finish_cb
965 * @return an iterator handle to use for iteration
966 */
967struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
968GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
969 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
970 GNUNET_SCHEDULER_TaskCallback error_cb,
971 void *error_cb_cls,
972 GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
973 void *proc_cls,
974 GNUNET_SCHEDULER_TaskCallback finish_cb,
975 void *finish_cb_cls)
976{
977 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
978 struct GNUNET_MQ_Envelope *env;
979 struct AttributeIterationStartMessage *msg;
980 uint32_t rid;
981
982 rid = h->r_id_gen++;
983 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator);
984 it->h = h;
985 it->error_cb = error_cb;
986 it->error_cb_cls = error_cb_cls;
987 it->finish_cb = finish_cb;
988 it->finish_cb_cls = finish_cb_cls;
989 it->proc = proc;
990 it->proc_cls = proc_cls;
991 it->r_id = rid;
992 it->identity = *identity;
993 GNUNET_CONTAINER_DLL_insert_tail (h->it_head,
994 h->it_tail,
995 it);
996 env = GNUNET_MQ_msg (msg,
997 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START);
998 msg->id = htonl (rid);
999 msg->identity = *identity;
1000 if (NULL == h->mq)
1001 it->env = env;
1002 else
1003 GNUNET_MQ_send (h->mq,
1004 env);
1005 return it;
1006}
1007
1008
1009/**
1010 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
1011 * for the next record.
1012 *
1013 * @param it the iterator
570 */ 1014 */
1015void
1016GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
1017{
1018 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
1019 struct AttributeIterationNextMessage *msg;
1020 struct GNUNET_MQ_Envelope *env;
1021
1022 env = GNUNET_MQ_msg (msg,
1023 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT);
1024 msg->id = htonl (it->r_id);
1025 GNUNET_MQ_send (h->mq,
1026 env);
1027}
571 1028
572 1029
573/** 1030/**
574 * Destroy token 1031 * Stops iteration and releases the idp handle for further calls. Must
1032 * be called on any iteration that has not yet completed prior to calling
1033 * #GNUNET_IDENTITY_PROVIDER_disconnect.
575 * 1034 *
576 * @param token the token 1035 * @param it the iterator
577 */ 1036 */
578void 1037void
579GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token) 1038GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
1039{
1040 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
1041 struct GNUNET_MQ_Envelope *env;
1042 struct AttributeIterationStopMessage *msg;
1043
1044 if (NULL != h->mq)
1045 {
1046 env = GNUNET_MQ_msg (msg,
1047 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP);
1048 msg->id = htonl (it->r_id);
1049 GNUNET_MQ_send (h->mq,
1050 env);
1051 }
1052 free_it (it);
1053}
1054
1055
1056/** TODO
1057 * Issues a ticket to another identity. The identity may use
1058 * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
1059 * and retrieve the attributes specified in the AttributeList.
1060 *
1061 * @param h the identity provider to use
1062 * @param iss the issuing identity
1063 * @param rp the subject of the ticket (the relying party)
1064 * @param attr the attributes that the relying party is given access to
1065 * @param cb the callback
1066 * @param cb_cls the callback closure
1067 * @return handle to abort the operation
1068 */
1069struct GNUNET_IDENTITY_PROVIDER_Operation *
1070GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1071 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
1072 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
1073 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
1074 GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
1075 void *cb_cls)
1076{
1077 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
1078 struct IssueTicketMessage *tim;
1079 size_t attr_len;
1080
1081 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1082 op->h = h;
1083 op->tr_cb = cb;
1084 op->cls = cb_cls;
1085 op->r_id = h->r_id_gen++;
1086 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1087 h->op_tail,
1088 op);
1089 attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
1090 op->env = GNUNET_MQ_msg_extra (tim,
1091 attr_len,
1092 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET);
1093 tim->identity = *iss;
1094 tim->rp = *rp;
1095 tim->id = htonl (op->r_id);
1096
1097 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
1098 (char*)&tim[1]);
1099
1100 tim->attr_len = htons (attr_len);
1101 if (NULL != h->mq)
1102 GNUNET_MQ_send_copy (h->mq,
1103 op->env);
1104 return op;
1105}
1106
1107/**
1108 * Consumes an issued ticket. The ticket is persisted
1109 * and used to retrieve identity information from the issuer
1110 *
1111 * @param id the identity provider to use
1112 * @param identity the identity that is the subject of the issued ticket (the relying party)
1113 * @param ticket the issued ticket to consume
1114 * @param cb the callback to call
1115 * @param cb_cls the callback closure
1116 * @return handle to abort the operation
1117 */
1118struct GNUNET_IDENTITY_PROVIDER_Operation *
1119GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1120 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1121 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1122 GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
1123 void *cb_cls)
580{ 1124{
581 GNUNET_assert (NULL != token); 1125 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
582 if (NULL != token->data) 1126 struct ConsumeTicketMessage *ctm;
583 GNUNET_free (token->data); 1127
584 GNUNET_free (token); 1128 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1129 op->h = h;
1130 op->ar_cb = cb;
1131 op->cls = cb_cls;
1132 op->r_id = h->r_id_gen++;
1133 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1134 h->op_tail,
1135 op);
1136 op->env = GNUNET_MQ_msg_extra (ctm,
1137 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket),
1138 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET);
1139 ctm->identity = *identity;
1140 ctm->id = htonl (op->r_id);
1141
1142 GNUNET_memcpy ((char*)&ctm[1],
1143 ticket,
1144 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket));
1145
1146 if (NULL != h->mq)
1147 GNUNET_MQ_send_copy (h->mq,
1148 op->env);
1149 return op;
1150
585} 1151}
586 1152
1153
587/** 1154/**
588 * Returns string representation of token. A JSON-Web-Token. 1155 * Lists all tickets that have been issued to remote
1156 * identites (relying parties)
589 * 1157 *
590 * @param token the token 1158 * @param h the identity provider to use
591 * @return The JWT (must be freed) 1159 * @param identity the issuing identity
1160 * @param error_cb function to call on error (i.e. disconnect),
1161 * the handle is afterwards invalid
1162 * @param error_cb_cls closure for @a error_cb
1163 * @param proc function to call on each ticket; it
1164 * will be called repeatedly with a value (if available)
1165 * @param proc_cls closure for @a proc
1166 * @param finish_cb function to call on completion
1167 * the handle is afterwards invalid
1168 * @param finish_cb_cls closure for @a finish_cb
1169 * @return an iterator handle to use for iteration
592 */ 1170 */
593char * 1171struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
594GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token) 1172GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1173 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1174 GNUNET_SCHEDULER_TaskCallback error_cb,
1175 void *error_cb_cls,
1176 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
1177 void *proc_cls,
1178 GNUNET_SCHEDULER_TaskCallback finish_cb,
1179 void *finish_cb_cls)
595{ 1180{
596 return GNUNET_strdup (token->data); 1181 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
1182 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
1183 struct GNUNET_MQ_Envelope *env;
1184 struct TicketIterationStartMessage *msg;
1185 uint32_t rid;
1186
1187 GNUNET_CRYPTO_ecdsa_key_get_public (identity,
1188 &identity_pub);
1189 rid = h->r_id_gen++;
1190 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
1191 it->h = h;
1192 it->error_cb = error_cb;
1193 it->error_cb_cls = error_cb_cls;
1194 it->finish_cb = finish_cb;
1195 it->finish_cb_cls = finish_cb_cls;
1196 it->tr_cb = proc;
1197 it->cls = proc_cls;
1198 it->r_id = rid;
1199 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
1200 h->ticket_it_tail,
1201 it);
1202 env = GNUNET_MQ_msg (msg,
1203 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
1204 msg->id = htonl (rid);
1205 msg->identity = identity_pub;
1206 msg->is_audience = htonl (GNUNET_NO);
1207 if (NULL == h->mq)
1208 it->env = env;
1209 else
1210 GNUNET_MQ_send (h->mq,
1211 env);
1212 return it;
1213
597} 1214}
598 1215
1216
599/** 1217/**
600 * Returns string representation of ticket. Base64-Encoded 1218 * Lists all tickets that have been issued to remote
1219 * identites (relying parties)
601 * 1220 *
602 * @param ticket the ticket 1221 * @param id the identity provider to use
603 * @return the Base64-Encoded ticket 1222 * @param identity the issuing identity
1223 * @param error_cb function to call on error (i.e. disconnect),
1224 * the handle is afterwards invalid
1225 * @param error_cb_cls closure for @a error_cb
1226 * @param proc function to call on each ticket; it
1227 * will be called repeatedly with a value (if available)
1228 * @param proc_cls closure for @a proc
1229 * @param finish_cb function to call on completion
1230 * the handle is afterwards invalid
1231 * @param finish_cb_cls closure for @a finish_cb
1232 * @return an iterator handle to use for iteration
604 */ 1233 */
605char * 1234struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
606GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) 1235GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1236 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1237 GNUNET_SCHEDULER_TaskCallback error_cb,
1238 void *error_cb_cls,
1239 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
1240 void *proc_cls,
1241 GNUNET_SCHEDULER_TaskCallback finish_cb,
1242 void *finish_cb_cls)
607{ 1243{
608 return GNUNET_strdup (ticket->data); 1244 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
1245 struct GNUNET_MQ_Envelope *env;
1246 struct TicketIterationStartMessage *msg;
1247 uint32_t rid;
1248
1249 rid = h->r_id_gen++;
1250 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
1251 it->h = h;
1252 it->error_cb = error_cb;
1253 it->error_cb_cls = error_cb_cls;
1254 it->finish_cb = finish_cb;
1255 it->finish_cb_cls = finish_cb_cls;
1256 it->tr_cb = proc;
1257 it->cls = proc_cls;
1258 it->r_id = rid;
1259 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
1260 h->ticket_it_tail,
1261 it);
1262 env = GNUNET_MQ_msg (msg,
1263 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
1264 msg->id = htonl (rid);
1265 msg->identity = *identity;
1266 msg->is_audience = htonl (GNUNET_YES);
1267 if (NULL == h->mq)
1268 it->env = env;
1269 else
1270 GNUNET_MQ_send (h->mq,
1271 env);
1272 return it;
1273
1274
609} 1275}
610 1276
611/** 1277/**
612 * Created a ticket from a string (Base64 encoded ticket) 1278 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
1279 * for the next record.
613 * 1280 *
614 * @param input Base64 encoded ticket 1281 * @param it the iterator
615 * @param ticket pointer where the ticket is stored
616 * @return GNUNET_OK
617 */ 1282 */
618int 1283void
619GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, 1284GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
620 struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket)
621{ 1285{
622 *ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); 1286 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
623 (*ticket)->data = GNUNET_strdup (input); 1287 struct TicketIterationNextMessage *msg;
624 return GNUNET_OK; 1288 struct GNUNET_MQ_Envelope *env;
1289
1290 env = GNUNET_MQ_msg (msg,
1291 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT);
1292 msg->id = htonl (it->r_id);
1293 GNUNET_MQ_send (h->mq,
1294 env);
625} 1295}
626 1296
627 1297
628/** 1298/**
629 * Destroys a ticket 1299 * Stops iteration and releases the idp handle for further calls. Must
1300 * be called on any iteration that has not yet completed prior to calling
1301 * #GNUNET_IDENTITY_PROVIDER_disconnect.
630 * 1302 *
631 * @param ticket the ticket to destroy 1303 * @param it the iterator
632 */ 1304 */
633void 1305void
634GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) 1306GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
635{ 1307{
636 GNUNET_assert (NULL != ticket); 1308 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
637 if (NULL != ticket->data) 1309 struct GNUNET_MQ_Envelope *env;
638 GNUNET_free (ticket->data); 1310 struct TicketIterationStopMessage *msg;
639 GNUNET_free (ticket); 1311
1312 if (NULL != h->mq)
1313 {
1314 env = GNUNET_MQ_msg (msg,
1315 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP);
1316 msg->id = htonl (it->r_id);
1317 GNUNET_MQ_send (h->mq,
1318 env);
1319 }
1320 GNUNET_free (it);
640} 1321}
641 1322
1323/**
1324 * Revoked an issued ticket. The relying party will be unable to retrieve
1325 * updated attributes.
1326 *
1327 * @param id the identity provider to use
1328 * @param identity the issuing identity
1329 * @param ticket the ticket to revoke
1330 * @param cb the callback
1331 * @param cb_cls the callback closure
1332 * @return handle to abort the operation
1333 */
1334struct GNUNET_IDENTITY_PROVIDER_Operation *
1335GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1336 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1337 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1338 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
1339 void *cb_cls)
1340{
1341 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
1342 struct GNUNET_MQ_Envelope *env;
1343 struct RevokeTicketMessage *msg;
1344 uint32_t rid;
642 1345
1346 rid = h->r_id_gen++;
1347 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1348 op->h = h;
1349 op->rvk_cb = cb;
1350 op->cls = cb_cls;
1351 op->r_id = rid;
1352 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1353 h->op_tail,
1354 op);
1355 env = GNUNET_MQ_msg_extra (msg,
1356 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
1357 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET);
1358 msg->id = htonl (rid);
1359 msg->identity = *identity;
1360 memcpy (&msg[1],
1361 ticket,
1362 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
1363 if (NULL == h->mq)
1364 op->env = env;
1365 else
1366 GNUNET_MQ_send (h->mq,
1367 env);
1368 return op;
1369}
643 1370
644 1371
645 1372
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..ad5a95dc7 100644
--- a/src/identity/plugin_gnsrecord_identity.c
+++ b/src/identity-provider/plugin_gnsrecord_identity_provider.c
@@ -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..594e4788d
--- /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 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
372 */
373static int
374identity_provider_sqlite_store_ticket (void *cls,
375 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
376 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
377{
378 struct Plugin *plugin = cls;
379 size_t attrs_len;
380 char *attrs_ser;
381 int n;
382
383 {
384 /* First delete duplicates */
385 struct GNUNET_SQ_QueryParam dparams[] = {
386 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
387 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
388 GNUNET_SQ_query_param_end
389 };
390 if (GNUNET_OK !=
391 GNUNET_SQ_bind (plugin->delete_ticket,
392 dparams))
393 {
394 LOG_SQLITE (plugin,
395 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
396 "sqlite3_bind_XXXX");
397 GNUNET_SQ_reset (plugin->dbh,
398 plugin->delete_ticket);
399 return GNUNET_SYSERR;
400 }
401 n = sqlite3_step (plugin->delete_ticket);
402 GNUNET_SQ_reset (plugin->dbh,
403 plugin->delete_ticket);
404
405 attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
406 attrs_ser = GNUNET_malloc (attrs_len);
407 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
408 attrs_ser);
409 struct GNUNET_SQ_QueryParam sparams[] = {
410 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
411 GNUNET_SQ_query_param_auto_from_type (&ticket->audience),
412 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
413 GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len),
414 GNUNET_SQ_query_param_end
415 };
416
417 if (GNUNET_OK !=
418 GNUNET_SQ_bind (plugin->store_ticket,
419 sparams))
420 {
421 LOG_SQLITE (plugin,
422 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
423 "sqlite3_bind_XXXX");
424 GNUNET_SQ_reset (plugin->dbh,
425 plugin->store_ticket);
426 return GNUNET_SYSERR;
427 }
428 n = sqlite3_step (plugin->store_ticket);
429 GNUNET_SQ_reset (plugin->dbh,
430 plugin->store_ticket);
431 GNUNET_free (attrs_ser);
432 }
433 switch (n)
434 {
435 case SQLITE_DONE:
436 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
437 "sqlite",
438 "Ticket stored\n");
439 return GNUNET_OK;
440 case SQLITE_BUSY:
441 LOG_SQLITE (plugin,
442 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
443 "sqlite3_step");
444 return GNUNET_NO;
445 default:
446 LOG_SQLITE (plugin,
447 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
448 "sqlite3_step");
449 return GNUNET_SYSERR;
450 }
451}
452
453
454/**
455 * Store a ticket in the database.
456 *
457 * @param cls closure (internal context for the plugin)
458 * @param ticket the ticket to delete
459 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
460 */
461static int
462identity_provider_sqlite_delete_ticket (void *cls,
463 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
464{
465 struct Plugin *plugin = cls;
466 int n;
467
468 {
469 struct GNUNET_SQ_QueryParam sparams[] = {
470 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
471 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
472 GNUNET_SQ_query_param_end
473 };
474
475 if (GNUNET_OK !=
476 GNUNET_SQ_bind (plugin->delete_ticket,
477 sparams))
478 {
479 LOG_SQLITE (plugin,
480 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
481 "sqlite3_bind_XXXX");
482 GNUNET_SQ_reset (plugin->dbh,
483 plugin->store_ticket);
484 return GNUNET_SYSERR;
485 }
486 n = sqlite3_step (plugin->delete_ticket);
487 GNUNET_SQ_reset (plugin->dbh,
488 plugin->delete_ticket);
489 }
490 switch (n)
491 {
492 case SQLITE_DONE:
493 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
494 "sqlite",
495 "Ticket deleted\n");
496 return GNUNET_OK;
497 case SQLITE_BUSY:
498 LOG_SQLITE (plugin,
499 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
500 "sqlite3_step");
501 return GNUNET_NO;
502 default:
503 LOG_SQLITE (plugin,
504 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
505 "sqlite3_step");
506 return GNUNET_SYSERR;
507 }
508}
509
510
511/**
512 * The given 'sqlite' statement has been prepared to be run.
513 * It will return a record which should be given to the iterator.
514 * Runs the statement and parses the returned record.
515 *
516 * @param plugin plugin context
517 * @param stmt to run (and then clean up)
518 * @param iter iterator to call with the result
519 * @param iter_cls closure for @a iter
520 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
521 */
522static int
523get_ticket_and_call_iterator (struct Plugin *plugin,
524 sqlite3_stmt *stmt,
525 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
526 void *iter_cls)
527{
528 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
529 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
530 int ret;
531 int sret;
532 size_t attrs_len;
533 char *attrs_ser;
534
535 ret = GNUNET_NO;
536 if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
537 {
538 struct GNUNET_SQ_ResultSpec rs[] = {
539 GNUNET_SQ_result_spec_auto_from_type (&ticket.identity),
540 GNUNET_SQ_result_spec_auto_from_type (&ticket.audience),
541 GNUNET_SQ_result_spec_uint64 (&ticket.rnd),
542 GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser,
543 &attrs_len),
544 GNUNET_SQ_result_spec_end
545
546 };
547 ret = GNUNET_SQ_extract_result (stmt,
548 rs);
549 if (GNUNET_OK != ret)
550 {
551 GNUNET_break (0);
552 ret = GNUNET_SYSERR;
553 }
554 else
555 {
556 attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (attrs_ser,
557 attrs_len);
558 if (NULL != iter)
559 iter (iter_cls,
560 &ticket,
561 attrs);
562 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
563 ret = GNUNET_YES;
564 }
565 GNUNET_SQ_cleanup_result (rs);
566 }
567 else
568 {
569 if (SQLITE_DONE != sret)
570 LOG_SQLITE (plugin,
571 GNUNET_ERROR_TYPE_ERROR,
572 "sqlite_step");
573 }
574 GNUNET_SQ_reset (plugin->dbh,
575 stmt);
576 return ret;
577}
578
579
580/**
581 * Lookup tickets in the datastore.
582 *
583 * @param cls closure (internal context for the plugin)
584 * @param zone private key of the zone
585 * @param label name of the record in the zone
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..c27662a0d 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 */ 200 */
233 struct GNUNET_NAMESTORE_Handle *ns_handle; 201 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
234 202
235 /** 203 /**
236 * NS iterator 204 * Ticket iterator
237 */ 205 */
238 struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 206 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
239
240 /**
241 * NS Handle
242 */
243 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
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}
449 440
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}
497
520 498
499static void
500add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
501 const char* url,
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;
521 508
522 //Meta info 509 struct RequestHandle *handle = cls;
523 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST, 510 struct EgoEntry *ego_entry;
524 strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST), 511 struct MHD_Response *resp;
525 &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 };
526 523
527 scopes = NULL; 524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
528 if ( GNUNET_YES != 525 handle->url);
529 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 526 if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
530 &key) ) 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 549
560 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); 550 if (0 >= handle->rest_handle->data_size)
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
568 //Remote nonce
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
784 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
785 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
786 &key);
787 667
788 if ( GNUNET_YES != 668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
789 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 669 handle->url);
790 &key) ) 670 if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
671 strlen (handle->url))
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)
875 { 754 {
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 755 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
877 "Ticket nonce %"SCNu64" does not match expected nonce %"SCNu64"\n", 756 "Unable to parse JSONAPI Object from %s\n",
878 ticket_nonce, expected_nonce); 757 term_data);
879 handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n");
880 GNUNET_SCHEDULER_add_now (&do_error, handle); 758 GNUNET_SCHEDULER_add_now (&do_error, handle);
881 return; 759 return;
882 } 760 }
761 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
762 {
763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
764 "Cannot create more than 1 resource! (Got %d)\n",
765 GNUNET_JSONAPI_document_resource_count (json_obj));
766 GNUNET_JSONAPI_document_delete (json_obj);
767 GNUNET_SCHEDULER_add_now (&do_error, handle);
768 return;
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; 842
843 if (NULL == identity)
844 {
845 GNUNET_SCHEDULER_add_now (&return_response, handle);
846 return;
847 }
919 848
920 handle->op = NULL; 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);
921 854
922 if (NULL == ego) 855 value = json_string (attr->data);
856 GNUNET_JSONAPI_resource_add_attr (json_resource,
857 "value",
858 value);
859 json_decref (value);
860}
861
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))
@@ -1104,7 +1115,7 @@ list_ego (void *cls,
1104 * @return GNUNET_OK if request accepted 1115 * @return GNUNET_OK if request accepted
1105 */ 1116 */
1106static void 1117static void
1107rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, 1118rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
1108 GNUNET_REST_ResultProcessor proc, 1119 GNUNET_REST_ResultProcessor proc,
1109 void *proc_cls) 1120 void *proc_cls)
1110{ 1121{
@@ -1114,10 +1125,9 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1114 handle->proc_cls = proc_cls; 1125 handle->proc_cls = proc_cls;
1115 handle->proc = proc; 1126 handle->proc = proc;
1116 handle->state = ID_REST_STATE_INIT; 1127 handle->state = ID_REST_STATE_INIT;
1117 handle->conndata_handle = conndata_handle; 1128 handle->rest_handle = rest_handle;
1118 1129
1119 1130 handle->url = GNUNET_strdup (rest_handle->url);
1120 handle->url = GNUNET_strdup (conndata_handle->url);
1121 if (handle->url[strlen (handle->url)-1] == '/') 1131 if (handle->url[strlen (handle->url)-1] == '/')
1122 handle->url[strlen (handle->url)-1] = '\0'; 1132 handle->url[strlen (handle->url)-1] = '\0';
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1162,8 +1172,8 @@ libgnunet_plugin_rest_identity_provider_init (void *cls)
1162 MHD_HTTP_METHOD_DELETE, 1172 MHD_HTTP_METHOD_DELETE,
1163 MHD_HTTP_METHOD_OPTIONS); 1173 MHD_HTTP_METHOD_OPTIONS);
1164 1174
1165 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1166 _("Identity Token REST API initialized\n")); 1176 _("Identity Provider REST API initialized\n"));
1167 return api; 1177 return api;
1168} 1178}
1169 1179
@@ -1184,8 +1194,8 @@ libgnunet_plugin_rest_identity_provider_done (void *cls)
1184 GNUNET_free_non_null (allow_methods); 1194 GNUNET_free_non_null (allow_methods);
1185 GNUNET_free (api); 1195 GNUNET_free (api);
1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "Identity Token REST plugin is finished\n"); 1197 "Identity Provider REST plugin is finished\n");
1188 return NULL; 1198 return NULL;
1189} 1199}
1190 1200
1191/* end of plugin_rest_gns.c */ 1201/* 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_credential_service.h b/src/include/gnunet_credential_service.h
index 9e765c12b..67c2f2b4c 100644
--- a/src/include/gnunet_credential_service.h
+++ b/src/include/gnunet_credential_service.h
@@ -20,6 +20,7 @@
20 20
21/** 21/**
22 * @author Martin Schanzenbach 22 * @author Martin Schanzenbach
23 * @author Adnan Husain
23 * 24 *
24 * @file 25 * @file
25 * API to the Credential service 26 * API to the Credential service
@@ -34,6 +35,7 @@
34 35
35#include "gnunet_util_lib.h" 36#include "gnunet_util_lib.h"
36#include "gnunet_gns_service.h" 37#include "gnunet_gns_service.h"
38#include "gnunet_identity_service.h"
37 39
38#ifdef __cplusplus 40#ifdef __cplusplus
39extern "C" 41extern "C"
@@ -52,7 +54,157 @@ struct GNUNET_CREDENTIAL_Handle;
52/** 54/**
53 * Handle to control a lookup operation. 55 * Handle to control a lookup operation.
54 */ 56 */
55struct GNUNET_CREDENTIAL_LookupRequest; 57struct GNUNET_CREDENTIAL_Request;
58
59/*
60* Enum used for checking whether the issuer has the authority to issue credentials or is just a subject
61*/
62enum GNUNET_CREDENTIAL_CredentialFlags {
63
64 //Subject had credentials before, but have been revoked now
65 GNUNET_CREDENTIAL_FLAG_REVOKED=0,
66
67 //Subject flag indicates that the subject is a holder of this credential and may present it as such
68 GNUNET_CREDENTIAL_FLAG_SUBJECT=1,
69
70 //Issuer flag is used to signify that the subject is allowed to issue this credential and delegate issuance
71 GNUNET_CREDENTIAL_FLAG_ISSUER=2
72
73};
74
75GNUNET_NETWORK_STRUCT_BEGIN
76/**
77 * The attribute delegation record
78 */
79struct GNUNET_CREDENTIAL_DelegationRecord {
80
81 /**
82 * Number of delegation sets in this record
83 */
84 uint32_t set_count;
85
86 /**
87 * Length of delegation sets
88 */
89 uint64_t data_size;
90 /**
91 * Followed by set_count DelegationSetRecords
92 *
93 */
94};
95
96/**
97 * The attribute delegation record
98 */
99struct GNUNET_CREDENTIAL_DelegationRecordSet {
100
101 /**
102 * Public key of the subject this attribute was delegated to
103 */
104 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
105
106 /**
107 * Length of attribute, may be 0
108 */
109 uint32_t subject_attribute_len;
110};
111
112
113GNUNET_NETWORK_STRUCT_END
114
115/**
116 * The attribute delegation record
117 */
118struct GNUNET_CREDENTIAL_DelegationSet {
119
120 /**
121 * Public key of the subject this attribute was delegated to
122 */
123 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
124
125 uint32_t subject_attribute_len;
126
127 /**
128 * The subject attribute
129 */
130 const char *subject_attribute;
131};
132
133
134/**
135 * A delegation
136 */
137struct GNUNET_CREDENTIAL_Delegation {
138
139 /**
140 * The issuer of the delegation
141 */
142 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
143
144 /**
145 * Public key of the subject this attribute was delegated to
146 */
147 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
148
149 /**
150 * Length of the attribute
151 */
152 uint32_t issuer_attribute_len;
153
154 /**
155 * The attribute
156 */
157 const char *issuer_attribute;
158
159 /**
160 * Length of the attribute
161 */
162 uint32_t subject_attribute_len;
163
164 /**
165 * The attribute
166 */
167 const char *subject_attribute;
168};
169
170
171/**
172 * A credential
173 */
174struct GNUNET_CREDENTIAL_Credential {
175
176 /**
177 * The issuer of the credential
178 */
179 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
180
181 /**
182 * Public key of the subject this credential was issued to
183 */
184 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
185
186 /**
187 * Signature of this credential
188 */
189 struct GNUNET_CRYPTO_EcdsaSignature signature;
190
191 /**
192 * Expiration of this credential
193 */
194 struct GNUNET_TIME_Absolute expiration;
195
196 /**
197 * Length of the attribute
198 */
199 uint32_t issuer_attribute_len;
200
201 /**
202 * The attribute
203 */
204 const char *issuer_attribute;
205
206};
207
56 208
57 209
58/** 210/**
@@ -61,7 +213,7 @@ struct GNUNET_CREDENTIAL_LookupRequest;
61 * @param cfg configuration to use 213 * @param cfg configuration to use
62 * @return handle to the Credential service, or NULL on error 214 * @return handle to the Credential service, or NULL on error
63 */ 215 */
64struct GNUNET_Credential_Handle * 216struct GNUNET_CREDENTIAL_Handle *
65GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); 217GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
66 218
67 219
@@ -75,56 +227,129 @@ GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle);
75 227
76 228
77/** 229/**
78 * Iterator called on obtained result for a Credential lookup. 230 * Iterator called on obtained result for an attribute verification.
79 * 231 *
80 * @param cls closure 232 * @param cls closure
81 * @param issuer the issuer chain 233 * @param d_count the number of delegations processed
82 * @param issuer_len length of issuer chain 234 * @param delegation_chain the delegations processed
83 * @param value the value returned 235 * @param c_count the number of credentials found
236 * @param credential the credentials
84 */ 237 */
85typedef void 238typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls,
86(*GNUNET_CREDENTIAL_LookupResultProcessor) (void *cls, 239 unsigned int d_count,
87 struct GNUNET_IDENTITY_Ego *issuer, 240 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
88 uint16_t issuer_len, 241 unsigned int c_count,
89 const struct GNUNET_CREDENTIAL_Value *value); 242 struct GNUNET_CREDENTIAL_Credential *credential);
90 243
244/**
245 * Iterator called on obtained result for an attribute delegation.
246 *
247 * @param cls closure
248 * @param success GNUNET_YES if successful
249 * @param result the record data that can be handed to the subject
250 */
251typedef void (*GNUNET_CREDENTIAL_DelegateResultProcessor) (void *cls,
252 uint32_t success);
91 253
92/** 254/**
93 * Perform an asynchronous lookup operation for a credential. 255 * Iterator called on obtained result for an attribute delegation removal.
256 *
257 * @param cls closure
258 * @param success GNUNET_YES if successful
259 * @param result the record data that can be handed to the subject
260 */
261typedef void (*GNUNET_CREDENTIAL_RemoveDelegateResultProcessor) (void *cls,
262 uint32_t success);
263
264
265/**
266 * Performs attribute verification.
267 * Checks if there is a delegation chain from
268 * attribute ``issuer_attribute'' issued by the issuer
269 * with public key ``issuer_key'' maps to the attribute
270 * ``subject_attribute'' claimed by the subject with key
271 * ``subject_key''
94 * 272 *
95 * @param handle handle to the Credential service 273 * @param handle handle to the Credential service
96 * @param credential the credential to look up 274 * @param issuer_key the issuer public key
97 * @param subject Ego to check the credential for 275 * @param issuer_attribute the issuer attribute
276 * @param subject_key the subject public key
277 * @param subject_attribute the attribute claimed by the subject
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 * @return handle to the queued request
309 */
310struct GNUNET_CREDENTIAL_Request *
311GNUNET_CREDENTIAL_add_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
312 struct GNUNET_IDENTITY_Ego *issuer,
313 const char *attribute,
314 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
315 const char *delegated_attribute,
316 GNUNET_CREDENTIAL_DelegateResultProcessor proc,
317 void *proc_cls);
318
319/**
320 * Remove a delegation
321 *
322 * @param handle handle to the Credential service
323 * @param issuer the ego that was used to delegate the attribute
324 * @param attribute the name of the attribute that is delegated
118 * @return handle to the queued request 325 * @return handle to the queued request
119 */ 326 */
120struct GNUNET_CREDENTIAL_IssueRequest * 327struct GNUNET_CREDENTIAL_Request *
121GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle, 328GNUNET_CREDENTIAL_remove_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
122 struct GNUNET_IDENTITY_Ego *issuer, 329 struct GNUNET_IDENTITY_Ego *issuer,
123 struct GNUNET_IDENTITY_Ego *subject, 330 const char *attribute,
124 const char *credential, 331 GNUNET_CREDENTIAL_RemoveDelegateResultProcessor proc,
125 struct GNUNET_CREDENTIAL_Value *value, 332 void *proc_cls);
126 GNUNET_CREDENTIAL_IssueResultProcessor proc, 333
127 void *proc_cls); 334
335
336/**
337 * Issue an attribute to a subject
338 *
339 * @param handle handle to the Credential service
340 * @param issuer the ego that should be used to issue the attribute
341 * @param subject the subject of the attribute
342 * @param attribute the name of the attribute
343 * @param expiration the TTL of the credential
344 * @return handle to the queued request
345 */
346struct GNUNET_CREDENTIAL_Credential*
347GNUNET_CREDENTIAL_credential_issue (
348 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
349 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
350 const char *attribute,
351 struct GNUNET_TIME_Absolute *expiration);
352
128 353
129/** 354/**
130 * Remove a credential 355 * Remove a credential
@@ -135,14 +360,15 @@ GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle,
135 * @param credential the name of the credential 360 * @param credential the name of the credential
136 * @return handle to the queued request 361 * @return handle to the queued request
137 */ 362 */
138struct GNUNET_CREDENTIAL_IssueRequest * 363/**
139GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle, 364 struct GNUNET_CREDENTIAL_IssueRequest *
140 struct GNUNET_IDENTITY_Ego *issuer, 365 GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle,
141 struct GNUNET_IDENTITY_Ego *subject, 366 struct GNUNET_IDENTITY_Ego *issuer,
142 const char *credential, 367 struct GNUNET_IDENTITY_Ego *subject,
143 GNUNET_CREDENTIAL_IssueResultProcessor proc, 368 const char *credential,
144 void *proc_cls); 369 GNUNET_CREDENTIAL_IssueResultProcessor proc,
145 370 void *proc_cls);
371 */
146 372
147 373
148/** 374/**
@@ -151,7 +377,7 @@ GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle,
151 * @param lr the lookup request to cancel 377 * @param lr the lookup request to cancel
152 */ 378 */
153void 379void
154GNUNET_CREDENTIAL_lookup_cancel (struct GNUNET_CREDENTIAL_LookupRequest *lr); 380GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *vr);
155 381
156 382
157#if 0 /* keep Emacsens' auto-indent happy */ 383#if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index e886a561c..2fd67ae1b 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -395,6 +395,11 @@ struct GNUNET_CRYPTO_PaillierCiphertext
395 unsigned char bits[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8]; 395 unsigned char bits[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8];
396}; 396};
397 397
398/**
399 * @brief type for ABE master keys
400 */
401struct GNUNET_CRYPTO_AbeMasterKey;
402
398 403
399/* **************** Functions and Macros ************* */ 404/* **************** Functions and Macros ************* */
400 405
@@ -2137,6 +2142,83 @@ GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
2137 const struct GNUNET_CRYPTO_RsaPublicKey *public_key); 2142 const struct GNUNET_CRYPTO_RsaPublicKey *public_key);
2138 2143
2139 2144
2145/**
2146 * @ingroup crypto
2147 * Create a new CP-ABE master key. Caller must free return value.
2148 *
2149 * @return fresh private key; free using #GNUNET_free
2150 */
2151struct GNUNET_CRYPTO_AbeMasterKey *
2152GNUNET_CRYPTO_cpabe_create_master_key (void);
2153void
2154GNUNET_CRYPTO_cpabe_delete_master_key (struct GNUNET_CRYPTO_AbeMasterKey *key);
2155
2156/**
2157 * @ingroup crypto
2158 * Create a new CP-ABE key. Caller must free return value.
2159 *
2160 * @return fresh private key; free using #GNUNET_free
2161 */
2162struct GNUNET_CRYPTO_AbeKey *
2163GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *msk,
2164 char **attrs);
2165void
2166GNUNET_CRYPTO_cpabe_delete_key (struct GNUNET_CRYPTO_AbeKey *key,
2167 int delete_pub);
2168
2169
2170/**
2171 * @ingroup crypto
2172 * Encrypt a block using sessionkey.
2173 *
2174 * @param block the block to encrypt
2175 * @param size the size of the @a block
2176 * @param sessionkey the key used to encrypt
2177 * @param iv the initialization vector to use, use INITVALUE
2178 * for streams.
2179 * @return the size of the encrypted block, -1 for errors
2180 */
2181ssize_t
2182GNUNET_CRYPTO_cpabe_encrypt (const void *block,
2183 size_t size,
2184 const char *policy,
2185 const struct GNUNET_CRYPTO_AbeMasterKey *key,
2186 void **result);
2187
2188/**
2189 * @ingroup crypto
2190 * Encrypt a block using sessionkey.
2191 *
2192 * @param block the block to encrypt
2193 * @param size the size of the @a block
2194 * @param sessionkey the key used to encrypt
2195 * @param iv the initialization vector to use, use INITVALUE
2196 * for streams.
2197 * @return the size of the encrypted block, -1 for errors
2198 */
2199ssize_t
2200GNUNET_CRYPTO_cpabe_decrypt (const void *block,
2201 size_t size,
2202 const struct GNUNET_CRYPTO_AbeKey *key,
2203 void **result);
2204
2205ssize_t
2206GNUNET_CRYPTO_cpabe_serialize_key (const struct GNUNET_CRYPTO_AbeKey *key,
2207 void **result);
2208
2209struct GNUNET_CRYPTO_AbeKey*
2210GNUNET_CRYPTO_cpabe_deserialize_key (const void *data,
2211 size_t len);
2212
2213ssize_t
2214GNUNET_CRYPTO_cpabe_serialize_master_key (const struct GNUNET_CRYPTO_AbeMasterKey *key,
2215 void **result);
2216
2217struct GNUNET_CRYPTO_AbeMasterKey*
2218GNUNET_CRYPTO_cpabe_deserialize_master_key (const void *data,
2219 size_t len);
2220
2221
2140#if 0 /* keep Emacsens' auto-indent happy */ 2222#if 0 /* keep Emacsens' auto-indent happy */
2141{ 2223{
2142#endif 2224#endif
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..a6c9e1f1c
--- /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 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..6bc05d0f4 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,309 @@ 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 attr the attribute
116 * @param aud audience (identity)
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 */ 135 */
124struct GNUNET_IDENTITY_PROVIDER_Operation * 136typedef void
125GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id, 137(*GNUNET_IDENTITY_PROVIDER_AttributeResult) (void *cls,
126 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key, 138 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
127 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, 139 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
128 const char* scope, 140
129 struct GNUNET_TIME_Absolute expiration,
130 uint64_t nonce,
131 GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
132 void *cb_cls);
133 141
134 142
135/** 143/**
136 * Exchange a ticket for a token. Intended to be used by audience that 144 * List all attributes for a local identity.
137 * received a ticket. 145 * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
146 * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
147 * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
148 * immediately, and then again after
149 * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
138 * 150 *
139 * @param id identity provider service to use 151 * On error (disconnect), @a error_cb will be invoked.
140 * @param ticket the ticket to exchange 152 * On normal completion, @a finish_cb proc will be
141 * @param aud_privkey the audience of the ticket 153 * invoked.
142 * @param cont function to call once the operation finished 154 *
143 * @param cont_cls closure for @a cont 155 * @param h handle to the idp
144 * @return handle to abort the operation 156 * @param identity identity to access
157 * @param error_cb function to call on error (i.e. disconnect),
158 * the handle is afterwards invalid
159 * @param error_cb_cls closure for @a error_cb
160 * @param proc function to call on each attribute; it
161 * will be called repeatedly with a value (if available)
162 * @param proc_cls closure for @a proc
163 * @param finish_cb function to call on completion
164 * the handle is afterwards invalid
165 * @param finish_cb_cls closure for @a finish_cb
166 * @return an iterator handle to use for iteration
145 */ 167 */
146struct GNUNET_IDENTITY_PROVIDER_Operation * 168struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
147GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id, 169GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
148 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, 170 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
149 const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey, 171 GNUNET_SCHEDULER_TaskCallback error_cb,
150 GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont, 172 void *error_cb_cls,
151 void *cont_cls); 173 GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
174 void *proc_cls,
175 GNUNET_SCHEDULER_TaskCallback finish_cb,
176 void *finish_cb_cls);
152 177
153 178
154/** 179/**
155 * Disconnect from identity provider service. 180 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
181 * for the next record.
156 * 182 *
157 * @param h identity provider service to disconnect 183 * @param it the iterator
158 */ 184 */
159void 185void
160GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); 186GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
161 187
162 188
163/** 189/**
164 * Cancel an identity provider operation. Note that the operation MAY still 190 * Stops iteration and releases the idp handle for further calls. Must
165 * be executed; this merely cancels the continuation; if the request 191 * be called on any iteration that has not yet completed prior to calling
166 * was already transmitted, the service may still choose to complete 192 * #GNUNET_IDENTITY_PROVIDER_disconnect.
167 * the operation.
168 * 193 *
169 * @param op operation to cancel 194 * @param it the iterator
170 */ 195 */
171void 196void
172GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op); 197GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
173 198
174 199
175/** 200/**
176 * Convenience API 201 * Method called when a token has been issued.
202 * On success returns a ticket that can be given to the audience to retrive the
203 * token
204 *
205 * @param cls closure
206 * @param ticket the ticket
177 */ 207 */
208typedef void
209(*GNUNET_IDENTITY_PROVIDER_TicketCallback)(void *cls,
210 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
178 211
179/** 212/**
180 * Destroy token 213 * Issues a ticket to another identity. The identity may use
214 * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
215 * and retrieve the attributes specified in the AttributeList.
181 * 216 *
182 * @param token the token 217 * @param id the identity provider to use
218 * @param iss the issuing identity
219 * @param rp the subject of the ticket (the relying party)
220 * @param attr the attributes that the relying party is given access to
221 * @param cb the callback
222 * @param cb_cls the callback closure
223 * @return handle to abort the operation
183 */ 224 */
184void 225struct GNUNET_IDENTITY_PROVIDER_Operation *
185GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token); 226GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
227 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
228 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
229 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
230 GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
231 void *cb_cls);
186 232
187/** 233/**
188 * Returns string representation of token. A JSON-Web-Token. 234 * Revoked an issued ticket. The relying party will be unable to retrieve
235 * updated attributes.
189 * 236 *
190 * @param token the token 237 * @param id the identity provider to use
191 * @return The JWT (must be freed) 238 * @param identity the issuing identity
239 * @param ticket the ticket to revoke
240 * @param cb the callback
241 * @param cb_cls the callback closure
242 * @return handle to abort the operation
192 */ 243 */
193char * 244struct GNUNET_IDENTITY_PROVIDER_Operation *
194GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token); 245GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
246 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
247 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
248 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
249 void *cb_cls);
250
251
195 252
196/** 253/**
197 * Returns string representation of ticket. Base64-Encoded 254 * Consumes an issued ticket. The ticket is persisted
255 * and used to retrieve identity information from the issuer
198 * 256 *
199 * @param ticket the ticket 257 * @param id the identity provider to use
200 * @return the Base64-Encoded ticket 258 * @param identity the identity that is the subject of the issued ticket (the audience)
259 * @param ticket the issued ticket to consume
260 * @param cb the callback to call
261 * @param cb_cls the callback closure
262 * @return handle to abort the operation
263 */
264struct GNUNET_IDENTITY_PROVIDER_Operation *
265GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
266 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
267 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
268 GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
269 void *cb_cls);
270
271/**
272 * Lists all tickets that have been issued to remote
273 * identites (relying parties)
274 *
275 * @param h the identity provider to use
276 * @param identity the issuing identity
277 * @param error_cb function to call on error (i.e. disconnect),
278 * the handle is afterwards invalid
279 * @param error_cb_cls closure for @a error_cb
280 * @param proc function to call on each ticket; it
281 * will be called repeatedly with a value (if available)
282 * @param proc_cls closure for @a proc
283 * @param finish_cb function to call on completion
284 * the handle is afterwards invalid
285 * @param finish_cb_cls closure for @a finish_cb
286 * @return an iterator handle to use for iteration
287 */
288struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
289GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
290 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
291 GNUNET_SCHEDULER_TaskCallback error_cb,
292 void *error_cb_cls,
293 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
294 void *proc_cls,
295 GNUNET_SCHEDULER_TaskCallback finish_cb,
296 void *finish_cb_cls);
297
298/**
299 * Lists all tickets that have been issued to remote
300 * identites (relying parties)
301 *
302 * @param id the identity provider to use
303 * @param identity the issuing identity
304 * @param error_cb function to call on error (i.e. disconnect),
305 * the handle is afterwards invalid
306 * @param error_cb_cls closure for @a error_cb
307 * @param proc function to call on each ticket; it
308 * will be called repeatedly with a value (if available)
309 * @param proc_cls closure for @a proc
310 * @param finish_cb function to call on completion
311 * the handle is afterwards invalid
312 * @param finish_cb_cls closure for @a finish_cb
313 * @return an iterator handle to use for iteration
201 */ 314 */
202char * 315struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
203GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); 316GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
317 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
318 GNUNET_SCHEDULER_TaskCallback error_cb,
319 void *error_cb_cls,
320 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
321 void *proc_cls,
322 GNUNET_SCHEDULER_TaskCallback finish_cb,
323 void *finish_cb_cls);
204 324
205/** 325/**
206 * Created a ticket from a string (Base64 encoded ticket) 326 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
327 * for the next record.
207 * 328 *
208 * @param input Base64 encoded ticket 329 * @param it the iterator
209 * @param ticket pointer where the ticket is stored
210 * @return GNUNET_OK
211 */ 330 */
212int 331void
213GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, 332GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
214 struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket);
215 333
216/** 334/**
217 * Destroys a ticket 335 * Stops iteration and releases the idp handle for further calls. Must
336 * be called on any iteration that has not yet completed prior to calling
337 * #GNUNET_IDENTITY_PROVIDER_disconnect.
218 * 338 *
219 * @param ticket the ticket to destroy 339 * @param it the iterator
220 */ 340 */
221void 341void
222GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); 342GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
343
344/**
345 * Disconnect from identity provider service.
346 *
347 * @param h identity provider service to disconnect
348 */
349void
350GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
351
352
353/**
354 * Cancel an identity provider operation. Note that the operation MAY still
355 * be executed; this merely cancels the continuation; if the request
356 * was already transmitted, the service may still choose to complete
357 * the operation.
358 *
359 * @param op operation to cancel
360 */
361void
362GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op);
223 363
224#if 0 /* keep Emacsens' auto-indent happy */ 364#if 0 /* keep Emacsens' auto-indent happy */
225{ 365{
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_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..cc9ff4745 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -119,11 +119,22 @@ libgnunetutil_la_LIBADD = \
119 $(LTLIBINTL) \ 119 $(LTLIBINTL) \
120 -lltdl $(Z_LIBS) -lunistring $(XLIB) 120 -lltdl $(Z_LIBS) -lunistring $(XLIB)
121 121
122if HAVE_PBC
123if HAVE_ABE
124libgnunetutil_la_SOURCES += \
125 crypto_abe.c
126libgnunetutil_la_LIBADD += \
127 $(ABE_LIBADD) \
128 -lgabe \
129 -lpbc \
130 -lglib-2.0
131endif
132endif
133
122libgnunetutil_la_LDFLAGS = \ 134libgnunetutil_la_LDFLAGS = \
123 $(GN_LIB_LDFLAGS) \ 135 $(GN_LIB_LDFLAGS) \
124 -version-info 13:0:0 136 -version-info 13:0:0
125 137
126
127libgnunetutil_taler_wallet_la_SOURCES = \ 138libgnunetutil_taler_wallet_la_SOURCES = \
128 common_allocation.c \ 139 common_allocation.c \
129 common_endian.c \ 140 common_endian.c \
@@ -553,6 +564,17 @@ test_speedup_SOURCES = \
553test_speedup_LDADD = \ 564test_speedup_LDADD = \
554 libgnunetutil.la 565 libgnunetutil.la
555 566
567if HAVE_PBC
568if HAVE_ABE
569test_crypto_abe_SOURCES = \
570 test_crypto_abe.c
571test_crypto_abe_LDADD = \
572 libgnunetutil.la
573check_PROGRAMS += \
574 test_crypto_abe
575endif
576endif
577
556perf_crypto_hash_SOURCES = \ 578perf_crypto_hash_SOURCES = \
557 perf_crypto_hash.c 579 perf_crypto_hash.c
558perf_crypto_hash_LDADD = \ 580perf_crypto_hash_LDADD = \
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}
diff --git a/src/util/test_crypto_abe.c b/src/util/test_crypto_abe.c
new file mode 100644
index 000000000..cb36dccae
--- /dev/null
+++ b/src/util/test_crypto_abe.c
@@ -0,0 +1,86 @@
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
29#define TESTSTRING "Hello World!"
30
31static int
32testAbecipher ()
33{
34 struct GNUNET_CRYPTO_AbeMasterKey *msk;
35 struct GNUNET_CRYPTO_AbeKey *key;
36 char *result;
37 char **attrs;
38 int size;
39 char *res;
40 msk = GNUNET_CRYPTO_cpabe_create_master_key ();
41 size = GNUNET_CRYPTO_cpabe_encrypt (TESTSTRING, strlen (TESTSTRING) + 1,
42 "testattr", //Policy
43 msk,
44 (void*)&result);
45 GNUNET_assert (-1 != size);
46 attrs = GNUNET_malloc (2 * sizeof (char*));
47 attrs[0] = "testattr";
48 attrs[1] = NULL;
49 key = GNUNET_CRYPTO_cpabe_create_key (msk,
50 attrs);
51
52 size = GNUNET_CRYPTO_cpabe_decrypt (result, size,
53 key,
54 (void*)&res);
55 if (strlen (TESTSTRING) + 1 != size)
56 {
57 printf ("abeciphertest failed: decryptBlock returned %d\n", size);
58 return 1;
59 }
60 if (0 != strcmp (res, TESTSTRING))
61 {
62 printf ("abeciphertest failed: %s != %s\n", res, TESTSTRING);
63 return 1;
64 }
65 else
66 return 0;
67}
68
69
70int
71main (int argc, char *argv[])
72{
73 int failureCount = 0;
74
75 GNUNET_log_setup ("test-crypto-abe", "WARNING", NULL);
76 failureCount += testAbecipher ();
77
78 if (failureCount != 0)
79 {
80 printf ("%d TESTS FAILED!\n", failureCount);
81 return -1;
82 }
83 return 0;
84}
85
86/* end of test_crypto_aes.c */