aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README9
-rw-r--r--configure.ac25
-rw-r--r--contrib/Dockerfile63
-rw-r--r--contrib/docker-entrypoint.sh3
-rw-r--r--po/POTFILES.in134
-rw-r--r--src/Makefile.am14
-rw-r--r--src/abe/Makefile.am50
-rw-r--r--src/abe/abe.c499
-rw-r--r--src/abe/test_cpabe.c87
-rw-r--r--src/credential/Makefile.am112
-rw-r--r--src/credential/credential.conf.in5
-rw-r--r--src/credential/credential.h221
-rw-r--r--src/credential/credential_api.c511
-rw-r--r--src/credential/credential_misc.c168
-rw-r--r--src/credential/credential_misc.h35
-rw-r--r--src/credential/credential_serialization.c460
-rw-r--r--src/credential/credential_serialization.h159
-rw-r--r--src/credential/gnunet-credential.c588
-rw-r--r--src/credential/gnunet-service-credential.c1160
-rw-r--r--src/credential/plugin_gnsrecord_credential.c353
-rw-r--r--src/credential/plugin_rest_credential.c1146
-rwxr-xr-xsrc/credential/test_credential_collect.sh47
-rwxr-xr-xsrc/credential/test_credential_collect_rest.sh90
-rw-r--r--src/credential/test_credential_defaults.conf24
-rwxr-xr-xsrc/credential/test_credential_issue.sh44
-rwxr-xr-xsrc/credential/test_credential_issue_rest.sh53
-rw-r--r--src/credential/test_credential_lookup.conf28
-rwxr-xr-xsrc/credential/test_credential_verify.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_and.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_rest.sh87
-rwxr-xr-xsrc/credential/test_credential_verify_simple.sh50
-rw-r--r--src/exit/gnunet-daemon-exit.c2
-rw-r--r--src/gns/gns_api.c11
-rw-r--r--src/gns/plugin_gnsrecord_gns.c67
-rw-r--r--src/identity-attribute/Makefile.am44
-rw-r--r--src/identity-attribute/identity_attribute.c421
-rw-r--r--src/identity-attribute/identity_attribute.h56
-rw-r--r--src/identity-attribute/plugin_identity_attribute_gnuid.c184
-rw-r--r--src/identity-provider/Makefile.am74
-rw-r--r--src/identity-provider/gnunet-identity-token.c179
-rw-r--r--src/identity-provider/gnunet-idp.c439
-rw-r--r--src/identity-provider/gnunet-service-identity-provider.c3064
-rw-r--r--src/identity-provider/identity-provider.conf4
-rw-r--r--src/identity-provider/identity_provider.h307
-rw-r--r--src/identity-provider/identity_provider_api.c1213
-rw-r--r--src/identity-provider/identity_token.c964
-rw-r--r--src/identity-provider/identity_token.h346
-rw-r--r--src/identity-provider/jwt.c180
-rw-r--r--src/identity-provider/plugin_gnsrecord_identity_provider.c (renamed from src/identity/plugin_gnsrecord_identity.c)48
-rw-r--r--src/identity-provider/plugin_identity_provider_sqlite.c736
-rw-r--r--src/identity-provider/plugin_rest_identity_provider.c1119
-rw-r--r--src/identity-provider/test_idp.conf28
-rwxr-xr-xsrc/identity-provider/test_idp.sh31
-rwxr-xr-xsrc/identity-provider/test_idp_attribute.sh40
-rwxr-xr-xsrc/identity-provider/test_idp_consume.sh43
-rw-r--r--src/identity-provider/test_idp_defaults.conf24
-rwxr-xr-xsrc/identity-provider/test_idp_issue.sh42
-rwxr-xr-xsrc/identity-provider/test_idp_revoke.sh60
-rw-r--r--src/identity/Makefile.am11
-rw-r--r--src/identity/plugin_rest_identity.c3
-rw-r--r--src/include/gnunet_abe_lib.h193
-rw-r--r--src/include/gnunet_credential_service.h297
-rw-r--r--src/include/gnunet_gnsrecord_lib.h22
-rw-r--r--src/include/gnunet_identity_attribute_lib.h277
-rw-r--r--src/include/gnunet_identity_attribute_plugin.h149
-rw-r--r--src/include/gnunet_identity_provider_plugin.h123
-rw-r--r--src/include/gnunet_identity_provider_service.h333
-rw-r--r--src/include/gnunet_jsonapi_lib.h2
-rw-r--r--src/include/gnunet_protocols.h42
-rw-r--r--src/include/gnunet_rest_lib.h4
-rw-r--r--src/include/gnunet_rest_plugin.h2
-rw-r--r--src/include/gnunet_signatures.h5
-rw-r--r--src/jsonapi/jsonapi_document.c32
-rw-r--r--src/jsonapi/jsonapi_resource.c6
-rw-r--r--src/namestore/plugin_rest_namestore.c27
-rw-r--r--src/rest/rest.conf1
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/crypto_abe.c416
78 files changed, 14264 insertions, 3795 deletions
diff --git a/README b/README
index db64bc17a..ef30fe7e3 100644
--- a/README
+++ b/README
@@ -15,8 +15,11 @@ GNU package (http://www.gnu.org/).
15This is an ALPHA release. There are known and significant bugs as 15This is an ALPHA release. There are known and significant bugs as
16well as many missing features in this release. 16well as many missing features in this release.
17 17
18GNUnet is free software released under the GNU General Public License
19(v3 or later). For details see the COPYING file in this directory.
20
18Additional documentation about GNUnet can be found at 21Additional documentation about GNUnet can be found at
19https://gnunet.org/. 22https://gnunet.org/ and in the doc/ folder.
20 23
21 24
22Dependencies: 25Dependencies:
@@ -63,6 +66,8 @@ How to install?
63The fastest way is to use a binary package if it is available for your 66The fastest way is to use a binary package if it is available for your
64system. For a more detailed description, read the installation 67system. For a more detailed description, read the installation
65instructions on the webpage at https://gnunet.org/installation. 68instructions on the webpage at https://gnunet.org/installation.
69Generic installation instructions are in the INSTALL file in this
70directory.
66 71
67Note that some functions of GNUnet require "root" access. GNUnet will 72Note that some functions of GNUnet require "root" access. GNUnet will
68install (tiny) SUID binaries for those functions is you run "make 73install (tiny) SUID binaries for those functions is you run "make
@@ -300,7 +305,7 @@ Stay tuned
300 305
301* https://gnunet.org/ 306* https://gnunet.org/
302* https://gnunet.org/bugs/ 307* https://gnunet.org/bugs/
303* https://gnunet.org/svn/ 308* https://gnunet.org/git/
304* http://www.gnu.org/software/gnunet/ 309* http://www.gnu.org/software/gnunet/
305* http://mail.gnu.org/mailman/listinfo/gnunet-developers 310* http://mail.gnu.org/mailman/listinfo/gnunet-developers
306* http://mail.gnu.org/mailman/listinfo/help-gnunet 311* http://mail.gnu.org/mailman/listinfo/help-gnunet
diff --git a/configure.ac b/configure.ac
index eae03b01b..017b4836c 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,8 @@ 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/abe/Makefile
1662src/identity-attribute/Makefile
1638src/identity-provider/Makefile 1663src/identity-provider/Makefile
1639pkgconfig/Makefile 1664pkgconfig/Makefile
1640pkgconfig/gnunetarm.pc 1665pkgconfig/gnunetarm.pc
diff --git a/contrib/Dockerfile b/contrib/Dockerfile
new file mode 100644
index 000000000..5a193a46d
--- /dev/null
+++ b/contrib/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/contrib/docker-entrypoint.sh b/contrib/docker-entrypoint.sh
new file mode 100644
index 000000000..807d86d6f
--- /dev/null
+++ b/contrib/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..2fcb74c09 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,15 +1,24 @@
1src/abe/abe.c
1src/arm/arm_api.c 2src/arm/arm_api.c
2src/arm/arm_monitor_api.c 3src/arm/arm_monitor_api.c
3src/arm/gnunet-arm.c 4src/arm/gnunet-arm.c
4src/arm/gnunet-service-arm.c 5src/arm/gnunet-service-arm.c
5src/arm/mockup-service.c 6src/arm/mockup-service.c
7src/ats-tests/ats-testing-experiment.c
8src/ats-tests/ats-testing-log.c
9src/ats-tests/ats-testing-preferences.c
10src/ats-tests/ats-testing-traffic.c
11src/ats-tests/ats-testing.c
12src/ats-tests/gnunet-ats-sim.c
13src/ats-tests/gnunet-solver-eval.c
14src/ats-tool/gnunet-ats.c
6src/ats/ats_api_connectivity.c 15src/ats/ats_api_connectivity.c
7src/ats/ats_api_performance.c 16src/ats/ats_api_performance.c
8src/ats/ats_api_scanner.c 17src/ats/ats_api_scanner.c
9src/ats/ats_api_scheduling.c 18src/ats/ats_api_scheduling.c
10src/ats/gnunet-ats-solver-eval.c 19src/ats/gnunet-ats-solver-eval.c
11src/ats/gnunet-service-ats_addresses.c
12src/ats/gnunet-service-ats.c 20src/ats/gnunet-service-ats.c
21src/ats/gnunet-service-ats_addresses.c
13src/ats/gnunet-service-ats_connectivity.c 22src/ats/gnunet-service-ats_connectivity.c
14src/ats/gnunet-service-ats_normalization.c 23src/ats/gnunet-service-ats_normalization.c
15src/ats/gnunet-service-ats_performance.c 24src/ats/gnunet-service-ats_performance.c
@@ -20,14 +29,6 @@ src/ats/gnunet-service-ats_scheduling.c
20src/ats/plugin_ats_mlp.c 29src/ats/plugin_ats_mlp.c
21src/ats/plugin_ats_proportional.c 30src/ats/plugin_ats_proportional.c
22src/ats/plugin_ats_ril.c 31src/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 32src/auction/gnunet-auction-create.c
32src/auction/gnunet-auction-info.c 33src/auction/gnunet-auction-info.c
33src/auction/gnunet-auction-join.c 34src/auction/gnunet-auction-join.c
@@ -39,8 +40,8 @@ src/block/plugin_block_test.c
39src/cadet/cadet_api.c 40src/cadet/cadet_api.c
40src/cadet/cadet_test_lib.c 41src/cadet/cadet_test_lib.c
41src/cadet/desirability_table.c 42src/cadet/desirability_table.c
42src/cadet/gnunet-cadet.c
43src/cadet/gnunet-cadet-profiler.c 43src/cadet/gnunet-cadet-profiler.c
44src/cadet/gnunet-cadet.c
44src/cadet/gnunet-service-cadet.c 45src/cadet/gnunet-service-cadet.c
45src/cadet/gnunet-service-cadet_channel.c 46src/cadet/gnunet-service-cadet_channel.c
46src/cadet/gnunet-service-cadet_connection.c 47src/cadet/gnunet-service-cadet_connection.c
@@ -56,15 +57,15 @@ src/consensus/gnunet-service-consensus.c
56src/consensus/plugin_block_consensus.c 57src/consensus/plugin_block_consensus.c
57src/conversation/conversation_api.c 58src/conversation/conversation_api.c
58src/conversation/conversation_api_call.c 59src/conversation/conversation_api_call.c
59src/conversation/gnunet-conversation.c
60src/conversation/gnunet-conversation-test.c 60src/conversation/gnunet-conversation-test.c
61src/conversation/gnunet_gst.c 61src/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 62src/conversation/gnunet-helper-audio-playback-gst.c
65src/conversation/gnunet-helper-audio-record.c 63src/conversation/gnunet-helper-audio-playback.c
66src/conversation/gnunet-helper-audio-record-gst.c 64src/conversation/gnunet-helper-audio-record-gst.c
65src/conversation/gnunet-helper-audio-record.c
67src/conversation/gnunet-service-conversation.c 66src/conversation/gnunet-service-conversation.c
67src/conversation/gnunet_gst.c
68src/conversation/gnunet_gst_test.c
68src/conversation/microphone.c 69src/conversation/microphone.c
69src/conversation/plugin_gnsrecord_conversation.c 70src/conversation/plugin_gnsrecord_conversation.c
70src/conversation/speaker.c 71src/conversation/speaker.c
@@ -75,6 +76,13 @@ src/core/gnunet-service-core.c
75src/core/gnunet-service-core_kx.c 76src/core/gnunet-service-core_kx.c
76src/core/gnunet-service-core_sessions.c 77src/core/gnunet-service-core_sessions.c
77src/core/gnunet-service-core_typemap.c 78src/core/gnunet-service-core_typemap.c
79src/credential/credential_api.c
80src/credential/credential_misc.c
81src/credential/credential_serialization.c
82src/credential/gnunet-credential.c
83src/credential/gnunet-service-credential.c
84src/credential/plugin_gnsrecord_credential.c
85src/credential/plugin_rest_credential.c
78src/curl/curl.c 86src/curl/curl.c
79src/curl/curl_reschedule.c 87src/curl/curl_reschedule.c
80src/datacache/datacache.c 88src/datacache/datacache.c
@@ -94,7 +102,6 @@ src/dht/dht_api.c
94src/dht/dht_test_lib.c 102src/dht/dht_test_lib.c
95src/dht/gnunet-dht-get.c 103src/dht/gnunet-dht-get.c
96src/dht/gnunet-dht-monitor.c 104src/dht/gnunet-dht-monitor.c
97src/dht/gnunet_dht_profiler.c
98src/dht/gnunet-dht-put.c 105src/dht/gnunet-dht-put.c
99src/dht/gnunet-service-dht.c 106src/dht/gnunet-service-dht.c
100src/dht/gnunet-service-dht_clients.c 107src/dht/gnunet-service-dht_clients.c
@@ -103,6 +110,7 @@ src/dht/gnunet-service-dht_hello.c
103src/dht/gnunet-service-dht_neighbours.c 110src/dht/gnunet-service-dht_neighbours.c
104src/dht/gnunet-service-dht_nse.c 111src/dht/gnunet-service-dht_nse.c
105src/dht/gnunet-service-dht_routing.c 112src/dht/gnunet-service-dht_routing.c
113src/dht/gnunet_dht_profiler.c
106src/dht/plugin_block_dht.c 114src/dht/plugin_block_dht.c
107src/dns/dns_api.c 115src/dns/dns_api.c
108src/dns/dnsparser.c 116src/dns/dnsparser.c
@@ -117,8 +125,8 @@ src/dv/gnunet-dv.c
117src/dv/gnunet-service-dv.c 125src/dv/gnunet-service-dv.c
118src/dv/plugin_transport_dv.c 126src/dv/plugin_transport_dv.c
119src/exit/gnunet-daemon-exit.c 127src/exit/gnunet-daemon-exit.c
120src/exit/gnunet-helper-exit.c
121src/exit/gnunet-helper-exit-windows.c 128src/exit/gnunet-helper-exit-windows.c
129src/exit/gnunet-helper-exit.c
122src/fragmentation/defragmentation.c 130src/fragmentation/defragmentation.c
123src/fragmentation/fragmentation.c 131src/fragmentation/fragmentation.c
124src/fs/fs_api.c 132src/fs/fs_api.c
@@ -143,8 +151,8 @@ src/fs/gnunet-auto-share.c
143src/fs/gnunet-daemon-fsprofiler.c 151src/fs/gnunet-daemon-fsprofiler.c
144src/fs/gnunet-directory.c 152src/fs/gnunet-directory.c
145src/fs/gnunet-download.c 153src/fs/gnunet-download.c
146src/fs/gnunet-fs.c
147src/fs/gnunet-fs-profiler.c 154src/fs/gnunet-fs-profiler.c
155src/fs/gnunet-fs.c
148src/fs/gnunet-helper-fs-publish.c 156src/fs/gnunet-helper-fs-publish.c
149src/fs/gnunet-publish.c 157src/fs/gnunet-publish.c
150src/fs/gnunet-search.c 158src/fs/gnunet-search.c
@@ -162,10 +170,10 @@ src/fs/plugin_block_fs.c
162src/gns/gns_api.c 170src/gns/gns_api.c
163src/gns/gnunet-bcd.c 171src/gns/gnunet-bcd.c
164src/gns/gnunet-dns2gns.c 172src/gns/gnunet-dns2gns.c
165src/gns/gnunet-gns.c
166src/gns/gnunet-gns-helper-service-w32.c 173src/gns/gnunet-gns-helper-service-w32.c
167src/gns/gnunet-gns-import.c 174src/gns/gnunet-gns-import.c
168src/gns/gnunet-gns-proxy.c 175src/gns/gnunet-gns-proxy.c
176src/gns/gnunet-gns.c
169src/gns/gnunet-service-gns.c 177src/gns/gnunet-service-gns.c
170src/gns/gnunet-service-gns_interceptor.c 178src/gns/gnunet-service-gns_interceptor.c
171src/gns/gnunet-service-gns_resolver.c 179src/gns/gnunet-service-gns_resolver.c
@@ -174,41 +182,44 @@ src/gns/nss/nss_gns_query.c
174src/gns/plugin_block_gns.c 182src/gns/plugin_block_gns.c
175src/gns/plugin_gnsrecord_gns.c 183src/gns/plugin_gnsrecord_gns.c
176src/gns/plugin_rest_gns.c 184src/gns/plugin_rest_gns.c
185src/gns/w32nsp-install.c
186src/gns/w32nsp-resolve.c
187src/gns/w32nsp-uninstall.c
188src/gns/w32nsp.c
177src/gnsrecord/gnsrecord.c 189src/gnsrecord/gnsrecord.c
178src/gnsrecord/gnsrecord_crypto.c 190src/gnsrecord/gnsrecord_crypto.c
179src/gnsrecord/gnsrecord_misc.c 191src/gnsrecord/gnsrecord_misc.c
180src/gnsrecord/gnsrecord_serialization.c 192src/gnsrecord/gnsrecord_serialization.c
181src/gnsrecord/plugin_gnsrecord_dns.c 193src/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 194src/hello/address.c
187src/hello/gnunet-hello.c 195src/hello/gnunet-hello.c
188src/hello/hello.c 196src/hello/hello.c
189src/hostlist/gnunet-daemon-hostlist.c 197src/hostlist/gnunet-daemon-hostlist.c
190src/hostlist/gnunet-daemon-hostlist_client.c 198src/hostlist/gnunet-daemon-hostlist_client.c
191src/hostlist/gnunet-daemon-hostlist_server.c 199src/hostlist/gnunet-daemon-hostlist_server.c
200src/identity-attribute/identity_attribute.c
201src/identity-attribute/plugin_identity_attribute_gnuid.c
202src/identity-provider/gnunet-idp.c
203src/identity-provider/gnunet-service-identity-provider.c
204src/identity-provider/identity_provider_api.c
205src/identity-provider/jwt.c
206src/identity-provider/plugin_gnsrecord_identity_provider.c
207src/identity-provider/plugin_identity_provider_sqlite.c
208src/identity-provider/plugin_rest_identity_provider.c
192src/identity/gnunet-identity.c 209src/identity/gnunet-identity.c
193src/identity/gnunet-service-identity.c 210src/identity/gnunet-service-identity.c
194src/identity/identity_api.c 211src/identity/identity_api.c
195src/identity/identity_api_lookup.c 212src/identity/identity_api_lookup.c
196src/identity/plugin_gnsrecord_identity.c
197src/identity/plugin_rest_identity.c 213src/identity/plugin_rest_identity.c
198src/identity-provider/gnunet-identity-token.c 214src/json/json.c
199src/identity-provider/gnunet-service-identity-provider.c 215src/json/json_generator.c
200src/identity-provider/identity_provider_api.c 216src/json/json_helper.c
201src/identity-provider/identity_token.c 217src/json/json_mhd.c
202src/identity-provider/plugin_rest_identity_provider.c
203src/jsonapi/jsonapi.c 218src/jsonapi/jsonapi.c
204src/jsonapi/jsonapi_document.c 219src/jsonapi/jsonapi_document.c
205src/jsonapi/jsonapi_error.c 220src/jsonapi/jsonapi_error.c
206src/jsonapi/jsonapi_relationship.c 221src/jsonapi/jsonapi_relationship.c
207src/jsonapi/jsonapi_resource.c 222src/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 223src/multicast/gnunet-multicast.c
213src/multicast/gnunet-service-multicast.c 224src/multicast/gnunet-service-multicast.c
214src/multicast/multicast_api.c 225src/multicast/multicast_api.c
@@ -222,8 +233,8 @@ src/namecache/namecache_api.c
222src/namecache/plugin_namecache_flat.c 233src/namecache/plugin_namecache_flat.c
223src/namecache/plugin_namecache_postgres.c 234src/namecache/plugin_namecache_postgres.c
224src/namecache/plugin_namecache_sqlite.c 235src/namecache/plugin_namecache_sqlite.c
225src/namestore/gnunet-namestore.c
226src/namestore/gnunet-namestore-fcfsd.c 236src/namestore/gnunet-namestore-fcfsd.c
237src/namestore/gnunet-namestore.c
227src/namestore/gnunet-service-namestore.c 238src/namestore/gnunet-service-namestore.c
228src/namestore/namestore_api.c 239src/namestore/namestore_api.c
229src/namestore/namestore_api_monitor.c 240src/namestore/namestore_api_monitor.c
@@ -238,10 +249,10 @@ src/nat-auto/gnunet-service-nat-auto.c
238src/nat-auto/gnunet-service-nat-auto_legacy.c 249src/nat-auto/gnunet-service-nat-auto_legacy.c
239src/nat-auto/nat_auto_api.c 250src/nat-auto/nat_auto_api.c
240src/nat-auto/nat_auto_api_test.c 251src/nat-auto/nat_auto_api_test.c
241src/nat/gnunet-helper-nat-client.c
242src/nat/gnunet-helper-nat-client-windows.c 252src/nat/gnunet-helper-nat-client-windows.c
243src/nat/gnunet-helper-nat-server.c 253src/nat/gnunet-helper-nat-client.c
244src/nat/gnunet-helper-nat-server-windows.c 254src/nat/gnunet-helper-nat-server-windows.c
255src/nat/gnunet-helper-nat-server.c
245src/nat/gnunet-nat.c 256src/nat/gnunet-nat.c
246src/nat/gnunet-service-nat.c 257src/nat/gnunet-service-nat.c
247src/nat/gnunet-service-nat_externalip.c 258src/nat/gnunet-service-nat_externalip.c
@@ -250,15 +261,15 @@ src/nat/gnunet-service-nat_mini.c
250src/nat/gnunet-service-nat_stun.c 261src/nat/gnunet-service-nat_stun.c
251src/nat/nat_api.c 262src/nat/nat_api.c
252src/nat/nat_api_stun.c 263src/nat/nat_api_stun.c
253src/nse/gnunet-nse.c
254src/nse/gnunet-nse-profiler.c 264src/nse/gnunet-nse-profiler.c
265src/nse/gnunet-nse.c
255src/nse/gnunet-service-nse.c 266src/nse/gnunet-service-nse.c
256src/nse/nse_api.c 267src/nse/nse_api.c
268src/peerinfo-tool/gnunet-peerinfo.c
269src/peerinfo-tool/gnunet-peerinfo_plugins.c
257src/peerinfo/gnunet-service-peerinfo.c 270src/peerinfo/gnunet-service-peerinfo.c
258src/peerinfo/peerinfo_api.c 271src/peerinfo/peerinfo_api.c
259src/peerinfo/peerinfo_api_notify.c 272src/peerinfo/peerinfo_api_notify.c
260src/peerinfo-tool/gnunet-peerinfo.c
261src/peerinfo-tool/gnunet-peerinfo_plugins.c
262src/peerstore/gnunet-peerstore.c 273src/peerstore/gnunet-peerstore.c
263src/peerstore/gnunet-service-peerstore.c 274src/peerstore/gnunet-service-peerstore.c
264src/peerstore/peerstore_api.c 275src/peerstore/peerstore_api.c
@@ -309,13 +320,13 @@ src/rps/gnunet-service-rps_custommap.c
309src/rps/gnunet-service-rps_sampler.c 320src/rps/gnunet-service-rps_sampler.c
310src/rps/gnunet-service-rps_sampler_elem.c 321src/rps/gnunet-service-rps_sampler_elem.c
311src/rps/gnunet-service-rps_view.c 322src/rps/gnunet-service-rps_view.c
312src/rps/rps_api.c
313src/rps/rps-test_util.c 323src/rps/rps-test_util.c
324src/rps/rps_api.c
314src/scalarproduct/gnunet-scalarproduct.c 325src/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 326src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
318src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c 327src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
328src/scalarproduct/gnunet-service-scalarproduct_alice.c
329src/scalarproduct/gnunet-service-scalarproduct_bob.c
319src/scalarproduct/scalarproduct_api.c 330src/scalarproduct/scalarproduct_api.c
320src/secretsharing/gnunet-secretsharing-profiler.c 331src/secretsharing/gnunet-secretsharing-profiler.c
321src/secretsharing/gnunet-service-secretsharing.c 332src/secretsharing/gnunet-service-secretsharing.c
@@ -342,15 +353,16 @@ src/statistics/gnunet-statistics.c
342src/statistics/statistics_api.c 353src/statistics/statistics_api.c
343src/template/gnunet-service-template.c 354src/template/gnunet-service-template.c
344src/template/gnunet-template.c 355src/template/gnunet-template.c
356src/testbed-logger/gnunet-service-testbed-logger.c
357src/testbed-logger/testbed_logger_api.c
345src/testbed/generate-underlay-topology.c 358src/testbed/generate-underlay-topology.c
346src/testbed/gnunet-daemon-latency-logger.c 359src/testbed/gnunet-daemon-latency-logger.c
347src/testbed/gnunet-daemon-testbed-blacklist.c 360src/testbed/gnunet-daemon-testbed-blacklist.c
348src/testbed/gnunet-daemon-testbed-underlay.c 361src/testbed/gnunet-daemon-testbed-underlay.c
349src/testbed/gnunet-helper-testbed.c 362src/testbed/gnunet-helper-testbed.c
350src/testbed/gnunet_mpi_test.c
351src/testbed/gnunet-service-test-barriers.c 363src/testbed/gnunet-service-test-barriers.c
352src/testbed/gnunet-service-testbed_barriers.c
353src/testbed/gnunet-service-testbed.c 364src/testbed/gnunet-service-testbed.c
365src/testbed/gnunet-service-testbed_barriers.c
354src/testbed/gnunet-service-testbed_cache.c 366src/testbed/gnunet-service-testbed_cache.c
355src/testbed/gnunet-service-testbed_connectionpool.c 367src/testbed/gnunet-service-testbed_connectionpool.c
356src/testbed/gnunet-service-testbed_cpustatus.c 368src/testbed/gnunet-service-testbed_cpustatus.c
@@ -358,20 +370,19 @@ src/testbed/gnunet-service-testbed_links.c
358src/testbed/gnunet-service-testbed_meminfo.c 370src/testbed/gnunet-service-testbed_meminfo.c
359src/testbed/gnunet-service-testbed_oc.c 371src/testbed/gnunet-service-testbed_oc.c
360src/testbed/gnunet-service-testbed_peers.c 372src/testbed/gnunet-service-testbed_peers.c
361src/testbed/gnunet_testbed_mpi_spawn.c
362src/testbed/gnunet-testbed-profiler.c 373src/testbed/gnunet-testbed-profiler.c
363src/testbed-logger/gnunet-service-testbed-logger.c 374src/testbed/gnunet_mpi_test.c
364src/testbed-logger/testbed_logger_api.c 375src/testbed/gnunet_testbed_mpi_spawn.c
365src/testbed/testbed_api_barriers.c
366src/testbed/testbed_api.c 376src/testbed/testbed_api.c
377src/testbed/testbed_api_barriers.c
367src/testbed/testbed_api_hosts.c 378src/testbed/testbed_api_hosts.c
368src/testbed/testbed_api_operations.c 379src/testbed/testbed_api_operations.c
369src/testbed/testbed_api_peers.c 380src/testbed/testbed_api_peers.c
370src/testbed/testbed_api_sd.c 381src/testbed/testbed_api_sd.c
371src/testbed/testbed_api_services.c 382src/testbed/testbed_api_services.c
372src/testbed/testbed_api_statistics.c 383src/testbed/testbed_api_statistics.c
373src/testbed/testbed_api_testbed.c
374src/testbed/testbed_api_test.c 384src/testbed/testbed_api_test.c
385src/testbed/testbed_api_testbed.c
375src/testbed/testbed_api_topology.c 386src/testbed/testbed_api_topology.c
376src/testbed/testbed_api_underlay.c 387src/testbed/testbed_api_underlay.c
377src/testing/gnunet-testing.c 388src/testing/gnunet-testing.c
@@ -380,34 +391,39 @@ src/testing/testing.c
380src/topology/friends.c 391src/topology/friends.c
381src/topology/gnunet-daemon-topology.c 392src/topology/gnunet-daemon-topology.c
382src/transport/gnunet-helper-transport-bluetooth.c 393src/transport/gnunet-helper-transport-bluetooth.c
383src/transport/gnunet-helper-transport-wlan.c
384src/transport/gnunet-helper-transport-wlan-dummy.c 394src/transport/gnunet-helper-transport-wlan-dummy.c
385src/transport/gnunet-service-transport_ats.c 395src/transport/gnunet-helper-transport-wlan.c
386src/transport/gnunet-service-transport.c 396src/transport/gnunet-service-transport.c
397src/transport/gnunet-service-transport_ats.c
387src/transport/gnunet-service-transport_hello.c 398src/transport/gnunet-service-transport_hello.c
388src/transport/gnunet-service-transport_manipulation.c 399src/transport/gnunet-service-transport_manipulation.c
389src/transport/gnunet-service-transport_neighbours.c 400src/transport/gnunet-service-transport_neighbours.c
390src/transport/gnunet-service-transport_plugins.c 401src/transport/gnunet-service-transport_plugins.c
391src/transport/gnunet-service-transport_validation.c 402src/transport/gnunet-service-transport_validation.c
392src/transport/gnunet-transport.c
393src/transport/gnunet-transport-certificate-creation.c 403src/transport/gnunet-transport-certificate-creation.c
394src/transport/gnunet-transport-profiler.c 404src/transport/gnunet-transport-profiler.c
395src/transport/gnunet-transport-wlan-receiver.c 405src/transport/gnunet-transport-wlan-receiver.c
396src/transport/gnunet-transport-wlan-sender.c 406src/transport/gnunet-transport-wlan-sender.c
407src/transport/gnunet-transport.c
397src/transport/plugin_transport_http_client.c 408src/transport/plugin_transport_http_client.c
398src/transport/plugin_transport_http_common.c 409src/transport/plugin_transport_http_common.c
399src/transport/plugin_transport_http_server.c 410src/transport/plugin_transport_http_server.c
400src/transport/plugin_transport_smtp.c 411src/transport/plugin_transport_smtp.c
401src/transport/plugin_transport_tcp.c 412src/transport/plugin_transport_tcp.c
402src/transport/plugin_transport_template.c 413src/transport/plugin_transport_template.c
403src/transport/plugin_transport_udp_broadcasting.c
404src/transport/plugin_transport_udp.c 414src/transport/plugin_transport_udp.c
415src/transport/plugin_transport_udp_broadcasting.c
405src/transport/plugin_transport_unix.c 416src/transport/plugin_transport_unix.c
406src/transport/plugin_transport_wlan.c 417src/transport/plugin_transport_wlan.c
407src/transport/tcp_connection_legacy.c 418src/transport/tcp_connection_legacy.c
408src/transport/tcp_server_legacy.c 419src/transport/tcp_server_legacy.c
409src/transport/tcp_server_mst_legacy.c 420src/transport/tcp_server_mst_legacy.c
410src/transport/tcp_service_legacy.c 421src/transport/tcp_service_legacy.c
422src/transport/transport-testing-filenames.c
423src/transport/transport-testing-loggers.c
424src/transport/transport-testing-main.c
425src/transport/transport-testing-send.c
426src/transport/transport-testing.c
411src/transport/transport_api_address_to_string.c 427src/transport/transport_api_address_to_string.c
412src/transport/transport_api_blacklist.c 428src/transport/transport_api_blacklist.c
413src/transport/transport_api_core.c 429src/transport/transport_api_core.c
@@ -416,11 +432,6 @@ src/transport/transport_api_manipulation.c
416src/transport/transport_api_monitor_peers.c 432src/transport/transport_api_monitor_peers.c
417src/transport/transport_api_monitor_plugins.c 433src/transport/transport_api_monitor_plugins.c
418src/transport/transport_api_offer_hello.c 434src/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 435src/tun/regex.c
425src/tun/tun.c 436src/tun/tun.c
426src/util/bandwidth.c 437src/util/bandwidth.c
@@ -434,10 +445,11 @@ src/util/configuration_loader.c
434src/util/container_bloomfilter.c 445src/util/container_bloomfilter.c
435src/util/container_heap.c 446src/util/container_heap.c
436src/util/container_meta_data.c 447src/util/container_meta_data.c
437src/util/container_multihashmap32.c
438src/util/container_multihashmap.c 448src/util/container_multihashmap.c
449src/util/container_multihashmap32.c
439src/util/container_multipeermap.c 450src/util/container_multipeermap.c
440src/util/container_multishortmap.c 451src/util/container_multishortmap.c
452src/util/crypto_abe.c
441src/util/crypto_crc.c 453src/util/crypto_crc.c
442src/util/crypto_ecc.c 454src/util/crypto_ecc.c
443src/util/crypto_ecc_dlog.c 455src/util/crypto_ecc_dlog.c
@@ -454,8 +466,8 @@ src/util/crypto_symmetric.c
454src/util/disk.c 466src/util/disk.c
455src/util/getopt.c 467src/util/getopt.c
456src/util/getopt_helpers.c 468src/util/getopt_helpers.c
457src/util/gnunet-config.c
458src/util/gnunet-config-diff.c 469src/util/gnunet-config-diff.c
470src/util/gnunet-config.c
459src/util/gnunet-ecc.c 471src/util/gnunet-ecc.c
460src/util/gnunet-helper-w32-console.c 472src/util/gnunet-helper-w32-console.c
461src/util/gnunet-resolver.c 473src/util/gnunet-resolver.c
@@ -486,8 +498,8 @@ src/util/time.c
486src/util/w32cat.c 498src/util/w32cat.c
487src/util/win.c 499src/util/win.c
488src/util/winproc.c 500src/util/winproc.c
489src/vpn/gnunet-helper-vpn.c
490src/vpn/gnunet-helper-vpn-windows.c 501src/vpn/gnunet-helper-vpn-windows.c
502src/vpn/gnunet-helper-vpn.c
491src/vpn/gnunet-service-vpn.c 503src/vpn/gnunet-service-vpn.c
492src/vpn/gnunet-vpn.c 504src/vpn/gnunet-vpn.c
493src/vpn/vpn_api.c 505src/vpn/vpn_api.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 7f1a00177..6d0284157 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,11 +12,12 @@ endif
12if HAVE_EXPERIMENTAL 12if HAVE_EXPERIMENTAL
13 EXP_DIR = \ 13 EXP_DIR = \
14 rps 14 rps
15endif 15# dv (FTBFS)
16 16if HAVE_ABE
17if HAVE_JSON 17 EXP_DIR += abe \
18if HAVE_MHD 18 credential \
19 PROVIDER_DIR = identity-provider 19 identity-attribute \
20 identity-provider
20endif 21endif
21endif 22endif
22 23
@@ -128,7 +129,6 @@ SUBDIRS = \
128 psyc \ 129 psyc \
129 social \ 130 social \
130 $(AUCTION_DIR) \ 131 $(AUCTION_DIR) \
131 $(EXP_DIR) \ 132 $(EXP_DIR)
132 $(PROVIDER_DIR)
133 133
134endif 134endif
diff --git a/src/abe/Makefile.am b/src/abe/Makefile.am
new file mode 100644
index 000000000..308e6c67c
--- /dev/null
+++ b/src/abe/Makefile.am
@@ -0,0 +1,50 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6libexecdir= $(pkglibdir)/libexec/
7
8pkgcfgdir= $(pkgdatadir)/config.d/
9
10dist_pkgcfg_DATA = \
11 abe.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = --coverage -O0
15 XLIB = -lgcov
16endif
17
18libgnunetabe_la_SOURCES = abe.c
19
20libgnunetabe_la_LIBADD = \
21 $(GCLIBADD)\
22 $(LIBGCRYPT_LIBS) \
23 $(LTLIBICONV) \
24 $(LTLIBINTL) \
25 $(ABE_LIBADD) \
26 -lgabe \
27 -lpbc \
28 -lglib-2.0 \
29 -lltdl $(Z_LIBS) -lunistring $(XLIB)
30
31libgnunetabe_la_LDFLAGS = \
32 $(GN_LIB_LDFLAGS) \
33 -version-info 1:0:0
34
35lib_LTLIBRARIES = libgnunetabe.la
36
37if ENABLE_TEST_RUN
38AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
39TESTS = $(check_PROGRAMS)
40endif
41
42check_PROGRAMS = test_cpabe
43
44test_cpabe_SOURCES = \
45 test_cpabe.c
46test_cpabe_LDADD = \
47 libgnunetabe.la \
48 $(top_builddir)/src/util/libgnunetutil.la
49check_PROGRAMS += \
50 test_cpabe
diff --git a/src/abe/abe.c b/src/abe/abe.c
new file mode 100644
index 000000000..3f1f6dc5b
--- /dev/null
+++ b/src/abe/abe.c
@@ -0,0 +1,499 @@
1/*
2 This file is part of GNUnet. Copyright (C) 2001-2018 Christian Grothoff
3 (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19
20*/
21
22/**
23 * @file abe/abe.c
24 * @brief functions for Attribute-Based Encryption
25 * @author Martin Schanzenbach
26 */
27
28
29#include "platform.h"
30#include <pbc/pbc.h>
31#include <gabe.h>
32
33#include "gnunet_crypto_lib.h"
34#include "gnunet_abe_lib.h"
35
36struct GNUNET_ABE_AbeMasterKey
37{
38 gabe_pub_t* pub;
39 gabe_msk_t* msk;
40};
41
42struct GNUNET_ABE_AbeKey
43{
44 gabe_pub_t* pub;
45 gabe_prv_t* prv;
46};
47
48static int
49init_aes( element_t k, int enc,
50 gcry_cipher_hd_t* handle,
51 struct GNUNET_CRYPTO_SymmetricSessionKey *key,
52 unsigned char* iv)
53{
54 int rc;
55 int key_len;
56 unsigned char* key_buf;
57
58 key_len = element_length_in_bytes(k) < 33 ? 3 : element_length_in_bytes(k);
59 key_buf = (unsigned char*) malloc(key_len);
60 element_to_bytes(key_buf, k);
61
62 memcpy (key->aes_key, key_buf, GNUNET_CRYPTO_AES_KEY_LENGTH);
63 GNUNET_assert (0 ==
64 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
65 GCRY_CIPHER_MODE_CFB, 0));
66 rc = gcry_cipher_setkey (*handle,
67 key->aes_key,
68 sizeof (key->aes_key));
69 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
70 memset (iv, 0, 16); //TODO make reasonable
71 rc = gcry_cipher_setiv (*handle,
72 iv,
73 16);
74 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
75
76 free(key_buf);
77 return rc;
78}
79
80static int
81aes_128_cbc_encrypt( char* pt,
82 int size,
83 element_t k,
84 char **ct )
85{
86 gcry_cipher_hd_t handle;
87 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
88 unsigned char iv[16];
89 char* buf;
90 int padding;
91 int buf_size;
92 uint8_t len[4];
93 init_aes(k, 1, &handle, &skey, iv);
94
95 /* TODO make less crufty */
96
97 /* stuff in real length (big endian) before padding */
98 len[0] = (size & 0xff000000)>>24;
99 len[1] = (size & 0xff0000)>>16;
100 len[2] = (size & 0xff00)>>8;
101 len[3] = (size & 0xff)>>0;
102 padding = 16 - ((4+size) % 16);
103 buf_size = 4 + size + padding;
104 buf = GNUNET_malloc (buf_size);
105 GNUNET_memcpy (buf, len, 4);
106 GNUNET_memcpy (buf+4, pt, size);
107 *ct = GNUNET_malloc (buf_size);
108
109 GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf, buf_size));
110 gcry_cipher_close (handle);
111 //AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
112 GNUNET_free (buf);
113 return buf_size;
114}
115
116static int
117aes_128_cbc_decrypt( char* ct,
118 int size,
119 element_t k,
120 char **pt )
121{
122 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
123 gcry_cipher_hd_t handle;
124 unsigned char iv[16];
125 char* tmp;
126 uint32_t len;
127
128 init_aes(k, 1, &handle, &skey, iv);
129
130 tmp = GNUNET_malloc (size);
131
132 //AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
133 GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size));
134 gcry_cipher_close (handle);
135 /* TODO make less crufty */
136
137 /* get real length */
138 len = 0;
139 len = len
140 | ((tmp[0])<<24) | ((tmp[1])<<16)
141 | ((tmp[2])<<8) | ((tmp[3])<<0);
142 /* truncate any garbage from the padding */
143 *pt = GNUNET_malloc (len);
144 GNUNET_memcpy (*pt, tmp+4, len);
145 GNUNET_free (tmp);
146 return len;
147}
148
149/**
150 * @ingroup abe
151 * Create a new CP-ABE master key. Caller must free return value.
152 *
153 * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
154 */
155struct GNUNET_ABE_AbeMasterKey*
156GNUNET_ABE_cpabe_create_master_key (void)
157{
158 struct GNUNET_ABE_AbeMasterKey* key;
159 key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
160 gabe_setup(&key->pub, &key->msk);
161 GNUNET_assert (NULL != key->pub);
162 GNUNET_assert (NULL != key->msk);
163 return key;
164}
165
166/**
167 * @ingroup abe
168 * Delete a CP-ABE master key.
169 *
170 * @param key the master key
171 * @return fresh private key; free using #GNUNET_free
172 */
173void
174GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key)
175{
176 gabe_msk_free (key->msk);
177 gabe_pub_free (key->pub);
178 //GNUNET_free (key->msk);
179 //gabe_msk_free (key->msk); //For some reason free of pub implicit?
180 GNUNET_free (key);
181}
182
183/**
184 * @ingroup abe
185 * Create a new CP-ABE key. Caller must free return value.
186 *
187 * @param key the master key
188 * @param attrs the attributes to append to the key
189 * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
190 */
191struct GNUNET_ABE_AbeKey*
192GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
193 char **attrs)
194{
195 struct GNUNET_ABE_AbeKey *prv_key;
196 int size;
197 char *tmp;
198
199 prv_key = GNUNET_new (struct GNUNET_ABE_AbeKey);
200 prv_key->prv = gabe_keygen(key->pub, key->msk, attrs);
201 size = gabe_pub_serialize(key->pub, &tmp);
202 prv_key->pub = gabe_pub_unserialize(tmp, size);
203 GNUNET_free (tmp);
204 GNUNET_assert (NULL != prv_key->prv);
205 return prv_key;
206}
207
208/**
209 * @ingroup abe
210 * Delete a CP-ABE key.
211 *
212 * @param key the key to delete
213 * @param delete_pub GNUNE_YES if the public key should also be freed (bug in gabe)
214 * @return fresh private key; free using #GNUNET_free
215 */
216void
217GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
218 int delete_pub)
219{
220 //Memory management in gabe is buggy
221 gabe_prv_free (key->prv);
222 if (GNUNET_YES == delete_pub)
223 gabe_pub_free (key->pub);
224 GNUNET_free (key);
225}
226
227static ssize_t
228write_cpabe (void **result,
229 uint32_t file_len,
230 char* cph_buf,
231 int cph_buf_len,
232 char* aes_buf,
233 int aes_buf_len)
234{
235 char *ptr;
236 uint32_t *len;
237
238 *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
239 ptr = *result;
240 len = (uint32_t*) ptr;
241 *len = htonl (file_len);
242 ptr += 4;
243 len = (uint32_t*) ptr;
244 *len = htonl (aes_buf_len);
245 ptr += 4;
246 memcpy (ptr, aes_buf, aes_buf_len);
247 ptr += aes_buf_len;
248 len = (uint32_t*) ptr;
249 *len = htonl (cph_buf_len);
250 ptr += 4;
251 memcpy (ptr, cph_buf, cph_buf_len);
252 return 12 + cph_buf_len + aes_buf_len;
253}
254
255static ssize_t
256read_cpabe (const void *data,
257 char** cph_buf,
258 int *cph_buf_len,
259 char** aes_buf,
260 int *aes_buf_len)
261{
262 int buf_len;
263 char *ptr;
264 uint32_t *len;
265
266 ptr = (char*)data;
267 len = (uint32_t*)ptr;
268 buf_len = ntohl (*len);
269 ptr += 4;
270 len = (uint32_t*)ptr;
271 *aes_buf_len = ntohl (*len);
272 ptr += 4;
273 *aes_buf = GNUNET_malloc (*aes_buf_len);
274 memcpy(*aes_buf, ptr, *aes_buf_len);
275 ptr += *aes_buf_len;
276 len = (uint32_t*)ptr;
277 *cph_buf_len = ntohl (*len);
278 ptr += 4;
279 *cph_buf = GNUNET_malloc (*cph_buf_len);
280 memcpy(*cph_buf, ptr, *cph_buf_len);
281
282 return buf_len;
283}
284
285/**
286 * @ingroup abe
287 * Encrypt a block using sessionkey.
288 *
289 * @param block the block to encrypt
290 * @param size the size of the @a block
291 * @param policy the ABE policy
292 * @param key the key used to encrypt
293 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
294 * @return the size of the encrypted block, -1 for errors
295 */
296ssize_t
297GNUNET_ABE_cpabe_encrypt (const void *block,
298 size_t size,
299 const char *policy,
300 const struct GNUNET_ABE_AbeMasterKey *key,
301 void **result)
302{
303 gabe_cph_t* cph;
304 char* plt;
305 char* cph_buf;
306 char* aes_buf;
307 element_t m;
308 int cph_buf_len;
309 int aes_buf_len;
310 ssize_t result_len;
311
312 if( !(cph = gabe_enc(key->pub, m, (char*)policy)) )
313 return GNUNET_SYSERR;
314 cph_buf_len = gabe_cph_serialize(cph,
315 &cph_buf);
316 gabe_cph_free(cph);
317 GNUNET_free (cph);
318 plt = GNUNET_memdup (block, size);
319 aes_buf_len = aes_128_cbc_encrypt(plt, size, m, &aes_buf);
320 GNUNET_free (plt);
321 element_clear(m);
322 result_len = write_cpabe(result, size, cph_buf, cph_buf_len, aes_buf, aes_buf_len);
323 GNUNET_free(cph_buf);
324 GNUNET_free(aes_buf);
325 return result_len;
326}
327
328/**
329 * @ingroup abe
330 * Decrypt a block using the ABE key.
331 *
332 * @param block the block to encrypt
333 * @param size the size of the @a block
334 * @param key the key used to decrypt
335 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
336 * @return the size of the encrypted block, -1 for errors
337 */
338ssize_t
339GNUNET_ABE_cpabe_decrypt (const void *block,
340 size_t size,
341 const struct GNUNET_ABE_AbeKey *key,
342 void **result)
343{
344 char* aes_buf;
345 char* cph_buf;
346 gabe_cph_t* cph;
347 element_t m;
348 int cph_buf_size;
349 int aes_buf_size;
350 int plt_len;
351
352 read_cpabe(block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
353 cph = gabe_cph_unserialize(key->pub, cph_buf, cph_buf_size);
354 if( !gabe_dec(key->pub, key->prv, cph, m) ) {
355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
356 "%s\n", gabe_error());
357 GNUNET_free (aes_buf);
358 GNUNET_free (cph_buf);
359 gabe_cph_free(cph);
360 GNUNET_free (cph);
361 element_clear (m);
362 return GNUNET_SYSERR;
363 }
364 gabe_cph_free(cph);
365 GNUNET_free (cph);
366 plt_len = aes_128_cbc_decrypt(aes_buf, aes_buf_size, m, (char**)result);
367 GNUNET_free (cph_buf);
368 GNUNET_free (aes_buf);
369 element_clear (m);
370 //freeing is buggy in gabe
371 //gabe_prv_free (prv);
372 //gabe_pub_free (pub);
373 return plt_len;
374}
375
376/**
377 * @ingroup abe
378 * Serialize an ABE key.
379 *
380 * @param key the key to serialize
381 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
382 * @return the size of the encrypted block, -1 for errors
383 */
384ssize_t
385GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
386 void **result)
387{
388 ssize_t len;
389 char *pub;
390 char *prv;
391 int pub_len;
392 int prv_len;
393
394 pub_len = gabe_pub_serialize (key->pub, &pub);
395 prv_len = gabe_prv_serialize (key->prv, &prv);
396
397 len = pub_len + prv_len + 12;
398 write_cpabe (result, len, pub, pub_len, prv, prv_len);
399
400 GNUNET_free (pub);
401 GNUNET_free (prv);
402
403 return len;
404}
405
406/**
407 * @ingroup abe
408 * Deserialize a serialized ABE key.
409 *
410 * @param data the data to deserialize
411 * @param len the length of the data.
412 * @return the ABE key. NULL of unsuccessful
413 */
414struct GNUNET_ABE_AbeKey*
415GNUNET_ABE_cpabe_deserialize_key (const void *data,
416 size_t len)
417{
418 struct GNUNET_ABE_AbeKey *key;
419 char *pub;
420 char *prv;
421 int prv_len;
422 int pub_len;
423
424 key = GNUNET_new (struct GNUNET_ABE_AbeKey);
425 read_cpabe (data,
426 &pub,
427 &pub_len,
428 &prv,
429 &prv_len);
430 key->pub = gabe_pub_unserialize (pub, pub_len);
431 key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
432
433 GNUNET_free (pub);
434 GNUNET_free (prv);
435 return key;
436}
437
438/**
439 * @ingroup abe
440 * Serialize an ABE master key.
441 *
442 * @param key the key to serialize
443 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
444 * @return the size of the encrypted block, -1 for errors
445 */
446ssize_t
447GNUNET_ABE_cpabe_serialize_master_key (const struct GNUNET_ABE_AbeMasterKey *key,
448 void **result)
449{
450 ssize_t len;
451 char *pub;
452 char *msk;
453 int pub_len;
454 int msk_len;
455
456 pub_len = gabe_pub_serialize (key->pub, &pub);
457 msk_len = gabe_msk_serialize (key->msk, &msk);
458
459 len = pub_len + msk_len + 12;
460 write_cpabe (result, len, pub, pub_len, msk, msk_len);
461
462 GNUNET_free (pub);
463 GNUNET_free (msk);
464
465 return len;
466}
467
468/**
469 * @ingroup abe
470 * Deserialize an ABE master key.
471 *
472 * @param data the data to deserialize
473 * @param len the length of the data.
474 * @return the ABE key. NULL of unsuccessful
475 */
476struct GNUNET_ABE_AbeMasterKey*
477GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
478 size_t len)
479{
480 struct GNUNET_ABE_AbeMasterKey *key;
481 char *msk;
482 char *pub;
483 int msk_len;
484 int pub_len;
485
486 key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
487 read_cpabe (data,
488 &pub,
489 &pub_len,
490 &msk,
491 &msk_len);
492 key->pub = gabe_pub_unserialize (pub, pub_len);
493 key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
494
495 GNUNET_free (pub);
496 GNUNET_free (msk);
497
498 return key;
499}
diff --git a/src/abe/test_cpabe.c b/src/abe/test_cpabe.c
new file mode 100644
index 000000000..9b2062b23
--- /dev/null
+++ b/src/abe/test_cpabe.c
@@ -0,0 +1,87 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2002, 2003, 2004, 2006 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19
20*/
21/**
22 * @author Martin Schanzenbach
23 * @file util/test_crypto_abe.c
24 * @brief test for ABE ciphers
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_abe_lib.h"
29
30#define TESTSTRING "Hello World!"
31
32static int
33testAbecipher ()
34{
35 struct GNUNET_ABE_AbeMasterKey *msk;
36 struct GNUNET_ABE_AbeKey *key;
37 char *result;
38 char **attrs;
39 int size;
40 char *res;
41 msk = GNUNET_ABE_cpabe_create_master_key ();
42 size = GNUNET_ABE_cpabe_encrypt (TESTSTRING, strlen (TESTSTRING) + 1,
43 "testattr", //Policy
44 msk,
45 (void*)&result);
46 GNUNET_assert (-1 != size);
47 attrs = GNUNET_malloc (2 * sizeof (char*));
48 attrs[0] = "testattr";
49 attrs[1] = NULL;
50 key = GNUNET_ABE_cpabe_create_key (msk,
51 attrs);
52
53 size = GNUNET_ABE_cpabe_decrypt (result, size,
54 key,
55 (void*)&res);
56 if (strlen (TESTSTRING) + 1 != size)
57 {
58 printf ("abeciphertest failed: decryptBlock returned %d\n", size);
59 return 1;
60 }
61 if (0 != strcmp (res, TESTSTRING))
62 {
63 printf ("abeciphertest failed: %s != %s\n", res, TESTSTRING);
64 return 1;
65 }
66 else
67 return 0;
68}
69
70
71int
72main (int argc, char *argv[])
73{
74 int failureCount = 0;
75
76 GNUNET_log_setup ("test-crypto-abe", "WARNING", NULL);
77 failureCount += testAbecipher ();
78
79 if (failureCount != 0)
80 {
81 printf ("%d TESTS FAILED!\n", failureCount);
82 return -1;
83 }
84 return 0;
85}
86
87/* end of test_crypto_aes.c */
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
new file mode 100644
index 000000000..ca11c5e4f
--- /dev/null
+++ b/src/credential/Makefile.am
@@ -0,0 +1,112 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4EXTRA_DIST = \
5 test_credential_defaults.conf \
6 test_credential_lookup.conf
7
8
9if USE_COVERAGE
10 AM_CFLAGS = --coverage -O0
11endif
12
13pkgcfgdir = $(pkgdatadir)/config.d/
14
15libexecdir= $(pkglibdir)/libexec/
16
17plugindir = $(libdir)/gnunet
18
19pkgcfg_DATA = \
20 credential.conf
21
22
23# /usr/lib - compiles a layer which can be used to be communicagte with the service
24lib_LTLIBRARIES = \
25 libgnunetcredential.la
26
27# /usr/lib/gnunet/libexec - Business logic . Separate process
28libexec_PROGRAMS = \
29 gnunet-service-credential
30
31bin_PROGRAMS = \
32 gnunet-credential
33
34plugin_LTLIBRARIES = \
35 libgnunet_plugin_gnsrecord_credential.la
36
37
38if HAVE_MHD
39if HAVE_JSON
40plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la
41endif
42endif
43
44
45gnunet_credential_SOURCES = \
46 gnunet-credential.c
47gnunet_credential_LDADD = \
48 libgnunetcredential.la \
49 $(top_builddir)/src/util/libgnunetutil.la \
50 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
51 $(top_builddir)/src/identity/libgnunetidentity.la \
52 $(GN_LIBINTL)
53
54
55libgnunet_plugin_gnsrecord_credential_la_SOURCES = \
56 plugin_gnsrecord_credential.c
57libgnunet_plugin_gnsrecord_credential_la_LIBADD = \
58 libgnunetcredential.la \
59 $(top_builddir)/src/util/libgnunetutil.la \
60 $(LTLIBINTL)
61libgnunet_plugin_gnsrecord_credential_la_LDFLAGS = \
62 $(GN_PLUGIN_LDFLAGS)
63
64
65
66gnunet_service_credential_SOURCES = \
67 gnunet-service-credential.c
68gnunet_service_credential_LDADD = \
69 libgnunetcredential.la \
70 $(top_builddir)/src/util/libgnunetutil.la \
71 $(top_builddir)/src/gns/libgnunetgns.la \
72 $(top_builddir)/src/namestore/libgnunetnamestore.la \
73 $(top_builddir)/src/statistics/libgnunetstatistics.la \
74 $(GN_LIBINTL)
75
76
77libgnunetcredential_la_SOURCES = \
78 credential_api.c \
79 credential_serialization.c \
80 credential_misc.c
81libgnunetcredential_la_LIBADD = \
82 $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
83libgnunetcredential_la_LDFLAGS = \
84 $(GN_LIB_LDFLAGS)
85
86
87libgnunet_plugin_rest_credential_la_SOURCES = \
88 plugin_rest_credential.c
89libgnunet_plugin_rest_credential_la_LIBADD = \
90 libgnunetcredential.la \
91 $(top_builddir)/src/rest/libgnunetrest.la \
92 $(top_builddir)/src/identity/libgnunetidentity.la \
93 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
94 $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
95 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
96 $(LTLIBINTL) -ljansson -lmicrohttpd
97libgnunet_plugin_rest_credential_la_LDFLAGS = \
98 $(GN_PLUGIN_LDFLAGS)
99
100
101check_SCRIPTS = \
102 test_credential_issue.sh \
103 test_credential_verify_simple.sh \
104 test_credential_verify.sh \
105 test_credential_verify_and.sh
106
107if ENABLE_TEST_RUN
108if HAVE_SQLITE
109 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
110 TESTS = $(check_SCRIPTS)
111endif
112endif
diff --git a/src/credential/credential.conf.in b/src/credential/credential.conf.in
new file mode 100644
index 000000000..71f3066ca
--- /dev/null
+++ b/src/credential/credential.conf.in
@@ -0,0 +1,5 @@
1[credential]
2BINARY = gnunet-service-credential
3UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-credential.sock
4USER_SERVICE = YES
5OPTIONS = -L DEBUG \ No newline at end of file
diff --git a/src/credential/credential.h b/src/credential/credential.h
new file mode 100644
index 000000000..66a4636fc
--- /dev/null
+++ b/src/credential/credential.h
@@ -0,0 +1,221 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @file credential/credential.h
22 * @brief IPC messages between CREDENTIAL API and CREDENTIAL service
23 * @author Martin Schanzenbach
24 */
25#ifndef CREDENTIAL_H
26#define CREDENTIAL_H
27
28#include "gnunet_credential_service.h"
29
30GNUNET_NETWORK_STRUCT_BEGIN
31
32/**
33 * Message from client to Credential service to collect credentials.
34 */
35struct CollectMessage
36{
37 /**
38 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
39 */
40 struct GNUNET_MessageHeader header;
41
42 /**
43 * Subject public key
44 */
45 struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key;
46
47 /**
48 * Trust anchor
49 */
50 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
51
52 /**
53 * Length of the issuer attribute
54 */
55 uint16_t issuer_attribute_len;
56
57 /**
58 * Unique identifier for this request (for key collisions).
59 */
60 uint32_t id GNUNET_PACKED;
61
62 /* Followed by the zero-terminated attribute */
63
64};
65
66
67/**
68 * Message from client to Credential service to verify attributes.
69 */
70struct VerifyMessage
71{
72 /**
73 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
74 */
75 struct GNUNET_MessageHeader header;
76
77 /**
78 * Subject public key
79 */
80 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
81
82 /**
83 * Trust anchor
84 */
85 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
86
87 /**
88 * Number of credentials
89 */
90 uint32_t c_count;
91
92 /**
93 * Length of the issuer attribute
94 */
95 uint16_t issuer_attribute_len;
96
97 /**
98 * Unique identifier for this request (for key collisions).
99 */
100 uint32_t id GNUNET_PACKED;
101
102 /* Followed by the zero-terminated attribute and credentials to look up */
103
104};
105
106
107/**
108 * Message from CREDENTIAL service to client: new results.
109 */
110struct DelegationChainResultMessage
111{
112 /**
113 * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT
114 */
115 struct GNUNET_MessageHeader header;
116
117 /**
118 * Unique identifier for this request (for key collisions).
119 */
120 uint32_t id GNUNET_PACKED;
121
122 /**
123 * Indicates if credential has been found at all
124 */
125 uint32_t cred_found GNUNET_PACKED;
126
127 /**
128 * The number of delegations in the response
129 */
130 uint32_t d_count GNUNET_PACKED;
131
132 /**
133 * The number of credentials in the response
134 */
135 uint32_t c_count GNUNET_PACKED;
136
137 /* followed by ad_count GNUNET_CREDENTIAL_RecordData structs*/
138
139};
140
141struct DelegationRecordData
142{
143 /**
144 * Subject key
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
147
148 /**
149 * Subject attributes
150 */
151 uint32_t subject_attribute_len GNUNET_PACKED;
152};
153
154
155struct ChainEntry
156{
157 /**
158 * Issuer key
159 */
160 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
161
162 /**
163 * Subject key
164 */
165 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
166
167 /**
168 * Issuer attributes
169 */
170 uint32_t issuer_attribute_len GNUNET_PACKED;
171
172 /**
173 * Subject attributes
174 */
175 uint32_t subject_attribute_len GNUNET_PACKED;
176};
177
178
179struct CredentialEntry
180{
181
182 /**
183 * The signature for this credential by the issuer
184 */
185 struct GNUNET_CRYPTO_EcdsaSignature signature;
186
187 /**
188 * Signature meta
189 */
190 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
191
192 /**
193 * Public key of the issuer
194 */
195 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
196
197 /**
198 * Public key of the subject this credential was issued to
199 */
200 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
201
202 /**
203 * Expiration time of this credential
204 */
205 uint64_t expiration GNUNET_PACKED;
206
207 /**
208 * Issuer attribute length
209 */
210 uint32_t issuer_attribute_len;
211
212 /**
213 * Followed by the attribute string
214 */
215};
216
217
218GNUNET_NETWORK_STRUCT_END
219
220#endif
221
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
new file mode 100644
index 000000000..677cb9ad4
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,511 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file credential/credential_api.c
22 * @brief library to access the CREDENTIAL service
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_constants.h"
28#include "gnunet_arm_service.h"
29#include "gnunet_hello_lib.h"
30#include "gnunet_protocols.h"
31#include "gnunet_signatures.h"
32#include "credential.h"
33#include "credential_serialization.h"
34#include "gnunet_credential_service.h"
35#include "gnunet_identity_service.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
39
40/**
41 * Handle to a verify request
42 */
43struct GNUNET_CREDENTIAL_Request
44{
45
46 /**
47 * DLL
48 */
49 struct GNUNET_CREDENTIAL_Request *next;
50
51 /**
52 * DLL
53 */
54 struct GNUNET_CREDENTIAL_Request *prev;
55
56 /**
57 * handle to credential service
58 */
59 struct GNUNET_CREDENTIAL_Handle *credential_handle;
60
61 /**
62 * processor to call on verify result
63 */
64 GNUNET_CREDENTIAL_CredentialResultProcessor verify_proc;
65
66 /**
67 * @e verify_proc closure
68 */
69 void *proc_cls;
70
71 /**
72 * Envelope with the message for this queue entry.
73 */
74 struct GNUNET_MQ_Envelope *env;
75
76 /**
77 * request id
78 */
79 uint32_t r_id;
80
81};
82
83
84/**
85 * Connection to the CREDENTIAL service.
86 */
87struct GNUNET_CREDENTIAL_Handle
88{
89
90 /**
91 * Configuration to use.
92 */
93 const struct GNUNET_CONFIGURATION_Handle *cfg;
94
95 /**
96 * Connection to service (if available).
97 */
98 struct GNUNET_MQ_Handle *mq;
99
100 /**
101 * Head of linked list of active verify requests.
102 */
103 struct GNUNET_CREDENTIAL_Request *request_head;
104
105 /**
106 * Tail of linked list of active verify requests.
107 */
108 struct GNUNET_CREDENTIAL_Request *request_tail;
109
110 /**
111 * Reconnect task
112 */
113 struct GNUNET_SCHEDULER_Task *reconnect_task;
114
115 /**
116 * How long do we wait until we try to reconnect?
117 */
118 struct GNUNET_TIME_Relative reconnect_backoff;
119
120 /**
121 * Request Id generator. Incremented by one for each request.
122 */
123 uint32_t r_id_gen;
124
125};
126
127
128/**
129 * Reconnect to CREDENTIAL service.
130 *
131 * @param handle the handle to the CREDENTIAL service
132 */
133static void
134reconnect (struct GNUNET_CREDENTIAL_Handle *handle);
135
136
137/**
138 * Reconnect to CREDENTIAL
139 *
140 * @param cls the handle
141 */
142static void
143reconnect_task (void *cls)
144{
145 struct GNUNET_CREDENTIAL_Handle *handle = cls;
146
147 handle->reconnect_task = NULL;
148 reconnect (handle);
149}
150
151
152/**
153 * Disconnect from service and then reconnect.
154 *
155 * @param handle our handle
156 */
157static void
158force_reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
159{
160 GNUNET_MQ_destroy (handle->mq);
161 handle->mq = NULL;
162 handle->reconnect_backoff
163 = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
164 handle->reconnect_task
165 = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
166 &reconnect_task,
167 handle);
168}
169
170
171/**
172 * Generic error handler, called with the appropriate error code and
173 * the same closure specified at the creation of the message queue.
174 * Not every message queue implementation supports an error handler.
175 *
176 * @param cls closure with the `struct GNUNET_CREDENTIAL_Handle *`
177 * @param error error code
178 */
179static void
180mq_error_handler (void *cls,
181 enum GNUNET_MQ_Error error)
182{
183 struct GNUNET_CREDENTIAL_Handle *handle = cls;
184
185 force_reconnect (handle);
186}
187
188/**
189 * Check validity of message received from the CREDENTIAL service
190 *
191 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
192 * @param vr_msg the incoming message
193 */
194static int
195check_result (void *cls,
196 const struct DelegationChainResultMessage *vr_msg)
197{
198 //TODO
199 return GNUNET_OK;
200}
201
202
203/**
204 * Handler for messages received from the CREDENTIAL service
205 *
206 * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
207 * @param vr_msg the incoming message
208 */
209static void
210handle_result (void *cls,
211 const struct DelegationChainResultMessage *vr_msg)
212{
213 struct GNUNET_CREDENTIAL_Handle *handle = cls;
214 uint32_t r_id = ntohl (vr_msg->id);
215 struct GNUNET_CREDENTIAL_Request *vr;
216 size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg);
217 uint32_t d_count = ntohl (vr_msg->d_count);
218 uint32_t c_count = ntohl (vr_msg->c_count);
219 struct GNUNET_CREDENTIAL_Delegation d_chain[d_count];
220 struct GNUNET_CREDENTIAL_Credential creds[c_count];
221 GNUNET_CREDENTIAL_CredentialResultProcessor proc;
222 void *proc_cls;
223
224 LOG (GNUNET_ERROR_TYPE_DEBUG,
225 "Received verify reply from CREDENTIAL service\n");
226 for (vr = handle->request_head; NULL != vr; vr = vr->next)
227 if (vr->r_id == r_id)
228 break;
229 if (NULL == vr)
230 return;
231 proc = vr->verify_proc;
232 proc_cls = vr->proc_cls;
233 GNUNET_CONTAINER_DLL_remove (handle->request_head,
234 handle->request_tail,
235 vr);
236 GNUNET_MQ_discard (vr->env);
237 GNUNET_free (vr);
238 GNUNET_assert (GNUNET_OK ==
239 GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen,
240 (const char*) &vr_msg[1],
241 d_count,
242 d_chain,
243 c_count,
244 creds));
245 if (GNUNET_NO == ntohl (vr_msg->cred_found))
246 {
247 proc (proc_cls,
248 0,
249 NULL,
250 0,
251 NULL); // TODO
252 } else {
253 proc (proc_cls,
254 d_count,
255 d_chain,
256 c_count,
257 creds);
258 }
259}
260
261
262/**
263 * Reconnect to CREDENTIAL service.
264 *
265 * @param handle the handle to the CREDENTIAL service
266 */
267static void
268reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
269{
270 struct GNUNET_MQ_MessageHandler handlers[] = {
271 GNUNET_MQ_hd_var_size (result,
272 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
273 struct DelegationChainResultMessage,
274 handle),
275 GNUNET_MQ_hd_var_size (result,
276 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT,
277 struct DelegationChainResultMessage,
278 handle),
279 GNUNET_MQ_handler_end ()
280 };
281 struct GNUNET_CREDENTIAL_Request *vr;
282
283 GNUNET_assert (NULL == handle->mq);
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Trying to connect to CREDENTIAL\n");
286 handle->mq = GNUNET_CLIENT_connect (handle->cfg,
287 "credential",
288 handlers,
289 &mq_error_handler,
290 handle);
291 if (NULL == handle->mq)
292 return;
293 for (vr = handle->request_head; NULL != vr; vr = vr->next)
294 GNUNET_MQ_send_copy (handle->mq,
295 vr->env);
296}
297
298
299/**
300 * Initialize the connection with the CREDENTIAL service.
301 *
302 * @param cfg configuration to use
303 * @return handle to the CREDENTIAL service, or NULL on error
304 */
305struct GNUNET_CREDENTIAL_Handle *
306GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
307{
308 struct GNUNET_CREDENTIAL_Handle *handle;
309
310 handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
311 handle->cfg = cfg;
312 reconnect (handle);
313 if (NULL == handle->mq)
314 {
315 GNUNET_free (handle);
316 return NULL;
317 }
318 return handle;
319}
320
321
322/**
323 * Shutdown connection with the CREDENTIAL service.
324 *
325 * @param handle handle of the CREDENTIAL connection to stop
326 */
327void
328GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle)
329{
330 if (NULL != handle->mq)
331 {
332 GNUNET_MQ_destroy (handle->mq);
333 handle->mq = NULL;
334 }
335 if (NULL != handle->reconnect_task)
336 {
337 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
338 handle->reconnect_task = NULL;
339 }
340 GNUNET_assert (NULL == handle->request_head);
341 GNUNET_free (handle);
342}
343
344
345/**
346 * Cancel pending verify request
347 *
348 * @param lr the verify request to cancel
349 */
350void
351GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *lr)
352{
353 struct GNUNET_CREDENTIAL_Handle *handle = lr->credential_handle;
354
355 GNUNET_CONTAINER_DLL_remove (handle->request_head,
356 handle->request_tail,
357 lr);
358 GNUNET_MQ_discard (lr->env);
359 GNUNET_free (lr);
360}
361
362
363/**
364 * Performs attribute collection.
365 * Collects all credentials of subject to fulfill the
366 * attribute, if possible
367 *
368 * @param handle handle to the Credential service
369 * @param issuer_key the issuer public key
370 * @param issuer_attribute the issuer attribute
371 * @param subject_key the subject public key
372 * @param proc function to call on result
373 * @param proc_cls closure for processor
374 * @return handle to the queued request
375 */
376struct GNUNET_CREDENTIAL_Request*
377GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
378 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
379 const char *issuer_attribute,
380 const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
381 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
382 void *proc_cls)
383{
384 /* IPC to shorten credential names, return shorten_handle */
385 struct CollectMessage *c_msg;
386 struct GNUNET_CREDENTIAL_Request *vr;
387 size_t nlen;
388
389 if (NULL == issuer_attribute)
390 {
391 GNUNET_break (0);
392 return NULL;
393 }
394
395 //DEBUG LOG
396 LOG (GNUNET_ERROR_TYPE_DEBUG,
397 "Trying to collect `%s' in CREDENTIAL\n",
398 issuer_attribute);
399 nlen = strlen (issuer_attribute) + 1;
400 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
401 {
402 GNUNET_break (0);
403 return NULL;
404 }
405 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
406 vr->credential_handle = handle;
407 vr->verify_proc = proc;
408 vr->proc_cls = proc_cls;
409 vr->r_id = handle->r_id_gen++;
410 vr->env = GNUNET_MQ_msg_extra (c_msg,
411 nlen,
412 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT);
413 c_msg->id = htonl (vr->r_id);
414 c_msg->subject_key = *subject_key;
415 c_msg->issuer_key = *issuer_key;
416 c_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
417 GNUNET_memcpy (&c_msg[1],
418 issuer_attribute,
419 strlen (issuer_attribute));
420 GNUNET_CONTAINER_DLL_insert (handle->request_head,
421 handle->request_tail,
422 vr);
423 if (NULL != handle->mq)
424 GNUNET_MQ_send_copy (handle->mq,
425 vr->env);
426 return vr;
427}
428/**
429 * Performs attribute verification.
430 * Checks if there is a delegation chain from
431 * attribute ``issuer_attribute'' issued by the issuer
432 * with public key ``issuer_key'' maps to the attribute
433 * ``subject_attribute'' claimed by the subject with key
434 * ``subject_key''
435 *
436 * @param handle handle to the Credential service
437 * @param issuer_key the issuer public key
438 * @param issuer_attribute the issuer attribute
439 * @param subject_key the subject public key
440 * @param credential_count number of credentials provided
441 * @param credentials subject credentials
442 * @param proc function to call on result
443 * @param proc_cls closure for processor
444 * @return handle to the queued request
445 */
446struct GNUNET_CREDENTIAL_Request*
447GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
448 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
449 const char *issuer_attribute,
450 const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
451 uint32_t credential_count,
452 const struct GNUNET_CREDENTIAL_Credential *credentials,
453 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
454 void *proc_cls)
455{
456 /* IPC to shorten credential names, return shorten_handle */
457 struct VerifyMessage *v_msg;
458 struct GNUNET_CREDENTIAL_Request *vr;
459 size_t nlen;
460 size_t clen;
461
462 if (NULL == issuer_attribute || NULL == credentials)
463 {
464 GNUNET_break (0);
465 return NULL;
466 }
467
468 clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
469 credentials);
470
471 //DEBUG LOG
472 LOG (GNUNET_ERROR_TYPE_DEBUG,
473 "Trying to verify `%s' in CREDENTIAL\n",
474 issuer_attribute);
475 nlen = strlen (issuer_attribute) + 1 + clen;
476 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
477 {
478 GNUNET_break (0);
479 return NULL;
480 }
481 vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
482 vr->credential_handle = handle;
483 vr->verify_proc = proc;
484 vr->proc_cls = proc_cls;
485 vr->r_id = handle->r_id_gen++;
486 vr->env = GNUNET_MQ_msg_extra (v_msg,
487 nlen,
488 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
489 v_msg->id = htonl (vr->r_id);
490 v_msg->subject_key = *subject_key;
491 v_msg->c_count = htonl(credential_count);
492 v_msg->issuer_key = *issuer_key;
493 v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
494 GNUNET_memcpy (&v_msg[1],
495 issuer_attribute,
496 strlen (issuer_attribute));
497 GNUNET_CREDENTIAL_credentials_serialize (credential_count,
498 credentials,
499 clen,
500 ((char*)&v_msg[1])
501 + strlen (issuer_attribute) + 1);
502 GNUNET_CONTAINER_DLL_insert (handle->request_head,
503 handle->request_tail,
504 vr);
505 if (NULL != handle->mq)
506 GNUNET_MQ_send_copy (handle->mq,
507 vr->env);
508 return vr;
509}
510
511/* end of credential_api.c */
diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c
new file mode 100644
index 000000000..c94c33919
--- /dev/null
+++ b/src/credential/credential_misc.c
@@ -0,0 +1,168 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_misc.c
24 * @brief Misc API for credentials
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34#include <inttypes.h>
35
36char*
37GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred)
38{
39 char *cred_str;
40 char *subject_pkey;
41 char *issuer_pkey;
42 char *signature;
43
44
45 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
46 issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
47 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
48 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
49 &signature);
50 GNUNET_asprintf (&cred_str,
51 "%s.%s -> %s | %s | %"SCNu64,
52 issuer_pkey,
53 cred->issuer_attribute,
54 subject_pkey,
55 signature,
56 cred->expiration.abs_value_us);
57 GNUNET_free (subject_pkey);
58 GNUNET_free (issuer_pkey);
59 GNUNET_free (signature);
60 return cred_str;
61}
62
63struct GNUNET_CREDENTIAL_Credential*
64GNUNET_CREDENTIAL_credential_from_string (const char* s)
65{
66 struct GNUNET_CREDENTIAL_Credential *cred;
67 size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
68 if (enclen % 5 > 0)
69 enclen += 5 - enclen % 5;
70 enclen /= 5; /* 260/5 = 52 */
71 char subject_pkey[enclen + 1];
72 char issuer_pkey[enclen + 1];
73 char name[253 + 1];
74 char signature[256]; //TODO max payload size
75
76 struct GNUNET_CRYPTO_EcdsaSignature *sig;
77 struct GNUNET_TIME_Absolute etime_abs;
78
79 if (5 != SSCANF (s,
80 "%52s.%253s -> %52s | %s | %"SCNu64,
81 issuer_pkey,
82 name,
83 subject_pkey,
84 signature,
85 &etime_abs.abs_value_us))
86 {
87 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
88 _("Unable to parse CRED record string `%s'\n"),
89 s);
90 return NULL;
91 }
92 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1);
93 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
94 strlen (subject_pkey),
95 &cred->subject_key);
96 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
97 strlen (issuer_pkey),
98 &cred->issuer_key);
99 GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature,
100 strlen (signature),
101 (char**)&sig));
102 cred->signature = *sig;
103 cred->expiration = etime_abs;
104 GNUNET_free (sig);
105 GNUNET_memcpy (&cred[1],
106 name,
107 strlen (name)+1);
108 cred->issuer_attribute_len = strlen ((char*)&cred[1]);
109 cred->issuer_attribute = (char*)&cred[1];
110 return cred;
111}
112
113/**
114 * Issue an attribute to a subject
115 *
116 * @param issuer the ego that should be used to issue the attribute
117 * @param subject the subject of the attribute
118 * @param attribute the name of the attribute
119 * @return handle to the queued request
120 */
121struct GNUNET_CREDENTIAL_Credential *
122GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
123 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
124 const char *attribute,
125 struct GNUNET_TIME_Absolute *expiration)
126{
127 struct CredentialEntry *crd;
128 struct GNUNET_CREDENTIAL_Credential *cred;
129 size_t size;
130
131 size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
132 crd = GNUNET_malloc (size);
133 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1);
134 crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
135
136 crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
137 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
138 &crd->issuer_key);
139 crd->subject_key = *subject;
140 crd->expiration = GNUNET_htonll (expiration->abs_value_us);
141 crd->issuer_attribute_len = htonl (strlen (attribute)+1);
142 GNUNET_memcpy ((char*)&crd[1],
143 attribute,
144 strlen (attribute)+1);
145 if (GNUNET_OK !=
146 GNUNET_CRYPTO_ecdsa_sign (issuer,
147 &crd->purpose,
148 &crd->signature))
149 {
150 GNUNET_break (0);
151 GNUNET_free (crd);
152 return NULL;
153 }
154 cred->signature = crd->signature;
155 cred->expiration = *expiration;
156 GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
157 &cred->issuer_key);
158
159 cred->subject_key = *subject;
160 GNUNET_memcpy (&cred[1],
161 attribute,
162 strlen (attribute)+1);
163 cred->issuer_attribute = (char*)&cred[1];
164 GNUNET_free (crd);
165 return cred;
166}
167
168
diff --git a/src/credential/credential_misc.h b/src/credential/credential_misc.h
new file mode 100644
index 000000000..c3aa8c214
--- /dev/null
+++ b/src/credential/credential_misc.h
@@ -0,0 +1,35 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @file credential/credential_misc.h
22 * @brief Credential helper functions
23 */
24#ifndef CREDENTIAL_MISC_H
25#define CREDENTIAL_MISC_H
26
27
28
29char*
30GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred);
31
32struct GNUNET_CREDENTIAL_Credential*
33GNUNET_CREDENTIAL_credential_from_string (const char* str);
34
35#endif
diff --git a/src/credential/credential_serialization.c b/src/credential/credential_serialization.c
new file mode 100644
index 000000000..1d23bb08c
--- /dev/null
+++ b/src/credential/credential_serialization.c
@@ -0,0 +1,460 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_serialization.c
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_credential_service.h"
32#include "gnunet_signatures.h"
33#include "credential.h"
34
35/**
36 * Calculate how many bytes we will need to serialize
37 * the given delegation chain
38 *
39 * @param ds_count number of delegation chain entries
40 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
41 * @return the required size to serialize
42 */
43size_t
44GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
45 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
46{
47 unsigned int i;
48 size_t ret;
49
50 ret = sizeof (struct DelegationRecordData) * (ds_count);
51
52 for (i=0; i<ds_count;i++)
53 {
54 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
55 ret += dsr[i].subject_attribute_len;
56 }
57 return ret;
58}
59
60/**
61 * Serizalize the given delegation chain entries and credential
62 *
63 * @param d_count number of delegation chain entries
64 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
65 * @param dest_size size of the destination
66 * @param dest where to store the result
67 * @return the size of the data, -1 on failure
68 */
69ssize_t
70GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
71 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
72 size_t dest_size,
73 char *dest)
74{
75 struct DelegationRecordData rec;
76 unsigned int i;
77 size_t off;
78
79 off = 0;
80 for (i=0;i<d_count;i++)
81 {
82 rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
83 rec.subject_key = dsr[i].subject_key;
84 if (off + sizeof (rec) > dest_size)
85 return -1;
86 GNUNET_memcpy (&dest[off],
87 &rec,
88 sizeof (rec));
89 off += sizeof (rec);
90 if (0 == dsr[i].subject_attribute_len)
91 continue;
92 if (off + dsr[i].subject_attribute_len > dest_size)
93 return -1;
94 GNUNET_memcpy (&dest[off],
95 dsr[i].subject_attribute,
96 dsr[i].subject_attribute_len);
97 off += dsr[i].subject_attribute_len;
98 }
99 return off;
100}
101
102
103/**
104 * Deserialize the given destination
105 *
106 * @param len size of the serialized delegation chain and cred
107 * @param src the serialized data
108 * @param d_count the number of delegation chain entries
109 * @param dsr where to put the delegation chain entries
110 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
111 */
112int
113GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
114 const char *src,
115 unsigned int d_count,
116 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
117{
118 struct DelegationRecordData rec;
119 unsigned int i;
120 size_t off;
121
122 off = 0;
123 for (i=0;i<d_count;i++)
124 {
125 if (off + sizeof (rec) > len)
126 return GNUNET_SYSERR;
127 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
128 dsr[i].subject_key = rec.subject_key;
129 off += sizeof (rec);
130 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
131 if (off + dsr[i].subject_attribute_len > len)
132 return GNUNET_SYSERR;
133 dsr[i].subject_attribute = (char*)&src[off];
134 off += dsr[i].subject_attribute_len;
135 }
136 return GNUNET_OK;
137}
138
139
140/**
141 * Calculate how many bytes we will need to serialize
142 * the credentials
143 *
144 * @param c_count number of credential entries
145 * @param cd a #GNUNET_CREDENTIAL_Credential
146 * @return the required size to serialize
147 */
148size_t
149GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
150 const struct GNUNET_CREDENTIAL_Credential *cd)
151{
152 unsigned int i;
153 size_t ret;
154
155 ret = sizeof (struct CredentialEntry) * (c_count);
156
157 for (i=0; i<c_count;i++)
158 {
159 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
160 ret += cd[i].issuer_attribute_len;
161 }
162 return ret;
163}
164/**
165 * Serizalize the given credentials
166 *
167 * @param c_count number of credential entries
168 * @param cd a #GNUNET_CREDENTIAL_Credential
169 * @param dest_size size of the destination
170 * @param dest where to store the result
171 * @return the size of the data, -1 on failure
172 */
173ssize_t
174GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
175 const struct GNUNET_CREDENTIAL_Credential *cd,
176 size_t dest_size,
177 char *dest)
178{
179 struct CredentialEntry c_rec;
180 unsigned int i;
181 size_t off;
182
183 off = 0;
184 for (i=0;i<c_count;i++)
185 {
186 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
187 c_rec.issuer_key = cd[i].issuer_key;
188 c_rec.subject_key = cd[i].subject_key;
189 c_rec.signature = cd[i].signature;
190 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
191 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
192 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
193 if (off + sizeof (c_rec) > dest_size)
194 return -1;
195 GNUNET_memcpy (&dest[off],
196 &c_rec,
197 sizeof (c_rec));
198 off += sizeof (c_rec);
199 if (off + cd[i].issuer_attribute_len > dest_size)
200 return -1;
201 GNUNET_memcpy (&dest[off],
202 cd[i].issuer_attribute,
203 cd[i].issuer_attribute_len);
204 off += cd[i].issuer_attribute_len;
205 }
206
207 return off;
208}
209
210
211
212/**
213 * Deserialize the given destination
214 *
215 * @param len size of the serialized creds
216 * @param src the serialized data
217 * @param c_count the number of credential entries
218 * @param cd where to put the credential data
219 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
220 */
221int
222GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
223 const char *src,
224 unsigned int c_count,
225 struct GNUNET_CREDENTIAL_Credential *cd)
226{
227 struct CredentialEntry c_rec;
228 unsigned int i;
229 size_t off;
230
231 off = 0;
232 for (i=0;i<c_count;i++)
233 {
234 if (off + sizeof (c_rec) > len)
235 return GNUNET_SYSERR;
236 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
237 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
238 cd[i].issuer_key = c_rec.issuer_key;
239 cd[i].subject_key = c_rec.subject_key;
240 cd[i].signature = c_rec.signature;
241 cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
242 off += sizeof (c_rec);
243 if (off + cd[i].issuer_attribute_len > len)
244 return GNUNET_SYSERR;
245 cd[i].issuer_attribute = &src[off];
246 off += cd[i].issuer_attribute_len;
247 }
248 return GNUNET_OK;
249}
250
251
252
253/**
254 * Calculate how many bytes we will need to serialize
255 * the given delegation chain and credential
256 *
257 * @param d_count number of delegation chain entries
258 * @param dd array of #GNUNET_CREDENTIAL_Delegation
259 * @param c_count number of credential entries
260 * @param cd a #GNUNET_CREDENTIAL_Credential
261 * @return the required size to serialize
262 */
263size_t
264GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
265 const struct GNUNET_CREDENTIAL_Delegation *dd,
266 unsigned int c_count,
267 const struct GNUNET_CREDENTIAL_Credential *cd)
268{
269 unsigned int i;
270 size_t ret;
271
272 ret = sizeof (struct ChainEntry) * (d_count);
273
274 for (i=0; i<d_count;i++)
275 {
276 GNUNET_assert ((ret +
277 dd[i].issuer_attribute_len +
278 dd[i].subject_attribute_len) >= ret);
279 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
280 }
281 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
282 return ret;
283}
284
285/**
286 * Serizalize the given delegation chain entries and credential
287 *
288 * @param d_count number of delegation chain entries
289 * @param dd array of #GNUNET_CREDENTIAL_Delegation
290 * @param c_count number of credential entries
291 * @param cd a #GNUNET_CREDENTIAL_Credential
292 * @param dest_size size of the destination
293 * @param dest where to store the result
294 * @return the size of the data, -1 on failure
295 */
296ssize_t
297GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
298 const struct GNUNET_CREDENTIAL_Delegation *dd,
299 unsigned int c_count,
300 const struct GNUNET_CREDENTIAL_Credential *cd,
301 size_t dest_size,
302 char *dest)
303{
304 struct ChainEntry rec;
305 unsigned int i;
306 size_t off;
307
308 off = 0;
309 for (i=0;i<d_count;i++)
310 {
311 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
312 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
313 rec.issuer_key = dd[i].issuer_key;
314 rec.subject_key = dd[i].subject_key;
315 if (off + sizeof (rec) > dest_size)
316 return -1;
317 GNUNET_memcpy (&dest[off],
318 &rec,
319 sizeof (rec));
320 off += sizeof (rec);
321 if (off + dd[i].issuer_attribute_len > dest_size)
322 return -1;
323 GNUNET_memcpy (&dest[off],
324 dd[i].issuer_attribute,
325 dd[i].issuer_attribute_len);
326 off += dd[i].issuer_attribute_len;
327 if (0 == dd[i].subject_attribute_len)
328 continue;
329 if (off + dd[i].subject_attribute_len > dest_size)
330 return -1;
331 GNUNET_memcpy (&dest[off],
332 dd[i].subject_attribute,
333 dd[i].subject_attribute_len);
334 off += dd[i].subject_attribute_len;
335 }
336 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
337 cd,
338 dest_size-off,
339 &dest[off]);
340}
341
342
343/**
344 * Deserialize the given destination
345 *
346 * @param len size of the serialized delegation chain and cred
347 * @param src the serialized data
348 * @param d_count the number of delegation chain entries
349 * @param dd where to put the delegation chain entries
350 * @param c_count the number of credential entries
351 * @param cd where to put the credential data
352 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
353 */
354int
355GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
356 const char *src,
357 unsigned int d_count,
358 struct GNUNET_CREDENTIAL_Delegation *dd,
359 unsigned int c_count,
360 struct GNUNET_CREDENTIAL_Credential *cd)
361{
362 struct ChainEntry rec;
363 unsigned int i;
364 size_t off;
365
366 off = 0;
367 for (i=0;i<d_count;i++)
368 {
369 if (off + sizeof (rec) > len)
370 return GNUNET_SYSERR;
371 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
372 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
373 dd[i].issuer_key = rec.issuer_key;
374 dd[i].subject_key = rec.subject_key;
375 off += sizeof (rec);
376 if (off + dd[i].issuer_attribute_len > len)
377 return GNUNET_SYSERR;
378 dd[i].issuer_attribute = &src[off];
379 off += dd[i].issuer_attribute_len;
380 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
381 if (off + dd[i].subject_attribute_len > len)
382 return GNUNET_SYSERR;
383 dd[i].subject_attribute = &src[off];
384 off += dd[i].subject_attribute_len;
385 }
386 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
387 &src[off],
388 c_count,
389 cd);
390}
391int
392GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
393 char **data)
394{
395 size_t size;
396 struct CredentialEntry *cdata;
397
398 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
399 *data = GNUNET_malloc (size);
400 cdata = (struct CredentialEntry*)*data;
401 cdata->subject_key = cred->subject_key;
402 cdata->issuer_key = cred->issuer_key;
403 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
404 cdata->signature = cred->signature;
405 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
406 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
407 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
408 GNUNET_memcpy (&cdata[1],
409 cred->issuer_attribute,
410 strlen (cred->issuer_attribute));
411
412 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
413 &cdata->purpose,
414 &cdata->signature,
415 &cdata->issuer_key))
416 {
417 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
418 "Invalid credential\n");
419 //return NULL;
420 }
421 return size;
422}
423
424struct GNUNET_CREDENTIAL_Credential*
425GNUNET_CREDENTIAL_credential_deserialize (const char* data,
426 size_t data_size)
427{
428 struct GNUNET_CREDENTIAL_Credential *cred;
429 struct CredentialEntry *cdata;
430 char *issuer_attribute;
431
432 if (data_size < sizeof (struct CredentialEntry))
433 return NULL;
434 cdata = (struct CredentialEntry*)data;
435 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
436 &cdata->purpose,
437 &cdata->signature,
438 &cdata->issuer_key))
439 {
440 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
441 "Invalid credential\n");
442 //return NULL;
443 }
444 issuer_attribute = (char*)&cdata[1];
445
446 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
447
448 cred->issuer_key = cdata->issuer_key;
449 cred->subject_key = cdata->subject_key;
450 GNUNET_memcpy (&cred[1],
451 issuer_attribute,
452 ntohl (cdata->issuer_attribute_len));
453 cred->signature = cdata->signature;
454 cred->issuer_attribute = (char*)&cred[1];
455 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
456 return cred;
457}
458
459
460/* end of credential_serialization.c */
diff --git a/src/credential/credential_serialization.h b/src/credential/credential_serialization.h
new file mode 100644
index 000000000..b870d47dc
--- /dev/null
+++ b/src/credential/credential_serialization.h
@@ -0,0 +1,159 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22/**
23 * @file credential/credential_serialization.h
24 * @brief API to serialize and deserialize delegation chains
25 * and credentials
26 * @author Martin Schanzenbach
27 */
28#ifndef CREDENTIAL_SERIALIZATION_H
29#define CREDENTIAL_SERIALIZATION_H
30
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_constants.h"
34#include "gnunet_credential_service.h"
35
36/**
37 * Calculate how many bytes we will need to serialize
38 * the given delegation record
39 *
40 * @param ds_count number of delegation chain entries
41 * @param dsr array of #GNUNET_CREDENTIAL_Delegation
42 * @return the required size to serialize
43 */
44size_t
45GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
46 const struct GNUNET_CREDENTIAL_DelegationSet *dsr);
47
48/**
49 * Serizalize the given delegation record entries
50 *
51 * @param d_count number of delegation chain entries
52 * @param dsr array of #GNUNET_CREDENTIAL_Delegation
53 * @param dest_size size of the destination
54 * @param dest where to store the result
55 * @return the size of the data, -1 on failure
56 */
57ssize_t
58GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
59 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
60 size_t dest_size,
61 char *dest);
62
63
64/**
65 * Deserialize the given destination
66 *
67 * @param len size of the serialized delegation recird
68 * @param src the serialized data
69 * @param d_count the number of delegation chain entries
70 * @param dsr where to put the delegation chain entries
71 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
72 */
73int
74GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
75 const char *src,
76 unsigned int d_count,
77 struct GNUNET_CREDENTIAL_DelegationSet *dsr);
78
79 /**
80 * Calculate how many bytes we will need to serialize
81 * the given delegation chain and credential
82 *
83 * @param d_count number of delegation chain entries
84 * @param dd array of #GNUNET_CREDENTIAL_Delegation
85 * @param c_count number of credential entries
86 * @param cd a #GNUNET_CREDENTIAL_Credential
87 * @return the required size to serialize
88 */
89 size_t
90 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
91 const struct GNUNET_CREDENTIAL_Delegation *dd,
92 unsigned int c_count,
93 const struct GNUNET_CREDENTIAL_Credential *cd);
94
95 /**
96 * Serizalize the given delegation chain entries and credential
97 *
98 * @param d_count number of delegation chain entries
99 * @param dd array of #GNUNET_CREDENTIAL_Delegation
100 * @param c_count number of credential entries
101 * @param cd a #GNUNET_CREDENTIAL_Credential
102 * @param dest_size size of the destination
103 * @param dest where to store the result
104 * @return the size of the data, -1 on failure
105 */
106 ssize_t
107 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
108 const struct GNUNET_CREDENTIAL_Delegation *dd,
109 unsigned int c_count,
110 const struct GNUNET_CREDENTIAL_Credential *cd,
111 size_t dest_size,
112 char *dest);
113
114
115 /**
116 * Deserialize the given destination
117 *
118 * @param len size of the serialized delegation chain and cred
119 * @param src the serialized data
120 * @param d_count the number of delegation chain entries
121 * @param dd where to put the delegation chain entries
122 * @param c_count number of credential entries
123 * @param cd where to put the credential data
124 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
125 */
126 int
127 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
128 const char *src,
129 unsigned int d_count,
130 struct GNUNET_CREDENTIAL_Delegation *dd,
131 unsigned int c_count,
132 struct GNUNET_CREDENTIAL_Credential *cd);
133 size_t
134 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
135 const struct GNUNET_CREDENTIAL_Credential *cd);
136
137ssize_t
138GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
139 const struct GNUNET_CREDENTIAL_Credential *cd,
140 size_t dest_size,
141 char *dest);
142
143
144int
145GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
146 const char *src,
147 unsigned int c_count,
148 struct GNUNET_CREDENTIAL_Credential *cd);
149
150
151int
152GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
153 char **data);
154
155struct GNUNET_CREDENTIAL_Credential*
156GNUNET_CREDENTIAL_credential_deserialize (const char* data,
157 size_t data_size);
158#endif
159/* end of credential_serialization.h */
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c
new file mode 100644
index 000000000..03f959b95
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,588 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file gnunet-credential.c
22 * @brief command line tool to access command line Credential service
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26#include <gnunet_util_lib.h>
27#include <gnunet_credential_service.h>
28#include <gnunet_gnsrecord_lib.h>
29#include "credential_misc.h"
30#include "credential_serialization.h"
31
32/**
33 * Configuration we are using.
34 */
35static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37/**
38 * EgoLookup
39 */
40static struct GNUNET_IDENTITY_EgoLookup *el;
41
42/**
43 * Handle to Credential service.
44 */
45static struct GNUNET_CREDENTIAL_Handle *credential;
46
47/**
48 * Desired timeout for the lookup (default is no timeout).
49 */
50static struct GNUNET_TIME_Relative timeout;
51
52/**
53 * Handle to verify request
54 */
55static struct GNUNET_CREDENTIAL_Request *verify_request;
56
57/**
58 * Handle to collect request
59 */
60static struct GNUNET_CREDENTIAL_Request *collect_request;
61
62/**
63 * Task scheduled to handle timeout.
64 */
65static struct GNUNET_SCHEDULER_Task *tt;
66
67/**
68 * Subject pubkey string
69 */
70static char *subject_key;
71
72/**
73 * Subject credential string
74 */
75static char *subject_credential;
76
77/**
78 * Credential TTL
79 */
80static char *expiration;
81
82/**
83 * Subject key
84 */
85struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
86
87/**
88 * Issuer key
89 */
90struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
91
92
93/**
94 * Issuer pubkey string
95 */
96static char *issuer_key;
97
98/**
99 * ego
100 */
101static char *ego_name;
102
103/**
104 * Issuer attribute
105 */
106static char *issuer_attr;
107
108/**
109 * Verify mode
110 */
111static int verify;
112
113/**
114 * Issue mode
115 */
116static int create_cred;
117
118/**
119 * Collect mode
120 */
121static int collect;
122
123/**
124 * Task run on shutdown. Cleans up everything.
125 *
126 * @param cls unused
127 */
128static void
129do_shutdown (void *cls)
130{
131 if (NULL != verify_request)
132 {
133 GNUNET_CREDENTIAL_request_cancel (verify_request);
134 verify_request = NULL;
135 }
136 if (NULL != credential)
137 {
138 GNUNET_CREDENTIAL_disconnect (credential);
139 credential = NULL;
140 }
141 if (NULL != tt)
142 {
143 GNUNET_SCHEDULER_cancel (tt);
144 tt = NULL;
145 }
146}
147
148
149/**
150 * Task run on timeout. Triggers shutdown.
151 *
152 * @param cls unused
153 */
154static void
155do_timeout (void *cls)
156{
157 tt = NULL;
158 GNUNET_SCHEDULER_shutdown ();
159}
160
161static void
162handle_collect_result (void *cls,
163 unsigned int d_count,
164 struct GNUNET_CREDENTIAL_Delegation *dc,
165 unsigned int c_count,
166 struct GNUNET_CREDENTIAL_Credential *cred)
167{
168 int i;
169 char* line;
170
171 verify_request = NULL;
172 if (NULL != cred)
173 {
174 for (i=0;i<c_count;i++)
175 {
176 line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
177 printf ("%s\n",
178 line);
179 GNUNET_free (line);
180 }
181 }
182
183
184 GNUNET_SCHEDULER_shutdown ();
185}
186
187
188static void
189handle_verify_result (void *cls,
190 unsigned int d_count,
191 struct GNUNET_CREDENTIAL_Delegation *dc,
192 unsigned int c_count,
193 struct GNUNET_CREDENTIAL_Credential *cred)
194{
195 int i;
196 char* iss_key;
197 char* sub_key;
198
199 verify_request = NULL;
200 if (NULL == cred)
201 printf ("Failed.\n");
202 else
203 {
204 printf("Delegation Chain:\n");
205 for (i=0;i<d_count;i++)
206 {
207 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
208 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
209 if (0 != dc[i].subject_attribute_len)
210 {
211 printf ("(%d) %s.%s <- %s.%s\n", i,
212 iss_key, dc[i].issuer_attribute,
213 sub_key, dc[i].subject_attribute);
214 } else {
215 printf ("(%d) %s.%s <- %s\n", i,
216 iss_key, dc[i].issuer_attribute,
217 sub_key);
218 }
219 GNUNET_free (iss_key);
220 GNUNET_free (sub_key);
221 }
222 printf("\nCredentials:\n");
223 for (i=0;i<c_count;i++)
224 {
225 iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
226 sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
227 printf ("%s.%s <- %s\n",
228 iss_key, cred[i].issuer_attribute,
229 sub_key);
230 GNUNET_free (iss_key);
231 GNUNET_free (sub_key);
232
233 }
234 printf ("Successful.\n");
235 }
236
237
238 GNUNET_SCHEDULER_shutdown ();
239}
240
241/**
242 * Callback invoked from identity service with ego information.
243 * An @a ego of NULL means the ego was not found.
244 *
245 * @param cls closure with the configuration
246 * @param ego an ego known to identity service, or NULL
247 */
248static void
249identity_cb (void *cls,
250 const struct GNUNET_IDENTITY_Ego *ego)
251{
252 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
253 struct GNUNET_CREDENTIAL_Credential *crd;
254 struct GNUNET_TIME_Absolute etime_abs;
255 struct GNUNET_TIME_Relative etime_rel;
256 char *res;
257
258 el = NULL;
259 if (NULL == ego)
260 {
261 if (NULL != ego_name)
262 {
263 fprintf (stderr,
264 _("Ego `%s' not known to identity service\n"),
265 ego_name);
266 }
267 GNUNET_SCHEDULER_shutdown ();
268 return;
269 }
270
271 if (GNUNET_YES == collect)
272 {
273
274 if (GNUNET_OK !=
275 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
276 strlen (issuer_key),
277 &issuer_pkey))
278 {
279 fprintf (stderr,
280 _("Issuer public key `%s' is not well-formed\n"),
281 issuer_key);
282 GNUNET_SCHEDULER_shutdown ();
283 }
284 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
285
286 collect_request = GNUNET_CREDENTIAL_collect(credential,
287 &issuer_pkey,
288 issuer_attr, //TODO argument
289 privkey,
290 &handle_collect_result,
291 NULL);
292 return;
293 }
294
295 //Else issue
296
297 if (NULL == expiration)
298 {
299 fprintf (stderr,
300 "Please specify a TTL\n");
301 GNUNET_SCHEDULER_shutdown ();
302 return;
303 } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
304 &etime_rel))
305 {
306 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
307 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
308 &etime_abs))
309 {
310 fprintf (stderr,
311 "%s is not a valid ttl!\n",
312 expiration);
313 GNUNET_SCHEDULER_shutdown ();
314 return;
315 }
316
317
318 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
319 GNUNET_free_non_null (ego_name);
320 ego_name = NULL;
321 crd = GNUNET_CREDENTIAL_credential_issue (privkey,
322 &subject_pkey,
323 issuer_attr,
324 &etime_abs);
325
326 res = GNUNET_CREDENTIAL_credential_to_string (crd);
327 GNUNET_free (crd);
328 printf ("%s\n", res);
329 GNUNET_SCHEDULER_shutdown ();
330}
331
332
333
334
335/**
336 * Main function that will be run.
337 *
338 * @param cls closure
339 * @param args remaining command-line arguments
340 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
341 * @param c configuration
342 */
343static void
344run (void *cls,
345 char *const *args,
346 const char *cfgfile,
347 const struct GNUNET_CONFIGURATION_Handle *c)
348{
349
350 cfg = c;
351
352
353 tt = GNUNET_SCHEDULER_add_delayed (timeout,
354 &do_timeout, NULL);
355 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
356
357 if (GNUNET_YES == collect) {
358 if (NULL == issuer_key)
359 {
360 fprintf (stderr,
361 _("Issuer public key not well-formed\n"));
362 GNUNET_SCHEDULER_shutdown ();
363 return;
364
365 }
366
367 credential = GNUNET_CREDENTIAL_connect (cfg);
368
369 if (NULL == credential)
370 {
371 fprintf (stderr,
372 _("Failed to connect to CREDENTIAL\n"));
373 GNUNET_SCHEDULER_shutdown ();
374 }
375 if (NULL == issuer_attr)
376 {
377 fprintf (stderr,
378 _("You must provide issuer the attribute\n"));
379 GNUNET_SCHEDULER_shutdown ();
380 }
381
382 if (NULL == ego_name)
383 {
384 fprintf (stderr,
385 _("ego required\n"));
386 GNUNET_SCHEDULER_shutdown ();
387 return;
388
389 }
390 el = GNUNET_IDENTITY_ego_lookup (cfg,
391 ego_name,
392 &identity_cb,
393 (void *) cfg);
394 return;
395
396 }
397
398 if (NULL == subject_key)
399 {
400 fprintf (stderr,
401 _("Subject public key needed\n"));
402 GNUNET_SCHEDULER_shutdown ();
403 return;
404
405 }
406 if (GNUNET_OK !=
407 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
408 strlen (subject_key),
409 &subject_pkey))
410 {
411 fprintf (stderr,
412 _("Subject public key `%s' is not well-formed\n"),
413 subject_key);
414 GNUNET_SCHEDULER_shutdown ();
415 return;
416 }
417 if (GNUNET_YES == verify) {
418 if (NULL == issuer_key)
419 {
420 fprintf (stderr,
421 _("Issuer public key not well-formed\n"));
422 GNUNET_SCHEDULER_shutdown ();
423 return;
424
425 }
426 if (GNUNET_OK !=
427 GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
428 strlen (issuer_key),
429 &issuer_pkey))
430 {
431 fprintf (stderr,
432 _("Issuer public key `%s' is not well-formed\n"),
433 issuer_key);
434 GNUNET_SCHEDULER_shutdown ();
435 }
436 credential = GNUNET_CREDENTIAL_connect (cfg);
437
438 if (NULL == credential)
439 {
440 fprintf (stderr,
441 _("Failed to connect to CREDENTIAL\n"));
442 GNUNET_SCHEDULER_shutdown ();
443 }
444 if (NULL == issuer_attr || NULL == subject_credential)
445 {
446 fprintf (stderr,
447 _("You must provide issuer and subject attributes\n"));
448 GNUNET_SCHEDULER_shutdown ();
449 }
450
451 //Subject credentials are comma separated
452 char *tmp = GNUNET_strdup (subject_credential);
453 char *tok = strtok (tmp, ",");
454 if (NULL == tok)
455 {
456 fprintf (stderr,
457 "Invalid subject credentials\n");
458 GNUNET_free (tmp);
459 GNUNET_SCHEDULER_shutdown ();
460 }
461 int count = 1;
462 int i;
463 while (NULL != (tok = strtok(NULL, ",")))
464 count++;
465 struct GNUNET_CREDENTIAL_Credential credentials[count];
466 struct GNUNET_CREDENTIAL_Credential *cred;
467 GNUNET_free (tmp);
468 tmp = GNUNET_strdup (subject_credential);
469 tok = strtok (tmp, ",");
470 for (i=0;i<count;i++)
471 {
472 cred = GNUNET_CREDENTIAL_credential_from_string (tok);
473 GNUNET_memcpy (&credentials[i],
474 cred,
475 sizeof (struct GNUNET_CREDENTIAL_Credential));
476 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
477 tok = strtok(NULL, ",");
478 GNUNET_free (cred);
479 }
480
481 verify_request = GNUNET_CREDENTIAL_verify(credential,
482 &issuer_pkey,
483 issuer_attr, //TODO argument
484 &subject_pkey,
485 count,
486 credentials,
487 &handle_verify_result,
488 NULL);
489 for (i=0;i<count;i++)
490 {
491 GNUNET_free ((char*)credentials[i].issuer_attribute);
492 }
493 } else if (GNUNET_YES == create_cred) {
494 if (NULL == ego_name)
495 {
496 fprintf (stderr,
497 _("Issuer ego required\n"));
498 GNUNET_SCHEDULER_shutdown ();
499 return;
500
501 }
502 el = GNUNET_IDENTITY_ego_lookup (cfg,
503 ego_name,
504 &identity_cb,
505 (void *) cfg);
506 return;
507 } else {
508 fprintf (stderr,
509 _("Please specify name to lookup, subject key and issuer key!\n"));
510 GNUNET_SCHEDULER_shutdown ();
511 }
512 return;
513}
514
515
516/**
517 * The main function for gnunet-gns.
518 *
519 * @param argc number of arguments from the command line
520 * @param argv command line arguments
521 * @return 0 ok, 1 on error
522 */
523int
524main (int argc, char *const *argv)
525{
526 struct GNUNET_GETOPT_CommandLineOption options[] = {
527 GNUNET_GETOPT_option_flag ('I',
528 "issue",
529 gettext_noop ("create credential"),
530 &create_cred),
531 GNUNET_GETOPT_option_flag ('V',
532 "verify",
533 gettext_noop ("verify credential against attribute"),
534 &verify),
535 GNUNET_GETOPT_option_string ('s',
536 "subject",
537 "PKEY",
538 gettext_noop ("The public key of the subject to lookup the credential for"),
539 &subject_key),
540 GNUNET_GETOPT_option_string ('b',
541 "credential",
542 "CRED",
543 gettext_noop ("The name of the credential presented by the subject"),
544 &subject_credential),
545 GNUNET_GETOPT_option_string ('i',
546 "issuer",
547 "PKEY",
548 gettext_noop ("The public key of the authority to verify the credential against"),
549 &issuer_key),
550 GNUNET_GETOPT_option_string ('e',
551 "ego",
552 "EGO",
553 gettext_noop ("The ego to use"),
554 &ego_name),
555 GNUNET_GETOPT_option_string ('a',
556 "attribute",
557 "ATTR",
558 gettext_noop ("The issuer attribute to verify against or to issue"),
559 &issuer_attr),
560 GNUNET_GETOPT_option_string ('T',
561 "ttl",
562 "EXP",
563 gettext_noop ("The time to live for the credential"),
564 &expiration),
565 GNUNET_GETOPT_option_flag ('g',
566 "collect",
567 gettext_noop ("collect credentials"),
568 &collect),
569 GNUNET_GETOPT_OPTION_END
570 };
571 int ret;
572
573 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
574 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
575 return 2;
576
577 GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
578 ret =
579 (GNUNET_OK ==
580 GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
581 _("GNUnet credential resolver tool"),
582 options,
583 &run, NULL)) ? 0 : 1;
584 GNUNET_free ((void*) argv);
585 return ret;
586}
587
588/* end of gnunet-credential.c */
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c
new file mode 100644
index 000000000..be88839e9
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1160 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file credential/gnunet-service-credential.c
22 * @brief GNUnet Credential Service (main service)
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_credential_service.h"
28#include "gnunet_statistics_service.h"
29#include "credential.h"
30#include "credential_serialization.h"
31#include "gnunet_protocols.h"
32#include "gnunet_signatures.h"
33
34#include <gnunet_dnsparser_lib.h>
35#include <gnunet_identity_service.h>
36#include <gnunet_gnsrecord_lib.h>
37#include <gnunet_namestore_service.h>
38#include <gnunet_gns_service.h>
39
40
41#define GNUNET_CREDENTIAL_MAX_LENGTH 255
42
43struct VerifyRequestHandle;
44
45struct DelegationSetQueueEntry;
46
47
48struct DelegationChainEntry
49{
50 /**
51 * DLL
52 */
53 struct DelegationChainEntry *next;
54
55 /**
56 * DLL
57 */
58 struct DelegationChainEntry *prev;
59
60 /**
61 * The issuer
62 */
63 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
64
65 /**
66 * The subject
67 */
68 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
69
70 /**
71 * The issued attribute
72 */
73 char *issuer_attribute;
74
75 /**
76 * The delegated attribute
77 */
78 char *subject_attribute;
79};
80
81/**
82 * DLL for record
83 */
84struct CredentialRecordEntry
85{
86 /**
87 * DLL
88 */
89 struct CredentialRecordEntry *next;
90
91 /**
92 * DLL
93 */
94 struct CredentialRecordEntry *prev;
95
96 /**
97 * Number of references in delegation chains
98 */
99 uint32_t refcount;
100
101 /**
102 * Payload
103 */
104 struct GNUNET_CREDENTIAL_Credential *credential;
105};
106
107/**
108 * DLL used for delegations
109 * Used for OR delegations
110 */
111struct DelegationQueueEntry
112{
113 /**
114 * DLL
115 */
116 struct DelegationQueueEntry *next;
117
118 /**
119 * DLL
120 */
121 struct DelegationQueueEntry *prev;
122
123 /**
124 * Sets under this Queue
125 */
126 struct DelegationSetQueueEntry *set_entries_head;
127
128 /**
129 * Sets under this Queue
130 */
131 struct DelegationSetQueueEntry *set_entries_tail;
132
133 /**
134 * Parent set
135 */
136 struct DelegationSetQueueEntry *parent_set;
137
138 /**
139 * Required solutions
140 */
141 uint32_t required_solutions;
142};
143
144/**
145 * DLL for delegation sets
146 * Used for AND delegation set
147 */
148struct DelegationSetQueueEntry
149{
150 /**
151 * DLL
152 */
153 struct DelegationSetQueueEntry *next;
154
155 /**
156 * DLL
157 */
158 struct DelegationSetQueueEntry *prev;
159
160 /**
161 * GNS handle
162 */
163 struct GNUNET_GNS_LookupRequest *lookup_request;
164
165 /**
166 * Verify handle
167 */
168 struct VerifyRequestHandle *handle;
169
170 /**
171 * Parent attribute delegation
172 */
173 struct DelegationQueueEntry *parent;
174
175 /**
176 * Issuer key
177 */
178 struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
179
180 /**
181 * Queue entries of this set
182 */
183 struct DelegationQueueEntry *queue_entries_head;
184
185 /**
186 * Queue entries of this set
187 */
188 struct DelegationQueueEntry *queue_entries_tail;
189
190 /**
191 * Parent QueueEntry
192 */
193 struct DelegationQueueEntry *parent_queue_entry;
194
195 /**
196 * Issuer attribute delegated to
197 */
198 char *issuer_attribute;
199
200 /**
201 * The current attribute to look up
202 */
203 char *lookup_attribute;
204
205 /**
206 * Trailing attribute context
207 */
208 char *attr_trailer;
209
210 /**
211 * Still to resolve delegation as string
212 */
213 char *unresolved_attribute_delegation;
214
215 /**
216 * The delegation chain entry
217 */
218 struct DelegationChainEntry *delegation_chain_entry;
219
220};
221
222
223/**
224 * Handle to a lookup operation from api
225 */
226struct VerifyRequestHandle
227{
228
229 /**
230 * We keep these in a DLL.
231 */
232 struct VerifyRequestHandle *next;
233
234 /**
235 * We keep these in a DLL.
236 */
237 struct VerifyRequestHandle *prev;
238
239 /**
240 * Handle to the requesting client
241 */
242 struct GNUNET_SERVICE_Client *client;
243
244 /**
245 * GNS handle
246 */
247 struct GNUNET_GNS_LookupRequest *lookup_request;
248
249 /**
250 * Size of delegation tree
251 */
252 uint32_t delegation_chain_size;
253
254 /**
255 * Children of this attribute
256 */
257 struct DelegationChainEntry *delegation_chain_head;
258
259 /**
260 * Children of this attribute
261 */
262 struct DelegationChainEntry *delegation_chain_tail;
263
264 /**
265 * Issuer public key
266 */
267 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
268
269 /**
270 * Issuer attribute
271 */
272 char *issuer_attribute;
273
274 /**
275 * Subject public key
276 */
277 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
278
279 /**
280 * Credential DLL
281 */
282 struct CredentialRecordEntry *cred_chain_head;
283
284 /**
285 * Credential DLL
286 */
287 struct CredentialRecordEntry *cred_chain_tail;
288
289 /**
290 * Credential DLL size
291 */
292 uint32_t cred_chain_size;
293
294 /**
295 * Root Delegation Set
296 */
297 struct DelegationSetQueueEntry *root_set;
298
299 /**
300 * Current Delegation Pointer
301 */
302 struct DelegationQueueEntry *current_delegation;
303
304 /**
305 * request id
306 */
307 uint32_t request_id;
308
309 /**
310 * Pending lookups
311 */
312 uint64_t pending_lookups;
313
314 /**
315 * Credential iterator
316 */
317 struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
318
319 /**
320 * Collect task
321 */
322 struct GNUNET_SCHEDULER_Task *collect_next_task;
323
324};
325
326
327/**
328 * Head of the DLL.
329 */
330static struct VerifyRequestHandle *vrh_head;
331
332/**
333 * Tail of the DLL.
334 */
335static struct VerifyRequestHandle *vrh_tail;
336
337/**
338 * Handle to the statistics service
339 */
340static struct GNUNET_STATISTICS_Handle *statistics;
341
342/**
343 * Handle to GNS service.
344 */
345static struct GNUNET_GNS_Handle *gns;
346
347
348/**
349 * Handle to namestore service
350 */
351static struct GNUNET_NAMESTORE_Handle *namestore;
352
353static void
354cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
355{
356 struct DelegationQueueEntry *dq_entry;
357 struct DelegationSetQueueEntry *child;
358
359 if (NULL == ds_entry)
360 return;
361
362 for (dq_entry = ds_entry->queue_entries_head;
363 NULL != dq_entry;
364 dq_entry = ds_entry->queue_entries_head)
365 {
366 GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
367 ds_entry->queue_entries_tail,
368 dq_entry);
369 for (child = dq_entry->set_entries_head;
370 NULL != child;
371 child = dq_entry->set_entries_head)
372 {
373 GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
374 dq_entry->set_entries_tail,
375 child);
376 cleanup_delegation_set (child);
377 }
378 GNUNET_free (dq_entry);
379 }
380 GNUNET_free_non_null (ds_entry->issuer_key);
381 GNUNET_free_non_null (ds_entry->lookup_attribute);
382 GNUNET_free_non_null (ds_entry->issuer_attribute);
383 GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation);
384 GNUNET_free_non_null (ds_entry->attr_trailer);
385 if (NULL != ds_entry->lookup_request)
386 {
387 GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
388 ds_entry->lookup_request = NULL;
389 }
390 if (NULL != ds_entry->delegation_chain_entry)
391 {
392 GNUNET_free_non_null (ds_entry->delegation_chain_entry->subject_attribute);
393 GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute);
394 GNUNET_free (ds_entry->delegation_chain_entry);
395 }
396 GNUNET_free (ds_entry);
397}
398
399static void
400cleanup_handle (struct VerifyRequestHandle *vrh)
401{
402 struct CredentialRecordEntry *cr_entry;
403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
404 "Cleaning up...\n");
405 if (NULL != vrh->lookup_request)
406 {
407 GNUNET_GNS_lookup_cancel (vrh->lookup_request);
408 vrh->lookup_request = NULL;
409 }
410 cleanup_delegation_set (vrh->root_set);
411 GNUNET_free_non_null (vrh->issuer_attribute);
412 for (cr_entry = vrh->cred_chain_head;
413 NULL != vrh->cred_chain_head;
414 cr_entry = vrh->cred_chain_head)
415 {
416 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
417 vrh->cred_chain_tail,
418 cr_entry);
419 GNUNET_free_non_null (cr_entry->credential);
420 GNUNET_free (cr_entry);
421 }
422 GNUNET_free (vrh);
423}
424
425static void
426shutdown_task (void *cls)
427{
428 struct VerifyRequestHandle *vrh;
429
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
431 "Shutting down!\n");
432
433 while (NULL != (vrh = vrh_head))
434 {
435 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
436 GNUNET_CONTAINER_DLL_remove (vrh_head,
437 vrh_tail,
438 vrh);
439 cleanup_handle (vrh);
440 }
441
442 if (NULL != gns)
443 {
444 GNUNET_GNS_disconnect (gns);
445 gns = NULL;
446 }
447 if (NULL != namestore)
448 {
449 GNUNET_NAMESTORE_disconnect (namestore);
450 namestore = NULL;
451 }
452 if (NULL != statistics)
453 {
454 GNUNET_STATISTICS_destroy (statistics,
455 GNUNET_NO);
456 statistics = NULL;
457 }
458
459}
460
461
462
463static void
464send_lookup_response (struct VerifyRequestHandle *vrh)
465{
466 struct GNUNET_MQ_Envelope *env;
467 struct DelegationChainResultMessage *rmsg;
468 struct DelegationChainEntry *dce;
469 struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
470 struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
471 struct CredentialRecordEntry *cd;
472 struct CredentialRecordEntry *tmp;
473 size_t size;
474
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Sending response\n");
477 dce = vrh->delegation_chain_head;
478 for (uint32_t i=0;i<vrh->delegation_chain_size;i++)
479 {
480 dd[i].issuer_key = dce->issuer_key;
481 dd[i].subject_key = dce->subject_key;
482 dd[i].issuer_attribute = dce->issuer_attribute;
483 dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
484 dd[i].subject_attribute_len = 0;
485 dd[i].subject_attribute = NULL;
486 if (NULL != dce->subject_attribute)
487 {
488 dd[i].subject_attribute = dce->subject_attribute;
489 dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
490 }
491 dce = dce->next;
492 }
493
494 /**
495 * Remove all credentials not needed
496 */
497 for (cd = vrh->cred_chain_head; NULL != cd;)
498 {
499 if (cd->refcount > 0)
500 {
501 cd = cd->next;
502 continue;
503 }
504 tmp = cd;
505 cd = cd->next;
506 GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
507 vrh->cred_chain_tail,
508 tmp);
509 GNUNET_free (tmp->credential);
510 GNUNET_free (tmp);
511 vrh->cred_chain_size--;
512 }
513
514 /**
515 * Get serialized record data
516 * Append at the end of rmsg
517 */
518 cd = vrh->cred_chain_head;
519 for (uint32_t i=0;i<vrh->cred_chain_size;i++)
520 {
521 cred[i].issuer_key = cd->credential->issuer_key;
522 cred[i].subject_key = cd->credential->subject_key;
523 cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
524 cred[i].issuer_attribute = cd->credential->issuer_attribute;
525 cred[i].expiration = cd->credential->expiration;
526 cred[i].signature = cd->credential->signature;
527 cd = cd->next;
528 }
529 size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
530 dd,
531 vrh->cred_chain_size,
532 cred);
533 env = GNUNET_MQ_msg_extra (rmsg,
534 size,
535 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
536 //Assign id so that client can find associated request
537 rmsg->id = vrh->request_id;
538 rmsg->d_count = htonl (vrh->delegation_chain_size);
539 rmsg->c_count = htonl (vrh->cred_chain_size);
540
541 if (0 < vrh->cred_chain_size)
542 rmsg->cred_found = htonl (GNUNET_YES);
543 else
544 rmsg->cred_found = htonl (GNUNET_NO);
545
546 GNUNET_assert (-1 !=
547 GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
548 dd,
549 vrh->cred_chain_size,
550 cred,
551 size,
552 (char*)&rmsg[1]));
553
554 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
555 env);
556 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
557 cleanup_handle(vrh);
558
559 GNUNET_STATISTICS_update (statistics,
560 "Completed verifications", 1,
561 GNUNET_NO);
562}
563
564
565static void
566backward_resolution (void* cls,
567 uint32_t rd_count,
568 const struct GNUNET_GNSRECORD_Data *rd)
569{
570
571 struct VerifyRequestHandle *vrh;
572 const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
573 struct CredentialRecordEntry *cred_pointer;
574 struct DelegationSetQueueEntry *current_set;
575 struct DelegationSetQueueEntry *ds_entry;
576 struct DelegationSetQueueEntry *tmp_set;
577 struct DelegationQueueEntry *dq_entry;
578 char *expanded_attr;
579 char *lookup_attribute;
580
581
582 current_set = cls;
583 current_set->lookup_request = NULL;
584 vrh = current_set->handle;
585 vrh->pending_lookups--;
586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
587 "Got %d attrs\n", rd_count);
588
589 // Each OR
590 for (uint32_t i=0; i < rd_count; i++)
591 {
592 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
593 continue;
594
595 sets = rd[i].data;
596 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
598 "Found new attribute delegation with %d sets. Creating new Job...\n",
599 ntohl (sets->set_count));
600
601 if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
602 (const char*)&sets[1],
603 ntohl(sets->set_count),
604 set))
605 {
606 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
607 "Failed to deserialize!\n");
608 continue;
609 }
610 dq_entry = GNUNET_new (struct DelegationQueueEntry);
611 dq_entry->required_solutions = ntohl(sets->set_count);
612 dq_entry->parent_set = current_set;
613 GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
614 current_set->queue_entries_tail,
615 dq_entry);
616 // Each AND
617 for (uint32_t j=0; j<ntohl(sets->set_count); j++)
618 {
619 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
620 if (NULL != current_set->attr_trailer)
621 {
622 if (0 == set[j].subject_attribute_len)
623 {
624 GNUNET_asprintf (&expanded_attr,
625 "%s",
626 current_set->attr_trailer);
627
628 } else {
629 GNUNET_asprintf (&expanded_attr,
630 "%s.%s",
631 set[j].subject_attribute,
632 current_set->attr_trailer);
633 }
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Expanded to %s\n", expanded_attr);
636 ds_entry->unresolved_attribute_delegation = expanded_attr;
637 } else {
638 if (0 != set[j].subject_attribute_len)
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
641 "Not Expanding %s\n", set[j].subject_attribute);
642 ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
643 }
644 }
645
646 //Add a credential chain entry
647 ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
648 ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
649 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
650 GNUNET_memcpy (ds_entry->issuer_key,
651 &set[j].subject_key,
652 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
653 if (0 < set[j].subject_attribute_len)
654 ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
655 ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
656 ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
657
658 ds_entry->parent_queue_entry = dq_entry; //current_delegation;
659 GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
660 dq_entry->set_entries_tail,
661 ds_entry);
662
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
664 "Checking for cred match\n");
665 /**
666 * Check if this delegation already matches one of our credentials
667 */
668 for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
669 cred_pointer = cred_pointer->next)
670 {
671 if(0 != memcmp (&set->subject_key,
672 &cred_pointer->credential->issuer_key,
673 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
674 continue;
675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
676 "Checking if %s matches %s\n",
677 ds_entry->unresolved_attribute_delegation,
678 cred_pointer->credential->issuer_attribute);
679
680 if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
681 cred_pointer->credential->issuer_attribute))
682 continue;
683
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
685 "Found issuer\n");
686 cred_pointer->refcount++;
687 //Backtrack
688 for (tmp_set = ds_entry;
689 NULL != tmp_set->parent_queue_entry;
690 tmp_set = tmp_set->parent_queue_entry->parent_set)
691 {
692 tmp_set->parent_queue_entry->required_solutions--;
693 if (NULL != tmp_set->delegation_chain_entry)
694 {
695 vrh->delegation_chain_size++;
696 GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
697 vrh->delegation_chain_tail,
698 tmp_set->delegation_chain_entry);
699 }
700 if (0 < tmp_set->parent_queue_entry->required_solutions)
701 break;
702 }
703
704 if (NULL == tmp_set->parent_queue_entry)
705 {
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 "All solutions found\n");
708 //Found match
709 send_lookup_response (vrh);
710 return;
711 }
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "Not all solutions found yet.\n");
714 continue;
715
716 }
717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718 "Building new lookup request from %s\n",
719 ds_entry->unresolved_attribute_delegation);
720 //Continue with backward resolution
721 char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
722 strcpy (issuer_attribute_name,
723 ds_entry->unresolved_attribute_delegation);
724 char *next_attr = strtok (issuer_attribute_name, ".");
725 GNUNET_asprintf (&lookup_attribute,
726 "%s.gnu",
727 next_attr);
728 GNUNET_asprintf (&ds_entry->lookup_attribute,
729 "%s",
730 next_attr);
731 if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
732 {
733 ds_entry->attr_trailer = NULL;
734 } else {
735 next_attr += strlen (next_attr) + 1;
736 ds_entry->attr_trailer = GNUNET_strdup (next_attr);
737 }
738
739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
740 "Looking up %s\n", ds_entry->lookup_attribute);
741 if (NULL != ds_entry->attr_trailer)
742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
743 "%s still to go...\n", ds_entry->attr_trailer);
744
745 vrh->pending_lookups++;
746 ds_entry->handle = vrh;
747 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
748 lookup_attribute,
749 ds_entry->issuer_key, //issuer_key,
750 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
751 GNUNET_GNS_LO_DEFAULT,
752 &backward_resolution,
753 ds_entry);
754 GNUNET_free (lookup_attribute);
755 }
756 }
757
758 if(0 == vrh->pending_lookups)
759 {
760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
761 "We are all out of attributes...\n");
762 send_lookup_response (vrh);
763 return;
764
765 }
766}
767
768
769/**
770 * Result from GNS lookup.
771 *
772 * @param cls the closure (our client lookup handle)
773 */
774static void
775delegation_chain_resolution_start (void* cls)
776{
777 struct VerifyRequestHandle *vrh = cls;
778 struct DelegationSetQueueEntry *ds_entry;
779 struct CredentialRecordEntry *cr_entry;
780 vrh->lookup_request = NULL;
781
782 if (0 == vrh->cred_chain_size)
783 {
784 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
785 "No credentials found\n");
786 send_lookup_response (vrh);
787 return;
788 }
789
790 for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
791 {
792 if (0 != memcmp (&cr_entry->credential->issuer_key,
793 &vrh->issuer_key,
794 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
795 continue;
796 if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
797 continue;
798 cr_entry->refcount++;
799 //Found match prematurely
800 send_lookup_response (vrh);
801 return;
802
803 }
804
805 /**
806 * Check for attributes from the issuer and follow the chain
807 * till you get the required subject's attributes
808 */
809 char issuer_attribute_name[strlen (vrh->issuer_attribute)];
810 strcpy (issuer_attribute_name,
811 vrh->issuer_attribute);
812 strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
813 ".gnu");
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815 "Looking up %s\n", issuer_attribute_name);
816 ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
817 ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
818 memcpy (ds_entry->issuer_key,
819 &vrh->issuer_key,
820 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
821 ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
822 ds_entry->handle = vrh;
823 ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
824 vrh->root_set = ds_entry;
825 vrh->pending_lookups = 1;
826 //Start with backward resolution
827 ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
828 issuer_attribute_name,
829 &vrh->issuer_key, //issuer_key,
830 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
831 GNUNET_GNS_LO_DEFAULT,
832 &backward_resolution,
833 ds_entry);
834}
835
836static int
837check_verify (void *cls,
838 const struct VerifyMessage *v_msg)
839{
840 size_t msg_size;
841 const char* attr;
842
843 msg_size = ntohs (v_msg->header.size);
844 if (msg_size < sizeof (struct VerifyMessage))
845 {
846 GNUNET_break (0);
847 return GNUNET_SYSERR;
848 }
849 if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
850 {
851 GNUNET_break (0);
852 return GNUNET_SYSERR;
853 }
854 attr = (const char *) &v_msg[1];
855
856 if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
857 {
858 GNUNET_break (0);
859 return GNUNET_SYSERR;
860 }
861 return GNUNET_OK;
862}
863
864static void
865handle_verify (void *cls,
866 const struct VerifyMessage *v_msg)
867{
868 struct VerifyRequestHandle *vrh;
869 struct GNUNET_SERVICE_Client *client = cls;
870 struct CredentialRecordEntry *cr_entry;
871 uint32_t credentials_count;
872 uint32_t credential_data_size;
873 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
874 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
875 char *attrptr = attr;
876 char *credential_data;
877 const char *utf_in;
878
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
880 "Received VERIFY message\n");
881 utf_in = (const char *) &v_msg[1];
882 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
883 GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
884 issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
885 vrh = GNUNET_new (struct VerifyRequestHandle);
886 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
887 vrh->client = client;
888 vrh->request_id = v_msg->id;
889 vrh->issuer_key = v_msg->issuer_key;
890 vrh->subject_key = v_msg->subject_key;
891 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
892 if (NULL == issuer_attribute)
893 {
894 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
895 "No issuer attribute provided!\n");
896 send_lookup_response (vrh);
897 return;
898 }
899 /**
900 * First, collect credentials
901 * TODO: cleanup!
902 */
903 credentials_count = ntohl(v_msg->c_count);
904 credential_data_size = ntohs (v_msg->header.size)
905 - sizeof (struct VerifyMessage)
906 - ntohs (v_msg->issuer_attribute_len)
907 - 1;
908 struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
909 credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
910 if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
911 credential_data,
912 credentials_count,
913 credentials))
914 {
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
916 "Cannot deserialize credentials!\n");
917 send_lookup_response (vrh);
918 return;
919 }
920
921 for (uint32_t i=0;i<credentials_count;i++) {
922 cr_entry = GNUNET_new (struct CredentialRecordEntry);
923 cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
924 credentials[i].issuer_attribute_len);
925 GNUNET_memcpy (cr_entry->credential,
926 &credentials[i],
927 sizeof (struct GNUNET_CREDENTIAL_Credential));
928 GNUNET_memcpy (&cr_entry->credential[1],
929 credentials[i].issuer_attribute,
930 credentials[i].issuer_attribute_len);
931 cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
932 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
933 vrh->cred_chain_tail,
934 cr_entry);
935 vrh->cred_chain_size++;
936 }
937
938 delegation_chain_resolution_start (vrh);
939
940}
941
942static void
943handle_cred_collection_error_cb (void *cls)
944{
945 struct VerifyRequestHandle *vrh = cls;
946 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
947 "Got disconnected from namestore database.\n");
948 vrh->cred_collection_iter = NULL;
949 send_lookup_response (vrh);
950}
951
952static void
953collect_next (void *cls)
954{
955 struct VerifyRequestHandle *vrh = cls;
956 vrh->collect_next_task = NULL;
957 GNUNET_assert (NULL != vrh->cred_collection_iter);
958 GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
959}
960
961static void
962handle_cred_collection_cb (void *cls,
963 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
964 const char *label,
965 unsigned int rd_count,
966 const struct GNUNET_GNSRECORD_Data *rd)
967{
968 struct VerifyRequestHandle *vrh = cls;
969 struct GNUNET_CREDENTIAL_Credential *crd;
970 struct CredentialRecordEntry *cr_entry;
971 int cred_record_count;
972
973 cred_record_count = 0;
974 for (uint32_t i=0; i < rd_count; i++)
975 {
976 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
977 continue;
978 cred_record_count++;
979 crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
980 rd[i].data_size);
981 if (NULL == crd)
982 {
983 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
984 "Invalid credential found\n");
985 continue;
986 }
987 cr_entry = GNUNET_new (struct CredentialRecordEntry);
988 cr_entry->credential = crd;
989 GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
990 vrh->cred_chain_tail,
991 cr_entry);
992 vrh->cred_chain_size++;
993 }
994 vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
995 vrh);
996}
997
998static void
999handle_cred_collection_finished_cb (void *cls)
1000{
1001 struct VerifyRequestHandle *vrh = cls;
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 "Done collecting credentials.\n");
1004 vrh->cred_collection_iter = NULL;
1005 delegation_chain_resolution_start (vrh);
1006}
1007
1008static void
1009handle_collect (void *cls,
1010 const struct CollectMessage *c_msg)
1011{
1012 char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1013 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
1014 struct VerifyRequestHandle *vrh;
1015 struct GNUNET_SERVICE_Client *client = cls;
1016 char *attrptr = attr;
1017 const char *utf_in;
1018
1019 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1020 "Received COLLECT message\n");
1021
1022 utf_in = (const char *) &c_msg[1];
1023 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
1024
1025 GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
1026 issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
1027 vrh = GNUNET_new (struct VerifyRequestHandle);
1028 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
1029 vrh->client = client;
1030 vrh->request_id = c_msg->id;
1031 vrh->issuer_key = c_msg->issuer_key;
1032 GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
1033 &vrh->subject_key);
1034 vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
1035
1036 if (NULL == issuer_attribute)
1037 {
1038 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1039 "No issuer attribute provided!\n");
1040 send_lookup_response (vrh);
1041 return;
1042 }
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1044 "Getting credentials for subject\n");
1045 /**
1046 * First, get attribute from subject
1047 */
1048 vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
1049 &c_msg->subject_key,
1050 &handle_cred_collection_error_cb,
1051 vrh,
1052 &handle_cred_collection_cb,
1053 vrh,
1054 &handle_cred_collection_finished_cb,
1055 vrh);
1056}
1057
1058
1059static int
1060check_collect (void *cls,
1061 const struct CollectMessage *c_msg)
1062{
1063 size_t msg_size;
1064 const char* attr;
1065
1066 msg_size = ntohs (c_msg->header.size);
1067 if (msg_size < sizeof (struct CollectMessage))
1068 {
1069 GNUNET_break (0);
1070 return GNUNET_SYSERR;
1071 }
1072 if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
1073 {
1074 GNUNET_break (0);
1075 return GNUNET_SYSERR;
1076 }
1077 attr = (const char *) &c_msg[1];
1078
1079 if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
1080 (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
1081 {
1082 GNUNET_break (0);
1083 return GNUNET_SYSERR;
1084 }
1085 return GNUNET_OK;
1086}
1087
1088static void
1089client_disconnect_cb (void *cls,
1090 struct GNUNET_SERVICE_Client *client,
1091 void *app_ctx)
1092{
1093 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1094 "Client %p disconnected\n",
1095 client);
1096}
1097
1098static void *
1099client_connect_cb (void *cls,
1100 struct GNUNET_SERVICE_Client *client,
1101 struct GNUNET_MQ_Handle *mq)
1102{
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104 "Client %p connected\n",
1105 client);
1106 return client;
1107}
1108
1109/**
1110 * Process Credential requests.
1111 *
1112 * @param cls closure
1113 * @param c configuration to use
1114 * @param handle service handle
1115 */
1116static void
1117run (void *cls,
1118 const struct GNUNET_CONFIGURATION_Handle *c,
1119 struct GNUNET_SERVICE_Handle *handle)
1120{
1121
1122 gns = GNUNET_GNS_connect (c);
1123 if (NULL == gns)
1124 {
1125 fprintf (stderr,
1126 _("Failed to connect to GNS\n"));
1127 }
1128 namestore = GNUNET_NAMESTORE_connect (c);
1129 if (NULL == namestore)
1130 {
1131 fprintf (stderr,
1132 _("Failed to connect to namestore\n"));
1133 }
1134
1135 statistics = GNUNET_STATISTICS_create ("credential", c);
1136 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1137}
1138
1139
1140/**
1141 * Define "main" method using service macro
1142 */
1143GNUNET_SERVICE_MAIN
1144("credential",
1145 GNUNET_SERVICE_OPTION_NONE,
1146 &run,
1147 &client_connect_cb,
1148 &client_disconnect_cb,
1149 NULL,
1150 GNUNET_MQ_hd_var_size (verify,
1151 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
1152 struct VerifyMessage,
1153 NULL),
1154 GNUNET_MQ_hd_var_size (collect,
1155 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
1156 struct CollectMessage,
1157 NULL),
1158 GNUNET_MQ_handler_end());
1159
1160/* end of gnunet-service-credential.c */
diff --git a/src/credential/plugin_gnsrecord_credential.c b/src/credential/plugin_gnsrecord_credential.c
new file mode 100644
index 000000000..342790b7a
--- /dev/null
+++ b/src/credential/plugin_gnsrecord_credential.c
@@ -0,0 +1,353 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file credential/plugin_gnsrecord_credential.c
23 * @brief gnsrecord plugin to provide the API for CREDENTIAL records
24 * @author Martin Schanzenbach
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_credential_service.h"
31#include "gnunet_gnsrecord_plugin.h"
32#include "gnunet_signatures.h"
33#include "credential_serialization.h"
34#include "credential_misc.h"
35
36/**
37 * Convert the 'value' of a record to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the record
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46credential_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51
52 const char *cdata;
53
54 switch (type)
55 {
56 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
57 {
58 struct GNUNET_CREDENTIAL_DelegationRecord sets;
59 char *attr_str;
60 char *subject_pkey;
61 char *tmp_str;
62 int i;
63 if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
64 return NULL; /* malformed */
65 memcpy (&sets,
66 data,
67 sizeof (sets));
68 cdata = data;
69 struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
70 if (GNUNET_OK != GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll (sets.data_size),
71 &cdata[sizeof (sets)],
72 ntohl (sets.set_count),
73 set))
74 return NULL;
75
76 for (i=0;i<ntohl(sets.set_count);i++)
77 {
78 subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key);
79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
80 "%d len attr\n", set[i].subject_attribute_len);
81 if (0 == set[i].subject_attribute_len)
82 {
83 if (0 == i)
84 {
85 GNUNET_asprintf (&attr_str,
86 "%s",
87 subject_pkey);
88 } else {
89 GNUNET_asprintf (&tmp_str,
90 "%s,%s",
91 attr_str,
92 subject_pkey);
93 GNUNET_free (attr_str);
94 attr_str = tmp_str;
95 }
96 } else {
97 if (0 == i)
98 {
99 GNUNET_asprintf (&attr_str,
100 "%s %s",
101 subject_pkey,
102 set[i].subject_attribute);
103 } else {
104 GNUNET_asprintf (&tmp_str,
105 "%s,%s %s",
106 attr_str,
107 subject_pkey,
108 set[i].subject_attribute);
109 GNUNET_free (attr_str);
110 attr_str = tmp_str;
111 }
112 }
113 GNUNET_free (subject_pkey);
114 }
115 return attr_str;
116 }
117 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
118 {
119 struct GNUNET_CREDENTIAL_Credential *cred;
120 char *cred_str;
121
122 cred = GNUNET_CREDENTIAL_credential_deserialize (data,
123 data_size);
124 cred_str = GNUNET_CREDENTIAL_credential_to_string (cred);
125 GNUNET_free (cred);
126 return cred_str;
127 }
128 case GNUNET_GNSRECORD_TYPE_POLICY:
129 {
130 return GNUNET_strndup (data,data_size);
131 }
132 default:
133 return NULL;
134 }
135}
136
137
138/**
139 * Convert human-readable version of a 'value' of a record to the binary
140 * representation.
141 *
142 * @param cls closure, unused
143 * @param type type of the record
144 * @param s human-readable string
145 * @param data set to value in binary encoding (will be allocated)
146 * @param data_size set to number of bytes in @a data
147 * @return #GNUNET_OK on success
148 */
149static int
150credential_string_to_value (void *cls,
151 uint32_t type,
152 const char *s,
153 void **data,
154 size_t *data_size)
155{
156 if (NULL == s)
157 return GNUNET_SYSERR;
158 switch (type)
159 {
160 case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
161 {
162 struct GNUNET_CREDENTIAL_DelegationRecord *sets;
163 char attr_str[253 + 1];
164 char subject_pkey[52 + 1];
165 char *token;
166 char *tmp_str;
167 int matches = 0;
168 int entries;
169 size_t tmp_data_size;
170 int i;
171
172 tmp_str = GNUNET_strdup (s);
173 token = strtok (tmp_str, ",");
174 entries = 0;
175 tmp_data_size = 0;
176 *data_size = sizeof (struct GNUNET_CREDENTIAL_DelegationRecord);
177 while (NULL != token)
178 {
179 matches = SSCANF (token,
180 "%s %s",
181 subject_pkey,
182 attr_str);
183 if (0 == matches)
184 {
185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186 _("Unable to parse ATTR record string `%s'\n"),
187 s);
188 GNUNET_free (tmp_str);
189 return GNUNET_SYSERR;
190 }
191 if (1 == matches) {
192 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet);
193 } else if (2 == matches) {
194 tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
195 }
196 entries++;
197 token = strtok (NULL, ",");
198 }
199 GNUNET_free (tmp_str);
200 tmp_str = GNUNET_strdup (s);
201 token = strtok (tmp_str, ",");
202 struct GNUNET_CREDENTIAL_DelegationSet set[entries];
203 for (i=0;i<entries;i++)
204 {
205 matches = SSCANF (token,
206 "%s %s",
207 subject_pkey,
208 attr_str);
209 GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
210 strlen (subject_pkey),
211 &set[i].subject_key);
212 if (2 == matches) {
213 set[i].subject_attribute_len = strlen (attr_str) + 1;
214 set[i].subject_attribute = GNUNET_strdup (attr_str);
215 }
216 token = strtok (NULL , ",");
217 }
218 tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
219 set);
220
221 if (-1 == tmp_data_size)
222 return GNUNET_SYSERR;
223 *data_size += tmp_data_size;
224 *data = sets = GNUNET_malloc (*data_size);
225 GNUNET_CREDENTIAL_delegation_set_serialize (entries,
226 set,
227 tmp_data_size,
228 (char*)&sets[1]);
229 for (i=0;i<entries;i++)
230 {
231 if (0 != set[i].subject_attribute_len)
232 GNUNET_free ((char*)set[i].subject_attribute);
233 }
234 sets->set_count = htonl (entries);
235 sets->data_size = GNUNET_htonll (tmp_data_size);
236
237 GNUNET_free (tmp_str);
238 return GNUNET_OK;
239 }
240 case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
241 {
242 struct GNUNET_CREDENTIAL_Credential *cred;
243 cred = GNUNET_CREDENTIAL_credential_from_string (s);
244
245 *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
246 (char**)data);
247 return GNUNET_OK;
248 }
249 case GNUNET_GNSRECORD_TYPE_POLICY:
250 {
251 *data_size = strlen (s);
252 *data = GNUNET_strdup (s);
253 return GNUNET_OK;
254 }
255 default:
256 return GNUNET_SYSERR;
257 }
258}
259
260
261/**
262 * Mapping of record type numbers to human-readable
263 * record type names.
264 */
265static struct {
266 const char *name;
267 uint32_t number;
268} name_map[] = {
269 { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
270 { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
271 { "POLICY", GNUNET_GNSRECORD_TYPE_POLICY },
272 { NULL, UINT32_MAX }
273};
274
275
276/**
277 * Convert a type name (i.e. "AAAA") to the corresponding number.
278 *
279 * @param cls closure, unused
280 * @param gns_typename name to convert
281 * @return corresponding number, UINT32_MAX on error
282 */
283static uint32_t
284credential_typename_to_number (void *cls,
285 const char *gns_typename)
286{
287 unsigned int i;
288
289 i=0;
290 while ( (name_map[i].name != NULL) &&
291 (0 != strcasecmp (gns_typename, name_map[i].name)) )
292 i++;
293 return name_map[i].number;
294}
295
296
297/**
298 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
299 *
300 * @param cls closure, unused
301 * @param type number of a type to convert
302 * @return corresponding typestring, NULL on error
303 */
304static const char *
305credential_number_to_typename (void *cls,
306 uint32_t type)
307{
308 unsigned int i;
309
310 i=0;
311 while ( (name_map[i].name != NULL) &&
312 (type != name_map[i].number) )
313 i++;
314 return name_map[i].name;
315}
316
317
318/**
319 * Entry point for the plugin.
320 *
321 * @param cls NULL
322 * @return the exported block API
323 */
324void *
325libgnunet_plugin_gnsrecord_credential_init (void *cls)
326{
327 struct GNUNET_GNSRECORD_PluginFunctions *api;
328
329 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
330 api->value_to_string = &credential_value_to_string;
331 api->string_to_value = &credential_string_to_value;
332 api->typename_to_number = &credential_typename_to_number;
333 api->number_to_typename = &credential_number_to_typename;
334 return api;
335}
336
337
338/**
339 * Exit point from the plugin.
340 *
341 * @param cls the return value from #libgnunet_plugin_block_test_init
342 * @return NULL
343 */
344void *
345libgnunet_plugin_gnsrecord_credential_done (void *cls)
346{
347 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
348
349 GNUNET_free (api);
350 return NULL;
351}
352
353/* end of plugin_gnsrecord_credential.c */
diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c
new file mode 100644
index 000000000..480658822
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,1146 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file credential/plugin_rest_credential.c
23 * @brief GNUnet CREDENTIAL REST plugin
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_rest_plugin.h"
29#include <gnunet_identity_service.h>
30#include <gnunet_gnsrecord_lib.h>
31#include <gnunet_namestore_service.h>
32#include <gnunet_credential_service.h>
33#include <gnunet_rest_lib.h>
34#include <gnunet_jsonapi_lib.h>
35#include <gnunet_jsonapi_util.h>
36#include <jansson.h>
37
38#define GNUNET_REST_API_NS_CREDENTIAL "/credential"
39
40#define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
41
42#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
43
44#define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
45
46#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
47
48#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
49
50#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
51
52#define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
53
54#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
55
56#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
57
58#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
59
60#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
61
62/**
63 * @brief struct returned by the initialization function of the plugin
64 */
65struct Plugin
66{
67 const struct GNUNET_CONFIGURATION_Handle *cfg;
68};
69
70const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72struct RequestHandle
73{
74 /**
75 * Handle to Credential service.
76 */
77 struct GNUNET_CREDENTIAL_Handle *credential;
78
79 /**
80 * Handle to lookup request
81 */
82 struct GNUNET_CREDENTIAL_Request *verify_request;
83
84 /**
85 * Handle to issue request
86 */
87 struct GNUNET_CREDENTIAL_Request *issue_request;
88
89 /**
90 * Handle to identity
91 */
92 struct GNUNET_IDENTITY_Handle *identity;
93
94 /**
95 * Handle to identity operation
96 */
97 struct GNUNET_IDENTITY_Operation *id_op;
98
99 /**
100 * Handle to ego lookup
101 */
102 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
103
104 /**
105 * Handle to rest request
106 */
107 struct GNUNET_REST_RequestHandle *rest_handle;
108
109 /**
110 * ID of a task associated with the resolution process.
111 */
112 struct GNUNET_SCHEDULER_Task * timeout_task;
113
114 /**
115 * The root of the received JSON or NULL
116 */
117 json_t *json_root;
118
119 /**
120 * The plugin result processor
121 */
122 GNUNET_REST_ResultProcessor proc;
123
124 /**
125 * The closure of the result processor
126 */
127 void *proc_cls;
128
129 /**
130 * The issuer attribute to verify
131 */
132 char *issuer_attr;
133
134 /**
135 * The subject attribute
136 */
137 char *subject_attr;
138
139 /**
140 * The public key of the issuer
141 */
142 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
143
144 /**
145 * The public key of the subject
146 */
147 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
148
149 /**
150 * HTTP response code
151 */
152 int response_code;
153
154 /**
155 * Timeout
156 */
157 struct GNUNET_TIME_Relative timeout;
158
159};
160
161
162/**
163 * Cleanup lookup handle.
164 *
165 * @param handle Handle to clean up
166 */
167static void
168cleanup_handle (struct RequestHandle *handle)
169{
170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
171 "Cleaning up\n");
172 if (NULL != handle->json_root)
173 json_decref (handle->json_root);
174
175 if (NULL != handle->issuer_attr)
176 GNUNET_free (handle->issuer_attr);
177 if (NULL != handle->subject_attr)
178 GNUNET_free (handle->subject_attr);
179 if (NULL != handle->verify_request)
180 GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
181 if (NULL != handle->credential)
182 GNUNET_CREDENTIAL_disconnect (handle->credential);
183 if (NULL != handle->id_op)
184 GNUNET_IDENTITY_cancel (handle->id_op);
185 if (NULL != handle->ego_lookup)
186 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
187 if (NULL != handle->identity)
188 GNUNET_IDENTITY_disconnect (handle->identity);
189 if (NULL != handle->timeout_task)
190 {
191 GNUNET_SCHEDULER_cancel (handle->timeout_task);
192 }
193 GNUNET_free (handle);
194}
195
196
197static void
198do_error (void *cls)
199{
200 struct RequestHandle *handle = cls;
201 struct MHD_Response *resp;
202
203 resp = GNUNET_REST_create_response (NULL);
204 handle->proc (handle->proc_cls, resp, handle->response_code);
205 cleanup_handle (handle);
206}
207
208/**
209 * Attribute delegation to JSON
210 *
211 * @param delegation_chain_entry the DSE
212 * @return JSON, NULL if failed
213 */
214static json_t*
215attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
216{
217 char *subject;
218 char *issuer;
219 json_t *attr_obj;
220
221 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
222 if (NULL == issuer)
223 {
224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 "Issuer in delegation malformed\n");
226 return NULL;
227 }
228 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
229 if (NULL == subject)
230 {
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 "Subject in credential malformed\n");
233 GNUNET_free (issuer);
234 return NULL;
235 }
236 attr_obj = json_object ();
237
238 json_object_set_new (attr_obj, "issuer", json_string (issuer));
239 json_object_set_new (attr_obj, "issuer_attribute",
240 json_string (delegation_chain_entry->issuer_attribute));
241
242 json_object_set_new (attr_obj, "subject", json_string (subject));
243 if (0 < delegation_chain_entry->subject_attribute_len)
244 {
245 json_object_set_new (attr_obj, "subject_attribute",
246 json_string (delegation_chain_entry->subject_attribute));
247 }
248 GNUNET_free (issuer);
249 GNUNET_free (subject);
250 return attr_obj;
251}
252
253/**
254 * JSONAPI resource to Credential
255 *
256 * @param res the JSONAPI resource
257 * @return the resulting credential, NULL if failed
258 */
259static struct GNUNET_CREDENTIAL_Credential*
260json_to_credential (json_t *res)
261{
262 struct GNUNET_CREDENTIAL_Credential *cred;
263 json_t *tmp;
264 const char *attribute;
265 const char *signature;
266 char *sig;
267
268 tmp = json_object_get (res, "attribute");
269 if (0 == json_is_string (tmp))
270 {
271 return NULL;
272 }
273 attribute = json_string_value (tmp);
274 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
275 + strlen (attribute));
276 cred->issuer_attribute = attribute;
277 cred->issuer_attribute_len = strlen (attribute);
278 tmp = json_object_get (res, "issuer");
279 if (0 == json_is_string (tmp))
280 {
281 GNUNET_free (cred);
282 return NULL;
283 }
284
285 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
286 strlen (json_string_value(tmp)),
287 &cred->issuer_key);
288 tmp = json_object_get (res, "subject");
289 if (0 == json_is_string (tmp))
290 {
291 GNUNET_free (cred);
292 return NULL;
293 }
294 GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
295 strlen (json_string_value(tmp)),
296 &cred->subject_key);
297
298 tmp = json_object_get (res, "signature");
299 if (0 == json_is_string (tmp))
300 {
301 GNUNET_free (cred);
302 return NULL;
303 }
304 signature = json_string_value (tmp);
305 GNUNET_STRINGS_base64_decode (signature,
306 strlen (signature),
307 (char**)&sig);
308 GNUNET_memcpy (&cred->signature,
309 sig,
310 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
311 GNUNET_free (sig);
312
313 tmp = json_object_get (res, "expiration");
314 if (0 == json_is_integer (tmp))
315 {
316 GNUNET_free (cred);
317 return NULL;
318 }
319 cred->expiration.abs_value_us = json_integer_value (tmp);
320 return cred;
321}
322
323
324/**
325 * Credential to JSON
326 *
327 * @param cred the credential
328 * @return the resulting json, NULL if failed
329 */
330static json_t*
331credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
332{
333 char *issuer;
334 char *subject;
335 char *signature;
336 char attribute[cred->issuer_attribute_len + 1];
337 json_t *cred_obj;
338
339 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
340 if (NULL == issuer)
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
343 "Issuer in credential malformed\n");
344 return NULL;
345 }
346 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
347 if (NULL == subject)
348 {
349 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
350 "Subject in credential malformed\n");
351 GNUNET_free (issuer);
352 return NULL;
353 }
354 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
355 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
356 &signature);
357 memcpy (attribute,
358 cred->issuer_attribute,
359 cred->issuer_attribute_len);
360 attribute[cred->issuer_attribute_len] = '\0';
361 cred_obj = json_object ();
362 json_object_set_new (cred_obj, "issuer", json_string (issuer));
363 json_object_set_new (cred_obj, "subject", json_string (subject));
364 json_object_set_new (cred_obj, "attribute", json_string (attribute));
365 json_object_set_new (cred_obj, "signature", json_string (signature));
366 json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
367 GNUNET_free (issuer);
368 GNUNET_free (subject);
369 GNUNET_free (signature);
370 return cred_obj;
371}
372
373static void
374handle_collect_response (void *cls,
375 unsigned int d_count,
376 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
377 unsigned int c_count,
378 struct GNUNET_CREDENTIAL_Credential *cred)
379{
380 struct RequestHandle *handle = cls;
381 struct MHD_Response *resp;
382 struct GNUNET_JSONAPI_Document *json_document;
383 struct GNUNET_JSONAPI_Resource *json_resource;
384 json_t *cred_obj;
385 json_t *cred_array;
386 char *result;
387 char *issuer;
388 char *id;
389 uint32_t i;
390
391 handle->verify_request = NULL;
392 if (NULL == cred) {
393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
394 "Verify failed.\n");
395 handle->response_code = MHD_HTTP_NOT_FOUND;
396 GNUNET_SCHEDULER_add_now (&do_error, handle);
397 return;
398 }
399 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
400 if (NULL == issuer)
401 {
402 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403 "Issuer in delegation malformed\n");
404 return;
405 }
406 GNUNET_asprintf (&id,
407 "%s.%s",
408 issuer,
409 handle->issuer_attr);
410 GNUNET_free (issuer);
411 json_document = GNUNET_JSONAPI_document_new ();
412 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
413 id);
414 GNUNET_free (id);
415 cred_array = json_array ();
416 for (i=0;i<c_count;i++)
417 {
418 cred_obj = credential_to_json (&cred[i]);
419 json_array_append_new (cred_array, cred_obj);
420 }
421 GNUNET_JSONAPI_resource_add_attr (json_resource,
422 GNUNET_REST_JSONAPI_CREDENTIAL,
423 cred_array);
424 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
425 GNUNET_JSONAPI_document_serialize (json_document, &result);
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
427 "Result %s\n",
428 result);
429 json_decref (cred_array);
430 GNUNET_JSONAPI_document_delete (json_document);
431 resp = GNUNET_REST_create_response (result);
432 GNUNET_free(result);
433 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
434 cleanup_handle (handle);
435}
436
437static void
438subject_ego_lookup (void *cls,
439 const struct GNUNET_IDENTITY_Ego *ego)
440{
441 struct RequestHandle *handle = cls;
442 const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
443 handle->ego_lookup = NULL;
444
445 if (NULL == ego)
446 {
447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
448 "Subject not found\n");
449 GNUNET_SCHEDULER_add_now (&do_error, handle);
450 return;
451 }
452 sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
453 handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
454 &handle->issuer_key,
455 handle->issuer_attr,
456 sub_key,
457 &handle_collect_response,
458 handle);
459}
460
461
462
463static void
464handle_verify_response (void *cls,
465 unsigned int d_count,
466 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
467 unsigned int c_count,
468 struct GNUNET_CREDENTIAL_Credential *cred)
469{
470
471 struct RequestHandle *handle = cls;
472 struct MHD_Response *resp;
473 struct GNUNET_JSONAPI_Document *json_document;
474 struct GNUNET_JSONAPI_Resource *json_resource;
475 json_t *cred_obj;
476 json_t *attr_obj;
477 json_t *cred_array;
478 json_t *attr_array;
479 char *result;
480 char *issuer;
481 char *id;
482 uint32_t i;
483
484 handle->verify_request = NULL;
485 if (NULL == cred) {
486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
487 "Verify failed.\n");
488 handle->response_code = MHD_HTTP_NOT_FOUND;
489 GNUNET_SCHEDULER_add_now (&do_error, handle);
490 return;
491 }
492 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
493 if (NULL == issuer)
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
496 "Issuer in delegation malformed\n");
497 return;
498 }
499 GNUNET_asprintf (&id,
500 "%s.%s",
501 issuer,
502 handle->issuer_attr);
503 GNUNET_free (issuer);
504 json_document = GNUNET_JSONAPI_document_new ();
505 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
506 id);
507 GNUNET_free (id);
508 attr_array = json_array ();
509 for (i = 0; i < d_count; i++)
510 {
511 attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
512 json_array_append_new (attr_array, attr_obj);
513 }
514 cred_array = json_array ();
515 for (i=0;i<c_count;i++)
516 {
517 cred_obj = credential_to_json (&cred[i]);
518 json_array_append_new (cred_array, cred_obj);
519 }
520 GNUNET_JSONAPI_resource_add_attr (json_resource,
521 GNUNET_REST_JSONAPI_CREDENTIAL,
522 cred_array);
523 GNUNET_JSONAPI_resource_add_attr (json_resource,
524 GNUNET_REST_JSONAPI_DELEGATIONS,
525 attr_array);
526 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
527 GNUNET_JSONAPI_document_serialize (json_document, &result);
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Result %s\n",
530 result);
531 json_decref (attr_array);
532 json_decref (cred_array);
533 GNUNET_JSONAPI_document_delete (json_document);
534 resp = GNUNET_REST_create_response (result);
535 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
536 GNUNET_free (result);
537 cleanup_handle (handle);
538}
539
540static void
541collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
542 const char* url,
543 void *cls)
544{
545 struct RequestHandle *handle = cls;
546 struct GNUNET_HashCode key;
547 char *tmp;
548 char *entity_attr;
549
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
551 "Connecting...\n");
552 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
553 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
554 &do_error, handle);
555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
556 "Connected\n");
557 if (NULL == handle->credential)
558 {
559 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560 "Connecting to CREDENTIAL failed\n");
561 GNUNET_SCHEDULER_add_now (&do_error, handle);
562 return;
563 }
564 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
565 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
566 &key);
567 if ( GNUNET_NO ==
568 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
569 &key) )
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 "Missing issuer attribute\n");
573 GNUNET_SCHEDULER_add_now (&do_error, handle);
574 return;
575 }
576 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
577 &key);
578 entity_attr = GNUNET_strdup (tmp);
579 tmp = strtok(entity_attr, ".");
580 if (NULL == tmp)
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
583 "Malformed issuer or attribute\n");
584 GNUNET_free (entity_attr);
585 GNUNET_SCHEDULER_add_now (&do_error, handle);
586 return;
587 }
588 if (GNUNET_OK !=
589 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
590 strlen (tmp),
591 &handle->issuer_key))
592 {
593 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
594 "Malformed issuer key\n");
595 GNUNET_free (entity_attr);
596 GNUNET_SCHEDULER_add_now (&do_error, handle);
597 return;
598 }
599 tmp = strtok (NULL, "."); //Issuer attribute
600 if (NULL == tmp)
601 {
602 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603 "Malformed attribute\n");
604 GNUNET_free (entity_attr);
605 GNUNET_SCHEDULER_add_now (&do_error, handle);
606 return;
607 }
608 handle->issuer_attr = GNUNET_strdup (tmp);
609 GNUNET_free (entity_attr);
610
611 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
612 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
613 &key);
614 if ( GNUNET_NO ==
615 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
616 &key) )
617 {
618 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619 "Missing subject\n");
620 GNUNET_free (entity_attr);
621 GNUNET_SCHEDULER_add_now (&do_error, handle);
622 return;
623 }
624 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
625 &key);
626 if (NULL == tmp)
627 {
628 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
629 "Malformed subject\n");
630 GNUNET_free (entity_attr);
631 GNUNET_SCHEDULER_add_now (&do_error, handle);
632 return;
633 }
634 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
635 tmp,
636 &subject_ego_lookup,
637 handle);
638}
639
640
641
642static void
643verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
644 const char* url,
645 void *cls)
646{
647 struct RequestHandle *handle = cls;
648 struct GNUNET_HashCode key;
649 struct GNUNET_JSONAPI_Document *json_obj;
650 struct GNUNET_JSONAPI_Resource *res;
651 struct GNUNET_CREDENTIAL_Credential *cred;
652 char *tmp;
653 char *entity_attr;
654 int i;
655 uint32_t credential_count;
656 uint32_t resource_count;
657 json_t *cred_json;
658 json_t *data_js;
659 json_error_t err;
660
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "Connecting...\n");
663 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
664 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
665 &do_error, handle);
666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
667 "Connected\n");
668 if (NULL == handle->credential)
669 {
670 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
671 "Connecting to CREDENTIAL failed\n");
672 GNUNET_SCHEDULER_add_now (&do_error, handle);
673 return;
674 }
675 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
676 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
677 &key);
678 if ( GNUNET_NO ==
679 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
680 &key) )
681 {
682 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
683 "Missing issuer attribute\n");
684 GNUNET_SCHEDULER_add_now (&do_error, handle);
685 return;
686 }
687 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
688 &key);
689 entity_attr = GNUNET_strdup (tmp);
690 tmp = strtok(entity_attr, ".");
691 if (NULL == tmp)
692 {
693 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
694 "Malformed issuer or attribute\n");
695 GNUNET_free (entity_attr);
696 GNUNET_SCHEDULER_add_now (&do_error, handle);
697 return;
698 }
699 if (GNUNET_OK !=
700 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
701 strlen (tmp),
702 &handle->issuer_key))
703 {
704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
705 "Malformed issuer key\n");
706 GNUNET_free (entity_attr);
707 GNUNET_SCHEDULER_add_now (&do_error, handle);
708 return;
709 }
710 tmp = strtok (NULL, "."); //Issuer attribute
711 if (NULL == tmp)
712 {
713 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
714 "Malformed attribute\n");
715 GNUNET_free (entity_attr);
716 GNUNET_SCHEDULER_add_now (&do_error, handle);
717 return;
718 }
719 handle->issuer_attr = GNUNET_strdup (tmp);
720 GNUNET_free (entity_attr);
721
722 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
723 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
724 &key);
725 if ( GNUNET_NO ==
726 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
727 &key) )
728 {
729 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
730 "Missing subject key\n");
731 GNUNET_free (entity_attr);
732 GNUNET_SCHEDULER_add_now (&do_error, handle);
733 return;
734 }
735 tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
736 &key);
737 if (NULL == tmp)
738 {
739 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
740 "Malformed subject\n");
741 GNUNET_free (entity_attr);
742 GNUNET_SCHEDULER_add_now (&do_error, handle);
743 return;
744 }
745 if (GNUNET_OK !=
746 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
747 strlen (tmp),
748 &handle->subject_key)) {
749 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
750 "Malformed subject key\n");
751 GNUNET_free (entity_attr);
752 GNUNET_SCHEDULER_add_now (&do_error, handle);
753 return;
754 }
755
756 if (0 >= handle->rest_handle->data_size)
757 {
758 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
759 "Missing credentials\n");
760 GNUNET_SCHEDULER_add_now (&do_error, handle);
761 return;
762 }
763
764 struct GNUNET_JSON_Specification docspec[] = {
765 GNUNET_JSON_spec_jsonapi_document (&json_obj),
766 GNUNET_JSON_spec_end()
767 };
768 char term_data[handle->rest_handle->data_size+1];
769 term_data[handle->rest_handle->data_size] = '\0';
770 credential_count = 0;
771 GNUNET_memcpy (term_data,
772 handle->rest_handle->data,
773 handle->rest_handle->data_size);
774 data_js = json_loads (term_data,
775 JSON_DECODE_ANY,
776 &err);
777 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
778 NULL, NULL));
779 json_decref (data_js);
780 if (NULL == json_obj)
781 {
782 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
783 "Unable to parse JSONAPI Object from %s\n",
784 term_data);
785 GNUNET_SCHEDULER_add_now (&do_error, handle);
786 return;
787 }
788
789 resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
790 GNUNET_assert (1 == resource_count);
791 res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
792 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
793 GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
794 {
795 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
796 "Resource not a credential!\n");
797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
798 "Unable to parse JSONAPI Object from %s\n",
799 term_data);
800 GNUNET_JSONAPI_document_delete (json_obj);
801 GNUNET_SCHEDULER_add_now (&do_error, handle);
802 return;
803 }
804 cred_json = GNUNET_JSONAPI_resource_read_attr (res,
805 GNUNET_REST_JSONAPI_CREDENTIAL);
806
807 GNUNET_assert (json_is_array (cred_json));
808
809 credential_count = json_array_size(cred_json);
810
811 struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
812 for (i=0;i<credential_count;i++)
813 {
814 cred = json_to_credential (json_array_get (cred_json, i));
815 if (NULL == cred)
816 {
817 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
818 "Unable to parse credential!\n");
819 continue;
820 }
821 GNUNET_memcpy (&credentials[i],
822 cred,
823 sizeof (struct GNUNET_CREDENTIAL_Credential));
824 credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
825 GNUNET_free (cred);
826 }
827 GNUNET_JSONAPI_document_delete(json_obj);
828 handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
829 &handle->issuer_key,
830 handle->issuer_attr,
831 &handle->subject_key,
832 credential_count,
833 credentials,
834 &handle_verify_response,
835 handle);
836 for (i=0;i<credential_count;i++)
837 GNUNET_free ((char*)credentials[i].issuer_attribute);
838
839}
840
841void
842send_cred_response (struct RequestHandle *handle,
843 struct GNUNET_CREDENTIAL_Credential *cred)
844{
845 struct MHD_Response *resp;
846 struct GNUNET_JSONAPI_Document *json_document;
847 struct GNUNET_JSONAPI_Resource *json_resource;
848 json_t *cred_obj;
849 char *result;
850 char *issuer;
851 char *subject;
852 char *signature;
853 char *id;
854
855 GNUNET_assert (NULL != cred);
856 issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
857 if (NULL == issuer)
858 {
859 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
860 "Subject malformed\n");
861 return;
862 }
863 GNUNET_asprintf (&id,
864 "%s.%s",
865 issuer,
866 (char*)&cred[1]);
867 subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
868 if (NULL == subject)
869 {
870 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
871 "Subject malformed\n");
872 return;
873 }
874 GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
875 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
876 &signature);
877 json_document = GNUNET_JSONAPI_document_new ();
878 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
879 id);
880 GNUNET_free (id);
881 cred_obj = json_object();
882 json_object_set_new (cred_obj, "issuer", json_string (issuer));
883 json_object_set_new (cred_obj, "subject", json_string (subject));
884 json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
885 json_object_set_new (cred_obj, "signature", json_string (signature));
886 GNUNET_JSONAPI_resource_add_attr (json_resource,
887 GNUNET_REST_JSONAPI_CREDENTIAL,
888 cred_obj);
889 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
890 GNUNET_JSONAPI_document_serialize (json_document, &result);
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
892 "Result %s\n",
893 result);
894 json_decref (cred_obj);
895 GNUNET_JSONAPI_document_delete (json_document);
896 resp = GNUNET_REST_create_response (result);
897 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
898 GNUNET_free (result);
899 GNUNET_free (signature);
900 GNUNET_free (issuer);
901 GNUNET_free (subject);
902 cleanup_handle (handle);
903}
904
905void
906get_cred_issuer_cb (void *cls,
907 struct GNUNET_IDENTITY_Ego *ego,
908 void **ctx,
909 const char *name)
910{
911 struct RequestHandle *handle = cls;
912 struct GNUNET_TIME_Absolute etime_abs;
913 struct GNUNET_TIME_Relative etime_rel;
914 const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
915 struct GNUNET_HashCode key;
916 struct GNUNET_CREDENTIAL_Credential *cred;
917 char* expiration_str;
918 char* tmp;
919
920 handle->id_op = NULL;
921
922 if (NULL == name)
923 {
924 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
925 "Issuer not configured!\n");
926 GNUNET_SCHEDULER_add_now (&do_error, handle);
927 return;
928 }
929
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 "Connecting to credential service...\n");
932 handle->credential = GNUNET_CREDENTIAL_connect (cfg);
933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
934 "Connected\n");
935 if (NULL == handle->credential)
936 {
937 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
938 "Connecting to CREDENTIAL failed\n");
939 GNUNET_SCHEDULER_add_now (&do_error, handle);
940 return;
941 }
942 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
943 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
944 &key);
945 if ( GNUNET_NO ==
946 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
947 &key) )
948 {
949 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
950 "Missing expiration\n");
951 GNUNET_SCHEDULER_add_now (&do_error, handle);
952 return;
953 }
954 expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
955 &key);
956 if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
957 &etime_rel))
958 {
959 etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
960 } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
961 &etime_abs))
962 {
963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
964 "Malformed expiration: %s\n", expiration_str);
965 GNUNET_SCHEDULER_add_now (&do_error, handle);
966 return;
967 }
968 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
969 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
970 &key);
971 if ( GNUNET_NO ==
972 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
973 &key) )
974 {
975 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
976 "Missing issuer attribute\n");
977 GNUNET_SCHEDULER_add_now (&do_error, handle);
978 return;
979 }
980 handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
981 (handle->rest_handle->url_param_map,
982 &key));
983 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
984 strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
985 &key);
986 if ( GNUNET_NO ==
987 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
988 &key) )
989 {
990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
991 "Missing subject\n");
992 GNUNET_SCHEDULER_add_now (&do_error, handle);
993 return;
994 }
995 tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
996 &key);
997 if (NULL == tmp)
998 {
999 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1000 "Malformed subject\n");
1001 GNUNET_SCHEDULER_add_now (&do_error, handle);
1002 return;
1003 }
1004 if (GNUNET_OK !=
1005 GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
1006 strlen (tmp),
1007 &handle->subject_key)) {
1008 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1009 "Malformed subject key\n");
1010 GNUNET_SCHEDULER_add_now (&do_error, handle);
1011 return;
1012 }
1013 issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
1014 cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
1015 &handle->subject_key,
1016 handle->issuer_attr,
1017 &etime_abs);
1018 if (NULL == cred)
1019 {
1020 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1021 "Failed to create credential\n");
1022 GNUNET_SCHEDULER_add_now (&do_error, handle);
1023 return;
1024 }
1025 send_cred_response (handle, cred);
1026}
1027
1028
1029static void
1030issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
1031 const char* url,
1032 void *cls)
1033{
1034 struct RequestHandle *handle = cls;
1035
1036 handle->identity = GNUNET_IDENTITY_connect (cfg,
1037 NULL,
1038 NULL);
1039 handle->id_op = GNUNET_IDENTITY_get(handle->identity,
1040 "credential-issuer",
1041 &get_cred_issuer_cb,
1042 handle);
1043 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1044 &do_error,
1045 handle);
1046}
1047
1048static void
1049options_cont (struct GNUNET_REST_RequestHandle *con_handle,
1050 const char* url,
1051 void *cls)
1052{
1053 struct MHD_Response *resp;
1054 struct RequestHandle *handle = cls;
1055
1056 //For GNS, independent of path return all options
1057 resp = GNUNET_REST_create_response (NULL);
1058 MHD_add_response_header (resp,
1059 "Access-Control-Allow-Methods",
1060 MHD_HTTP_METHOD_GET);
1061 handle->proc (handle->proc_cls,
1062 resp,
1063 MHD_HTTP_OK);
1064 cleanup_handle (handle);
1065}
1066
1067
1068static void
1069rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1070 GNUNET_REST_ResultProcessor proc,
1071 void *proc_cls)
1072{
1073 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1074 struct GNUNET_REST_RequestHandlerError err;
1075
1076 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1077 handle->proc_cls = proc_cls;
1078 handle->proc = proc;
1079 handle->rest_handle = conndata_handle;
1080
1081 static const struct GNUNET_REST_RequestHandler handlers[] = {
1082 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
1083 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
1084 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
1085 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
1086 GNUNET_REST_HANDLER_END
1087 };
1088
1089 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
1090 handlers,
1091 &err,
1092 handle))
1093 {
1094 handle->response_code = err.error_code;
1095 GNUNET_SCHEDULER_add_now (&do_error, handle);
1096 }
1097}
1098
1099
1100/**
1101 * Entry point for the plugin.
1102 *
1103 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
1104 * @return NULL on error, otherwise the plugin context
1105 */
1106void *
1107libgnunet_plugin_rest_credential_init (void *cls)
1108{
1109 static struct Plugin plugin;
1110 cfg = cls;
1111 struct GNUNET_REST_Plugin *api;
1112
1113 if (NULL != plugin.cfg)
1114 return NULL; /* can only initialize once! */
1115 memset (&plugin, 0, sizeof (struct Plugin));
1116 plugin.cfg = cfg;
1117 api = GNUNET_new (struct GNUNET_REST_Plugin);
1118 api->cls = &plugin;
1119 api->name = GNUNET_REST_API_NS_CREDENTIAL;
1120 api->process_request = &rest_credential_process_request;
1121 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1122 _("GNS REST API initialized\n"));
1123 return api;
1124}
1125
1126
1127/**
1128 * Exit point from the plugin.
1129 *
1130 * @param cls the plugin context (as returned by "init")
1131 * @return always NULL
1132 */
1133void *
1134libgnunet_plugin_rest_credential_done (void *cls)
1135{
1136 struct GNUNET_REST_Plugin *api = cls;
1137 struct Plugin *plugin = api->cls;
1138
1139 plugin->cfg = NULL;
1140 GNUNET_free (api);
1141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1142 "GNS REST plugin is finished\n");
1143 return NULL;
1144}
1145
1146/* end of plugin_rest_gns.c */
diff --git a/src/credential/test_credential_collect.sh b/src/credential/test_credential_collect.sh
new file mode 100755
index 000000000..6c713063f
--- /dev/null
+++ b/src/credential/test_credential_collect.sh
@@ -0,0 +1,47 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26TEST_ATTR2="test2"
27gnunet-arm -s -c test_credential_lookup.conf
28gnunet-identity -C testissuer -c test_credential_lookup.conf
29gnunet-identity -C testsubject -c test_credential_lookup.conf
30SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
31ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
32#TODO1 Get credential and store it with subject (3)
33CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
34$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
35CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c test_credential_lookup.conf`
36$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
37CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste -d, -s`
38echo $CREDS
39RES=$?
40gnunet-arm -e -c test_credential_lookup.conf
41
42if test $? != 0
43then
44 echo "Error collecting..."
45 exit 1
46fi
47
diff --git a/src/credential/test_credential_collect_rest.sh b/src/credential/test_credential_collect_rest.sh
new file mode 100755
index 000000000..0b31f85bc
--- /dev/null
+++ b/src/credential/test_credential_collect_rest.sh
@@ -0,0 +1,90 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60# (5) GNUnet issues Alice the credential "developer"
61CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
62
63# Alice stores the credential under "mygnunetcreds"
64gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
65
66#TODO2 Add -z swich like in gnunet-gns
67#RES_CRED=`gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY -c test_credential_lookup.conf`
68
69gnunet-arm -i rest -c test_credential_lookup.conf
70
71sleep 5
72
73curl -v "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"
74
75#TODO cleanup properly
76gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
77gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
78gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
79gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
80echo "Stopping arm..."
81gnunet-arm -e -c test_credential_lookup.conf
82echo "Done"
83if [ "$RES_CRED" != "Failed." ]
84then
85 echo -e "${RES_CRED}"
86 exit 0
87else
88 echo "FAIL: Failed to verify credential $RES_CRED."
89 exit 1
90fi
diff --git a/src/credential/test_credential_defaults.conf b/src/credential/test_credential_defaults.conf
new file mode 100644
index 000000000..d157ddd43
--- /dev/null
+++ b/src/credential/test_credential_defaults.conf
@@ -0,0 +1,24 @@
1@INLINE@ ../../contrib/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-credential-testing/
5
6[namestore-sqlite]
7FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
8
9[namecache-sqlite]
10FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
11
12[identity]
13# Directory where we store information about our egos
14EGODIR = $GNUNET_TEST_HOME/identity/egos/
15
16[dhtcache]
17DATABASE = heap
18
19[transport]
20PLUGINS = tcp
21
22[transport-tcp]
23BINDTO = 127.0.0.1
24
diff --git a/src/credential/test_credential_issue.sh b/src/credential/test_credential_issue.sh
new file mode 100755
index 000000000..158d91c5b
--- /dev/null
+++ b/src/credential/test_credential_issue.sh
@@ -0,0 +1,44 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C testissuer -c test_credential_lookup.conf
28gnunet-identity -C testsubject -c test_credential_lookup.conf
29SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
30ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
31#TODO1 Get credential and store it with subject (3)
32CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
33STATUS=$?
34
35if test $? != 0
36then
37 echo "Error issuing..."
38 exit 1
39fi
40#Try import
41$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
42RES=$?
43gnunet-arm -e -c test_credential_lookup.conf
44exit $RES
diff --git a/src/credential/test_credential_issue_rest.sh b/src/credential/test_credential_issue_rest.sh
new file mode 100755
index 000000000..15cd55083
--- /dev/null
+++ b/src/credential/test_credential_issue_rest.sh
@@ -0,0 +1,53 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-arm -i gns
28gnunet-arm -i credential
29gnunet-arm -i identity
30gnunet-arm -i rest -c test_credential_lookup.conf
31
32gnunet-arm -I -c test_credential_lookup.conf
33gnunet-identity -C testissuer -c test_credential_lookup.conf
34gnunet-identity -C testsubject -c test_credential_lookup.conf
35gnunet-identity -s credential-issuer -e testissuer
36SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
37ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
38#TODO1 Get credential and store it with subject (3)
39sleep 5
40curl "localhost:7776/credential/issue?subject_key=$SUBJECT_KEY&attribute=$TEST_ATTR&expiration=1d"
41#CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
42STATUS=$?
43
44if test $? != 0
45then
46 echo "Error issuing..."
47 exit 1
48fi
49#Try import
50#$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
51RES=$?
52gnunet-arm -e -c test_credential_lookup.conf
53exit $RES
diff --git a/src/credential/test_credential_lookup.conf b/src/credential/test_credential_lookup.conf
new file mode 100644
index 000000000..3684063b1
--- /dev/null
+++ b/src/credential/test_credential_lookup.conf
@@ -0,0 +1,28 @@
1@INLINE@ test_credential_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-credential-peer-1/
5
6[dht]
7AUTOSTART = YES
8
9[transport]
10PLUGINS =
11
12[credential]
13AUTOSTART = YES
14PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
15
16[rest]
17PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
18
19[gns]
20#PREFIX = valgrind --leak-check=full --track-origins=yes
21AUTOSTART = YES
22AUTO_IMPORT_PKEY = YES
23MAX_PARALLEL_BACKGROUND_QUERIES = 10
24DEFAULT_LOOKUP_TIMEOUT = 15 s
25RECORD_PUT_INTERVAL = 1 h
26ZONE_PUBLISH_TIME_WINDOW = 1 h
27DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
28
diff --git a/src/credential/test_credential_verify.sh b/src/credential/test_credential_verify.sh
new file mode 100755
index 000000000..d042bcfe6
--- /dev/null
+++ b/src/credential/test_credential_verify.sh
@@ -0,0 +1,81 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
61
62echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf
63#TODO2 Add -z swich like in gnunet-gns
64gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf
65
66
67#TODO cleanup properly
68gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
69gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
70gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
71gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
72gnunet-arm -e -c test_credential_lookup.conf
73
74if [ "$RES_CRED" != "Failed." ]
75then
76 echo -e "${RES_CRED}"
77 exit 0
78else
79 echo "FAIL: Failed to verify credential $RES_CRED."
80 exit 1
81fi
diff --git a/src/credential/test_credential_verify_and.sh b/src/credential/test_credential_verify_and.sh
new file mode 100755
index 000000000..9d5c1962e
--- /dev/null
+++ b/src/credential/test_credential_verify_and.sh
@@ -0,0 +1,81 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR,$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
52
53# (5) GNUnet issues Alice the credential "developer"
54CRED1=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
55# (5) GNUnet issues Alice the credential "user"
56CRED2=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED1" -e 5m -c test_credential_lookup.conf
59gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m -c test_credential_lookup.conf
60
61CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
62
63#TODO2 Add -z swich like in gnunet-gns
64RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf`
65
66
67#TODO cleanup properly
68gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
69gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
70gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
71gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
72gnunet-arm -e -c test_credential_lookup.conf
73
74if [ "$RES_CRED" != "Failed." ]
75then
76 echo -e "${RES_CRED}"
77 exit 0
78else
79 echo "FAIL: Failed to verify credential $RES_CRED."
80 exit 1
81fi
diff --git a/src/credential/test_credential_verify_rest.sh b/src/credential/test_credential_verify_rest.sh
new file mode 100755
index 000000000..6133ea25e
--- /dev/null
+++ b/src/credential/test_credential_verify_rest.sh
@@ -0,0 +1,87 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) Service.user -> GNU.project.member
19# (2) GNU.project -> GNUnet
20# (3) GNUnet.member -> GNUnet.developer
21# (4) GNUnet.member -> GNUnet.user
22# (5) GNUnet.developer -> Alice
23
24
25which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
26gnunet-arm -s -c test_credential_lookup.conf
27gnunet-identity -C service -c test_credential_lookup.conf
28gnunet-identity -C alice -c test_credential_lookup.conf
29gnunet-identity -C gnu -c test_credential_lookup.conf
30gnunet-identity -C gnunet -c test_credential_lookup.conf
31
32GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
33ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
34GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
35SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
36
37USER_ATTR="user"
38GNU_PROJECT_ATTR="project"
39MEMBER_ATTR="member"
40DEVELOPER_ATTR="developer"
41DEV_ATTR="developer"
42TEST_CREDENTIAL="mygnunetcreds"
43
44# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
45gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
46
47# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
48gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
49
50# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
51gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
52gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
53
54# (5) GNUnet issues Alice the credential "developer"
55CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
56
57# Alice stores the credential under "mygnunetcreds"
58gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
59
60#TODO2 Add -z swich like in gnunet-gns
61#RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
62
63gnunet-arm -i rest -c test_credential_lookup.conf
64
65sleep 5
66
67CREDS=`curl "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"`
68
69echo $CREDS
70
71curl -v "localhost:7776/credential/verify?attribute=$SERVICE_KEY.$USER_ATTR&subject_key=$ALICE_KEY" --data "$CREDS"
72
73#TODO cleanup properly
74gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
75gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
76gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
77gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
78gnunet-arm -e -c test_credential_lookup.conf
79
80if [ "$RES_CRED" != "Failed." ]
81then
82 echo -e "${RES_CRED}"
83 exit 0
84else
85 echo "FAIL: Failed to verify credential $RES_CRED."
86 exit 1
87fi
diff --git a/src/credential/test_credential_verify_simple.sh b/src/credential/test_credential_verify_simple.sh
new file mode 100755
index 000000000..c4fd8c7a3
--- /dev/null
+++ b/src/credential/test_credential_verify_simple.sh
@@ -0,0 +1,50 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
17
18# (3) Isser.user -> Subject
19
20
21which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
22gnunet-arm -s -c test_credential_lookup.conf
23gnunet-identity -C testissuer -c test_credential_lookup.conf
24gnunet-identity -C testsubject -c test_credential_lookup.conf
25
26TEST_ATTR="user"
27SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
28ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
29CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
30
31TEST_CREDENTIAL="t1"
32gnunet-namestore -p -z testsubject -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
33
34#TODO2 Add -z swich like in gnunet-gns
35#RES_CRED=`$DO_TIMEOUT gnunet-credential --verify --issuer=$ISSUER_KEY --attribute="$TEST_ATTR" --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
36RES_CRED=`gnunet-credential --verify --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
37
38#TODO cleanup properly
39gnunet-namestore -z testsubject -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
40gnunet-identity -D testsubject -c test_credential_lookup.conf
41gnunet-arm -e -c test_credential_lookup.conf
42echo $RES_CRED
43#TODO3 proper test
44if [ "$RES_CRED" == "Successful." ]
45then
46 exit 0
47else
48 echo "FAIL: Failed to verify credential."
49 exit 1
50fi
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 7196a1844..d9a5dd684 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -3802,7 +3802,7 @@ run (void *cls,
3802 if (GNUNET_YES != 3802 if (GNUNET_YES !=
3803 GNUNET_OS_check_helper_binary (binary, 3803 GNUNET_OS_check_helper_binary (binary,
3804 GNUNET_YES, 3804 GNUNET_YES,
3805 "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) //no nat, ipv4 only 3805 "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) //no nat, ipv4 only
3806 { 3806 {
3807 GNUNET_free (binary); 3807 GNUNET_free (binary);
3808 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3808 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index 26293f4df..84c4ae189 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -244,10 +244,7 @@ handle_result (void *cls,
244 return; 244 return;
245 proc = lr->lookup_proc; 245 proc = lr->lookup_proc;
246 proc_cls = lr->proc_cls; 246 proc_cls = lr->proc_cls;
247 GNUNET_CONTAINER_DLL_remove (handle->lookup_head, 247
248 handle->lookup_tail,
249 lr);
250 GNUNET_free (lr);
251 GNUNET_assert (GNUNET_OK == 248 GNUNET_assert (GNUNET_OK ==
252 GNUNET_GNSRECORD_records_deserialize (mlen, 249 GNUNET_GNSRECORD_records_deserialize (mlen,
253 (const char*) &lookup_msg[1], 250 (const char*) &lookup_msg[1],
@@ -256,6 +253,12 @@ handle_result (void *cls,
256 proc (proc_cls, 253 proc (proc_cls,
257 rd_count, 254 rd_count,
258 rd); 255 rd);
256 GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
257 handle->lookup_tail,
258 lr);
259 if (NULL != lr->env)
260 GNUNET_MQ_discard (lr->env);
261 GNUNET_free (lr);
259} 262}
260 263
261 264
diff --git a/src/gns/plugin_gnsrecord_gns.c b/src/gns/plugin_gnsrecord_gns.c
index 5d611e19e..6adad0f34 100644
--- a/src/gns/plugin_gnsrecord_gns.c
+++ b/src/gns/plugin_gnsrecord_gns.c
@@ -140,30 +140,6 @@ gns_value_to_string (void *cls,
140 GNUNET_free (ival); 140 GNUNET_free (ival);
141 return box_str; 141 return box_str;
142 } 142 }
143 case GNUNET_GNSRECORD_TYPE_REVERSE:
144 {
145 struct GNUNET_GNSRECORD_ReverseRecord rev;
146 char *rev_str;
147 char *pkey_str;
148
149 if (data_size < sizeof (struct GNUNET_GNSRECORD_ReverseRecord))
150 return NULL; /* malformed */
151
152 memcpy (&rev,
153 data,
154 sizeof (rev));
155 cdata = data;
156 pkey_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&rev.pkey);
157
158 GNUNET_asprintf (&rev_str,
159 "%s %s %"SCNu64,
160 &cdata[sizeof (rev)],
161 pkey_str,
162 rev.expiration.abs_value_us);
163 GNUNET_free (pkey_str);
164 return rev_str;
165
166 }
167 default: 143 default:
168 return NULL; 144 return NULL;
169 } 145 }
@@ -335,48 +311,6 @@ gns_string_to_value (void *cls,
335 GNUNET_free (bval); 311 GNUNET_free (bval);
336 return GNUNET_OK; 312 return GNUNET_OK;
337 } 313 }
338 case GNUNET_GNSRECORD_TYPE_REVERSE:
339 {
340 struct GNUNET_GNSRECORD_ReverseRecord *rev;
341 char known_by[253 + 1];
342 struct GNUNET_TIME_Absolute expiration;
343
344 /* TODO: From crypto_ecc.c
345 * Why is this not a constant???
346 */
347 size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
348 if (enclen % 5 > 0)
349 enclen += 5 - enclen % 5;
350 enclen /= 5; /* 260/5 = 52 */
351 char pkey_str[enclen + 1];
352
353 if (3 != SSCANF (s,
354 "%253s %52s %"SCNu64,
355 known_by,
356 pkey_str,
357 &expiration.abs_value_us))
358 {
359 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
360 _("Unable to parse REVERSE record string `%s'\n"),
361 s);
362 return GNUNET_SYSERR;
363 }
364 *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1;
365 *data = rev = GNUNET_malloc (*data_size);
366 if (GNUNET_OK !=
367 GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str,
368 strlen (pkey_str),
369 &rev->pkey))
370 {
371 GNUNET_free (rev);
372 return GNUNET_SYSERR;
373 }
374 rev->expiration = expiration;
375 GNUNET_memcpy (&rev[1],
376 known_by,
377 strlen (known_by));
378 return GNUNET_OK;
379 }
380 default: 314 default:
381 return GNUNET_SYSERR; 315 return GNUNET_SYSERR;
382 } 316 }
@@ -397,7 +331,6 @@ static struct {
397 { "VPN", GNUNET_GNSRECORD_TYPE_VPN }, 331 { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
398 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS }, 332 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
399 { "BOX", GNUNET_GNSRECORD_TYPE_BOX }, 333 { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
400 { "REVERSE", GNUNET_GNSRECORD_TYPE_REVERSE },
401 { NULL, UINT32_MAX } 334 { NULL, UINT32_MAX }
402}; 335};
403 336
diff --git a/src/identity-attribute/Makefile.am b/src/identity-attribute/Makefile.am
new file mode 100644
index 000000000..2c73a443e
--- /dev/null
+++ b/src/identity-attribute/Makefile.am
@@ -0,0 +1,44 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8libexecdir= $(pkglibdir)/libexec/
9
10if MINGW
11 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
12endif
13
14if USE_COVERAGE
15 AM_CFLAGS = --coverage -O0
16 XLIBS = -lgcov
17endif
18
19lib_LTLIBRARIES = \
20 libgnunetidentityattribute.la
21
22libgnunetidentityattribute_la_SOURCES = \
23 identity_attribute.c
24libgnunetidentityattribute_la_LIBADD = \
25 $(top_builddir)/src/util/libgnunetutil.la \
26 $(GN_LIBINTL)
27libgnunetidentityattribute_la_LDFLAGS = \
28 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
29 -version-info 0:0:0
30
31
32plugin_LTLIBRARIES = \
33 libgnunet_plugin_identity_attribute_gnuid.la
34
35
36libgnunet_plugin_identity_attribute_gnuid_la_SOURCES = \
37 plugin_identity_attribute_gnuid.c
38libgnunet_plugin_identity_attribute_gnuid_la_LIBADD = \
39 $(top_builddir)/src/util/libgnunetutil.la \
40 $(LTLIBINTL)
41libgnunet_plugin_identity_attribute_gnuid_la_LDFLAGS = \
42 $(GN_PLUGIN_LDFLAGS)
43
44
diff --git a/src/identity-attribute/identity_attribute.c b/src/identity-attribute/identity_attribute.c
new file mode 100644
index 000000000..cf50d058e
--- /dev/null
+++ b/src/identity-attribute/identity_attribute.c
@@ -0,0 +1,421 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21/**
22 * @file identity-attribute/identity_attribute.c
23 * @brief helper library to manage identity attributes
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "identity_attribute.h"
29#include "gnunet_identity_attribute_plugin.h"
30
31/**
32 * Handle for a plugin
33 */
34struct Plugin
35{
36 /**
37 * Name of the plugin
38 */
39 char *library_name;
40
41 /**
42 * Plugin API
43 */
44 struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
45};
46
47/**
48 * Plugins
49 */
50static struct Plugin **attr_plugins;
51
52/**
53 * Number of plugins
54 */
55static unsigned int num_plugins;
56
57/**
58 * Init canary
59 */
60static int initialized;
61
62/**
63 * Add a plugin
64 */
65static void
66add_plugin (void* cls,
67 const char *library_name,
68 void *lib_ret)
69{
70 struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = lib_ret;
71 struct Plugin *plugin;
72
73 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
74 "Loading attribute plugin `%s'\n",
75 library_name);
76 plugin = GNUNET_new (struct Plugin);
77 plugin->api = api;
78 plugin->library_name = GNUNET_strdup (library_name);
79 GNUNET_array_append (attr_plugins, num_plugins, plugin);
80}
81
82/**
83 * Load plugins
84 */
85static void
86init()
87{
88 if (GNUNET_YES == initialized)
89 return;
90 initialized = GNUNET_YES;
91 GNUNET_PLUGIN_load_all ("libgnunet_plugin_identity_attribute_", NULL,
92 &add_plugin, NULL);
93}
94
95/**
96 * Convert a type name to the corresponding number
97 *
98 * @param typename name to convert
99 * @return corresponding number, UINT32_MAX on error
100 */
101uint32_t
102GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename)
103{
104 unsigned int i;
105 struct Plugin *plugin;
106 uint32_t ret;
107
108 init ();
109 for (i = 0; i < num_plugins; i++)
110 {
111 plugin = attr_plugins[i];
112 if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
113 typename)))
114 return ret;
115 }
116 return UINT32_MAX;
117}
118
119/**
120 * Convert a type number to the corresponding type string
121 *
122 * @param type number of a type
123 * @return corresponding typestring, NULL on error
124 */
125const char*
126GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type)
127{
128 unsigned int i;
129 struct Plugin *plugin;
130 const char *ret;
131
132 init ();
133 for (i = 0; i < num_plugins; i++)
134 {
135 plugin = attr_plugins[i];
136 if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
137 type)))
138 return ret;
139 }
140 return NULL;
141}
142
143/**
144 * Convert human-readable version of a 'claim' of an attribute to the binary
145 * representation
146 *
147 * @param type type of the claim
148 * @param s human-readable string
149 * @param data set to value in binary encoding (will be allocated)
150 * @param data_size set to number of bytes in @a data
151 * @return #GNUNET_OK on success
152 */
153int
154GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
155 const char *s,
156 void **data,
157 size_t *data_size)
158{
159 unsigned int i;
160 struct Plugin *plugin;
161
162 init ();
163 for (i = 0; i < num_plugins; i++)
164 {
165 plugin = attr_plugins[i];
166 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
167 type,
168 s,
169 data,
170 data_size))
171 return GNUNET_OK;
172 }
173 return GNUNET_SYSERR;
174}
175
176/**
177 * Convert the 'claim' of an attribute to a string
178 *
179 * @param type the type of attribute
180 * @param data claim in binary encoding
181 * @param data_size number of bytes in @a data
182 * @return NULL on error, otherwise human-readable representation of the claim
183 */
184char *
185GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
186 const void* data,
187 size_t data_size)
188{
189 unsigned int i;
190 struct Plugin *plugin;
191 char *ret;
192
193 init();
194 for (i = 0; i < num_plugins; i++)
195 {
196 plugin = attr_plugins[i];
197 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
198 type,
199 data,
200 data_size)))
201 return ret;
202 }
203 return NULL;
204}
205
206/**
207 * Create a new attribute.
208 *
209 * @param attr_name the attribute name
210 * @param type the attribute type
211 * @param data the attribute value
212 * @param data_size the attribute value size
213 * @return the new attribute
214 */
215struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
216GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
217 uint32_t type,
218 const void* data,
219 size_t data_size)
220{
221 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
222 char *write_ptr;
223
224 attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) +
225 strlen (attr_name) + 1 +
226 data_size);
227 attr->type = type;
228 attr->data_size = data_size;
229 attr->version = 0;
230 write_ptr = (char*)&attr[1];
231 GNUNET_memcpy (write_ptr,
232 attr_name,
233 strlen (attr_name) + 1);
234 attr->name = write_ptr;
235 write_ptr += strlen (attr->name) + 1;
236 GNUNET_memcpy (write_ptr,
237 data,
238 data_size);
239 attr->data = write_ptr;
240 return attr;
241}
242
243size_t
244GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
245{
246 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
247 size_t len = 0;
248 for (le = attrs->list_head; NULL != le; le = le->next)
249 len += GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
250 return len;
251}
252
253size_t
254GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
255 char *result)
256{
257 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
258 size_t len;
259 size_t total_len;
260 char* write_ptr;
261
262 write_ptr = result;
263 total_len = 0;
264 for (le = attrs->list_head; NULL != le; le = le->next)
265 {
266 len = GNUNET_IDENTITY_ATTRIBUTE_serialize (le->claim,
267 write_ptr);
268 total_len += len;
269 write_ptr += len;
270 }
271 return total_len;
272}
273
274struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
275GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
276 size_t data_size)
277{
278 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
279 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
280 size_t attr_len;
281 const char* read_ptr;
282
283 if (data_size < sizeof (struct Attribute))
284 return NULL;
285
286 attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
287 read_ptr = data;
288 while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
289 {
290
291 le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
292 le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (read_ptr,
293 data_size - (read_ptr - data));
294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
295 "Deserialized attribute %s\n", le->claim->name);
296 GNUNET_CONTAINER_DLL_insert (attrs->list_head,
297 attrs->list_tail,
298 le);
299 attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
300 read_ptr += attr_len;
301 }
302 return attrs;
303}
304
305struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
306GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
307{
308 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
309 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *result_le;
310 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *result;
311 size_t len;
312
313 result = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
314 for (le = attrs->list_head; NULL != le; le = le->next)
315 {
316 result_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
317 len = sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) + le->claim->data_size;
318 result_le->claim = GNUNET_malloc (len);
319 GNUNET_memcpy (result_le->claim,
320 le->claim,
321 len);
322 result_le->claim->name = (const char*)&result_le->claim[1];
323 GNUNET_CONTAINER_DLL_insert (result->list_head,
324 result->list_tail,
325 result_le);
326 }
327 return result;
328}
329
330
331void
332GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
333{
334 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
335 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *tmp_le;
336
337 for (le = attrs->list_head; NULL != le;)
338 {
339 GNUNET_free (le->claim);
340 tmp_le = le;
341 le = le->next;
342 GNUNET_free (tmp_le);
343 }
344 GNUNET_free (attrs);
345
346}
347
348size_t
349GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
350{
351 return sizeof (struct Attribute)
352 + strlen (attr->name)
353 + attr->data_size;
354}
355
356size_t
357GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
358 char *result)
359{
360 size_t data_len_ser;
361 size_t name_len;
362 struct Attribute *attr_ser;
363 char* write_ptr;
364
365 attr_ser = (struct Attribute*)result;
366 attr_ser->attribute_type = htons (attr->type);
367 attr_ser->attribute_version = htonl (attr->version);
368 name_len = strlen (attr->name);
369 attr_ser->name_len = htons (name_len);
370 write_ptr = (char*)&attr_ser[1];
371 GNUNET_memcpy (write_ptr, attr->name, name_len);
372 write_ptr += name_len;
373 //TODO plugin-ize
374 //data_len_ser = plugin->serialize_attribute_value (attr,
375 // &attr_ser[1]);
376 data_len_ser = attr->data_size;
377 GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
378 attr_ser->data_size = htons (data_len_ser);
379
380 return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
381}
382
383struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
384GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
385 size_t data_size)
386{
387 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
388 struct Attribute *attr_ser;
389 size_t data_len;
390 size_t name_len;
391 char* write_ptr;
392
393 if (data_size < sizeof (struct Attribute))
394 return NULL;
395
396 attr_ser = (struct Attribute*)data;
397 data_len = ntohs (attr_ser->data_size);
398 name_len = ntohs (attr_ser->name_len);
399 attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim)
400 + data_len + name_len + 1);
401 attr->type = ntohs (attr_ser->attribute_type);
402 attr->version = ntohl (attr_ser->attribute_version);
403 attr->data_size = ntohs (attr_ser->data_size);
404
405 write_ptr = (char*)&attr[1];
406 GNUNET_memcpy (write_ptr,
407 &attr_ser[1],
408 name_len);
409 write_ptr[name_len] = '\0';
410 attr->name = write_ptr;
411
412 write_ptr += name_len + 1;
413 GNUNET_memcpy (write_ptr,
414 (char*)&attr_ser[1] + name_len,
415 attr->data_size);
416 attr->data = write_ptr;
417 return attr;
418
419}
420
421/* end of identity_attribute.c */
diff --git a/src/identity-attribute/identity_attribute.h b/src/identity-attribute/identity_attribute.h
new file mode 100644
index 000000000..8dfc17521
--- /dev/null
+++ b/src/identity-attribute/identity_attribute.h
@@ -0,0 +1,56 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file identity-attribute/identity_attribute.h
23 * @brief GNUnet Identity attributes
24 *
25 */
26#ifndef IDENTITY_ATTRIBUTE_H
27#define IDENTITY_ATTRIBUTE_H
28
29#include "gnunet_identity_provider_service.h"
30
31struct Attribute
32{
33 /**
34 * Attribute type
35 */
36 uint32_t attribute_type;
37
38 /**
39 * Attribute version
40 */
41 uint32_t attribute_version;
42
43 /**
44 * Name length
45 */
46 uint32_t name_len;
47
48 /**
49 * Data size
50 */
51 uint32_t data_size;
52
53 //followed by data_size Attribute value data
54};
55
56#endif
diff --git a/src/identity-attribute/plugin_identity_attribute_gnuid.c b/src/identity-attribute/plugin_identity_attribute_gnuid.c
new file mode 100644
index 000000000..006b45ea2
--- /dev/null
+++ b/src/identity-attribute/plugin_identity_attribute_gnuid.c
@@ -0,0 +1,184 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file identity-attribute/plugin_identity_attribute_gnuid.c
23 * @brief identity attribute plugin to provide the API for fundamental
24 * attribute types.
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_attribute_plugin.h"
31#include <inttypes.h>
32
33
34/**
35 * Convert the 'value' of an attribute to a string.
36 *
37 * @param cls closure, unused
38 * @param type type of the attribute
39 * @param data value in binary encoding
40 * @param data_size number of bytes in @a data
41 * @return NULL on error, otherwise human-readable representation of the value
42 */
43static char *
44gnuid_value_to_string (void *cls,
45 uint32_t type,
46 const void *data,
47 size_t data_size)
48{
49
50 switch (type)
51 {
52 case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
53 return GNUNET_strndup (data, data_size);
54 default:
55 return NULL;
56 }
57}
58
59
60/**
61 * Convert human-readable version of a 'value' of an attribute to the binary
62 * representation.
63 *
64 * @param cls closure, unused
65 * @param type type of the attribute
66 * @param s human-readable string
67 * @param data set to value in binary encoding (will be allocated)
68 * @param data_size set to number of bytes in @a data
69 * @return #GNUNET_OK on success
70 */
71static int
72gnuid_string_to_value (void *cls,
73 uint32_t type,
74 const char *s,
75 void **data,
76 size_t *data_size)
77{
78 if (NULL == s)
79 return GNUNET_SYSERR;
80 switch (type)
81 {
82
83 case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
84 *data = GNUNET_strdup (s);
85 *data_size = strlen (s);
86 return GNUNET_OK;
87 default:
88 return GNUNET_SYSERR;
89 }
90}
91
92
93/**
94 * Mapping of attribute type numbers to human-readable
95 * attribute type names.
96 */
97static struct {
98 const char *name;
99 uint32_t number;
100} gnuid_name_map[] = {
101 { "STRING", GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING },
102 { NULL, UINT32_MAX }
103};
104
105
106/**
107 * Convert a type name to the corresponding number.
108 *
109 * @param cls closure, unused
110 * @param gnuid_typename name to convert
111 * @return corresponding number, UINT32_MAX on error
112 */
113static uint32_t
114gnuid_typename_to_number (void *cls,
115 const char *gnuid_typename)
116{
117 unsigned int i;
118
119 i=0;
120 while ( (NULL != gnuid_name_map[i].name) &&
121 (0 != strcasecmp (gnuid_typename,
122 gnuid_name_map[i].name)) )
123 i++;
124 return gnuid_name_map[i].number;
125}
126
127
128/**
129 * Convert a type number (i.e. 1) to the corresponding type string
130 *
131 * @param cls closure, unused
132 * @param type number of a type to convert
133 * @return corresponding typestring, NULL on error
134 */
135static const char *
136gnuid_number_to_typename (void *cls,
137 uint32_t type)
138{
139 unsigned int i;
140
141 i=0;
142 while ( (NULL != gnuid_name_map[i].name) &&
143 (type != gnuid_name_map[i].number) )
144 i++;
145 return gnuid_name_map[i].name;
146}
147
148
149/**
150 * Entry point for the plugin.
151 *
152 * @param cls NULL
153 * @return the exported block API
154 */
155void *
156libgnunet_plugin_identity_attribute_gnuid_init (void *cls)
157{
158 struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
159
160 api = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions);
161 api->value_to_string = &gnuid_value_to_string;
162 api->string_to_value = &gnuid_string_to_value;
163 api->typename_to_number = &gnuid_typename_to_number;
164 api->number_to_typename = &gnuid_number_to_typename;
165 return api;
166}
167
168
169/**
170 * Exit point from the plugin.
171 *
172 * @param cls the return value from #libgnunet_plugin_block_test_init()
173 * @return NULL
174 */
175void *
176libgnunet_plugin_identity_attribute_gnuid_done (void *cls)
177{
178 struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = cls;
179
180 GNUNET_free (api);
181 return NULL;
182}
183
184/* end of plugin_identity_attribute_type_gnuid.c */
diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am
index 0d8752c4c..adf6af3b3 100644
--- a/src/identity-provider/Makefile.am
+++ b/src/identity-provider/Makefile.am
@@ -12,6 +12,15 @@ if USE_COVERAGE
12 XLIB = -lgcov 12 XLIB = -lgcov
13endif 13endif
14 14
15if HAVE_SQLITE
16SQLITE_PLUGIN = libgnunet_plugin_identity_provider_sqlite.la
17endif
18
19EXTRA_DIST = \
20 test_idp_defaults.conf \
21 test_idp.conf \
22 $(check_SCRIPTS)
23
15pkgcfgdir= $(pkgdatadir)/config.d/ 24pkgcfgdir= $(pkgdatadir)/config.d/
16 25
17libexecdir= $(pkglibdir)/libexec/ 26libexecdir= $(pkglibdir)/libexec/
@@ -22,29 +31,51 @@ pkgcfg_DATA = \
22lib_LTLIBRARIES = \ 31lib_LTLIBRARIES = \
23 libgnunetidentityprovider.la 32 libgnunetidentityprovider.la
24plugin_LTLIBRARIES = \ 33plugin_LTLIBRARIES = \
25 libgnunet_plugin_rest_identity_provider.la 34 libgnunet_plugin_rest_identity_provider.la \
35 libgnunet_plugin_gnsrecord_identity_provider.la \
36 $(SQLITE_PLUGIN)
26 37
27bin_PROGRAMS = \ 38bin_PROGRAMS = \
28 gnunet-identity-token 39 gnunet-idp
29 40
30libexec_PROGRAMS = \ 41libexec_PROGRAMS = \
31 gnunet-service-identity-provider 42 gnunet-service-identity-provider
32 43
33EXTRA_DIST = \ 44libgnunet_plugin_gnsrecord_identity_provider_la_SOURCES = \
34 $(pkgcfg_DATA) 45 plugin_gnsrecord_identity_provider.c
46libgnunet_plugin_gnsrecord_identity_provider_la_LIBADD = \
47 $(top_builddir)/src/util/libgnunetutil.la \
48 $(LTLIBINTL)
49libgnunet_plugin_gnsrecord_identity_provider_la_LDFLAGS = \
50 $(GN_PLUGIN_LDFLAGS)
51
52libgnunet_plugin_identity_provider_sqlite_la_SOURCES = \
53 plugin_identity_provider_sqlite.c
54libgnunet_plugin_identity_provider_sqlite_la_LIBADD = \
55 libgnunetidentityprovider.la \
56 $(top_builddir)/src/sq/libgnunetsq.la \
57 $(top_builddir)/src/statistics/libgnunetstatistics.la \
58 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
59 $(LTLIBINTL)
60libgnunet_plugin_identity_provider_sqlite_la_LDFLAGS = \
61 $(GN_PLUGIN_LDFLAGS)
62
63
35 64
36gnunet_service_identity_provider_SOURCES = \ 65gnunet_service_identity_provider_SOURCES = \
37 gnunet-service-identity-provider.c \ 66 gnunet-service-identity-provider.c
38 identity_token.c identity_token.h
39gnunet_service_identity_provider_LDADD = \ 67gnunet_service_identity_provider_LDADD = \
40 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 68 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
41 $(top_builddir)/src/util/libgnunetutil.la \ 69 $(top_builddir)/src/util/libgnunetutil.la \
42 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 70 $(top_builddir)/src/namestore/libgnunetnamestore.la \
43 $(top_builddir)/src/identity/libgnunetidentity.la \ 71 $(top_builddir)/src/identity/libgnunetidentity.la \
44 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 72 $(top_builddir)/src/statistics/libgnunetstatistics.la \
73 $(top_builddir)/src/abe/libgnunetabe.la \
74 $(top_builddir)/src/credential/libgnunetcredential.la \
75 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
76 libgnunetidentityprovider.la \
45 $(top_builddir)/src/gns/libgnunetgns.la \ 77 $(top_builddir)/src/gns/libgnunetgns.la \
46 $(GN_LIBINTL) \ 78 $(GN_LIBINTL)
47 -ljansson
48 79
49libgnunetidentityprovider_la_SOURCES = \ 80libgnunetidentityprovider_la_SOURCES = \
50 identity_provider_api.c \ 81 identity_provider_api.c \
@@ -57,22 +88,37 @@ libgnunetidentityprovider_la_LDFLAGS = \
57 -version-info 0:0:0 88 -version-info 0:0:0
58 89
59libgnunet_plugin_rest_identity_provider_la_SOURCES = \ 90libgnunet_plugin_rest_identity_provider_la_SOURCES = \
60 plugin_rest_identity_provider.c 91 plugin_rest_identity_provider.c \
92 jwt.c
61libgnunet_plugin_rest_identity_provider_la_LIBADD = \ 93libgnunet_plugin_rest_identity_provider_la_LIBADD = \
62 $(top_builddir)/src/identity/libgnunetidentity.la \ 94 $(top_builddir)/src/identity/libgnunetidentity.la \
63 libgnunetidentityprovider.la \ 95 libgnunetidentityprovider.la \
64 $(top_builddir)/src/rest/libgnunetrest.la \ 96 $(top_builddir)/src/rest/libgnunetrest.la \
65 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ 97 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
98 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
66 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 99 $(top_builddir)/src/namestore/libgnunetnamestore.la \
67 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ 100 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
68 $(LTLIBINTL) -ljansson -lmicrohttpd 101 $(LTLIBINTL) -ljansson -lmicrohttpd
69libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \ 102libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \
70 $(GN_PLUGIN_LDFLAGS) 103 $(GN_PLUGIN_LDFLAGS)
71 104
72 105gnunet_idp_SOURCES = \
73gnunet_identity_token_SOURCES = \ 106 gnunet-idp.c
74 gnunet-identity-token.c 107gnunet_idp_LDADD = \
75gnunet_identity_token_LDADD = \
76 $(top_builddir)/src/util/libgnunetutil.la \ 108 $(top_builddir)/src/util/libgnunetutil.la \
77 -ljansson -lmicrohttpd \ 109 $(top_builddir)/src/namestore/libgnunetnamestore.la \
110 libgnunetidentityprovider.la \
111 $(top_builddir)/src/identity/libgnunetidentity.la \
112 $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
78 $(GN_LIBINTL) 113 $(GN_LIBINTL)
114
115check_SCRIPTS = \
116 test_idp_attribute.sh \
117 test_idp_issue.sh \
118 test_idp_consume.sh \
119 test_idp_revoke.sh
120
121if ENABLE_TEST_RUN
122 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
123 TESTS = $(check_SCRIPTS)
124endif
diff --git a/src/identity-provider/gnunet-identity-token.c b/src/identity-provider/gnunet-identity-token.c
deleted file mode 100644
index 30b63bfc4..000000000
--- a/src/identity-provider/gnunet-identity-token.c
+++ /dev/null
@@ -1,179 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file src/identity-provider/gnunet-service-identity-provider.c
23 * @brief Identity Token Service
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include <jansson.h>
30#include "gnunet_signatures.h"
31
32/**
33 * The token
34 */
35static char* token;
36
37/**
38 * Weather to print the token
39 */
40static int print_token;
41
42static void
43run (void *cls,
44 char *const *args,
45 const char *cfgfile,
46 const struct GNUNET_CONFIGURATION_Handle *c)
47{
48 char *payload;
49 char *header;
50 //Get token parts
51 const char *header_b64;
52 const char *payload_b64;
53 const char *signature_b32;
54 const char *keystring;
55 char *data;
56 json_t *payload_json;
57 json_t *keystring_json;
58 json_error_t error;
59 struct GNUNET_CRYPTO_EcdsaPublicKey key;
60 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
61 struct GNUNET_CRYPTO_EcdsaSignature sig;
62
63 if (NULL == token)
64 {
65 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
66 _("Option `-t' is required\n"));
67 return;
68 }
69 header_b64 = strtok (token, ".");
70 payload_b64 = strtok (NULL, ".");
71 signature_b32 = strtok (NULL, ".");
72 if ( (NULL == header_b64) ||
73 (NULL == payload_b64) ||
74 (NULL == signature_b32) )
75 {
76 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
77 _("Token `%s' is malformed\n"),
78 token);
79 GNUNET_free (token);
80 token = NULL;
81 return;
82 }
83
84 //Decode payload
85 GNUNET_STRINGS_base64_decode (payload_b64,
86 strlen (payload_b64),
87 &payload);
88 //Decode header
89 GNUNET_STRINGS_base64_decode (header_b64,
90 strlen (header_b64),
91 &header);
92
93
94 GNUNET_asprintf(&data,
95 "%s,%s",
96 header_b64,
97 payload_b64);
98 char *val = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
99 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose*)val;
100 purpose->size = htonl(sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
101 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
102 GNUNET_memcpy (&purpose[1], data, strlen(data));
103 GNUNET_free (data);
104 GNUNET_free (token);
105 token = NULL;
106
107 if (print_token)
108 printf ("Token:\nHeader:\t\t%s\nPayload:\t%s\n",
109 header,
110 payload);
111 GNUNET_free (header);
112
113 payload_json = json_loads (payload, 0, &error);
114 GNUNET_free (payload);
115
116 if ((NULL == payload_json) || (! json_is_object (payload_json)) )
117 {
118 GNUNET_free (val);
119 return;
120 }
121 keystring_json = json_object_get (payload_json, "iss");
122 if (! json_is_string (keystring_json))
123 {
124 GNUNET_free (val);
125 return;
126 }
127 keystring = json_string_value (keystring_json);
128 if (GNUNET_OK !=
129 GNUNET_CRYPTO_ecdsa_public_key_from_string (keystring,
130 strlen (keystring),
131 &key))
132 {
133 GNUNET_free (val);
134 return;
135 }
136 GNUNET_STRINGS_string_to_data (signature_b32,
137 strlen (signature_b32),
138 &sig,
139 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
140
141 if (print_token)
142 printf ("Signature:\t%s\n",
143 keystring);
144
145 if (GNUNET_OK !=
146 GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN,
147 purpose,
148 &sig,
149 &key))
150 printf("Signature not OK!\n");
151 else
152 printf("Signature OK!\n");
153 GNUNET_free (val);
154 return;
155}
156
157
158int
159main(int argc, char *const argv[])
160{
161 struct GNUNET_GETOPT_CommandLineOption options[] = {
162
163 GNUNET_GETOPT_option_string ('t',
164 "token",
165 NULL,
166 gettext_noop ("GNUid token"),
167 &token),
168
169 GNUNET_GETOPT_option_flag ('p',
170 "print",
171 gettext_noop ("Print token contents"),
172 &print_token),
173
174 GNUNET_GETOPT_OPTION_END
175 };
176 return GNUNET_PROGRAM_run (argc, argv, "ct",
177 "ct", options,
178 &run, NULL);
179}
diff --git a/src/identity-provider/gnunet-idp.c b/src/identity-provider/gnunet-idp.c
new file mode 100644
index 000000000..62f07842b
--- /dev/null
+++ b/src/identity-provider/gnunet-idp.c
@@ -0,0 +1,439 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file src/identity-provider/gnunet-idp.c
23 * @brief Identity Provider utility
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_identity_provider_service.h"
31#include "gnunet_identity_service.h"
32#include "gnunet_signatures.h"
33
34/**
35 * return value
36 */
37static int ret;
38
39/**
40 * List attribute flag
41 */
42static int list;
43
44/**
45 * Relying party
46 */
47static char* rp;
48
49/**
50 * The attribute
51 */
52static char* attr_name;
53
54/**
55 * Attribute value
56 */
57static char* attr_value;
58
59/**
60 * Attributes to issue
61 */
62static char* issue_attrs;
63
64/**
65 * Ticket to consume
66 */
67static char* consume_ticket;
68
69/**
70 * Attribute type
71 */
72static char* type_str;
73
74/**
75 * Ticket to revoke
76 */
77static char* revoke_ticket;
78
79/**
80 * Ego name
81 */
82static char* ego_name;
83
84/**
85 * Identity handle
86 */
87static struct GNUNET_IDENTITY_Handle *identity_handle;
88
89/**
90 * IdP handle
91 */
92static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle;
93
94/**
95 * IdP operation
96 */
97static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
98
99/**
100 * Attribute iterator
101 */
102static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator;
103
104/**
105 * Master ABE key
106 */
107static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
108
109/**
110 * ego private key
111 */
112static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
113
114/**
115 * rp public key
116 */
117static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
118
119/**
120 * Ticket to consume
121 */
122static struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
123
124/**
125 * Attribute list
126 */
127static struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list;
128
129static void
130do_cleanup(void *cls)
131{
132 if (NULL != attr_iterator)
133 GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator);
134 if (NULL != idp_handle)
135 GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle);
136 if (NULL != identity_handle)
137 GNUNET_IDENTITY_disconnect (identity_handle);
138 if (NULL != abe_key)
139 GNUNET_free (abe_key);
140 if (NULL != attr_list)
141 GNUNET_free (attr_list);
142}
143
144static void
145ticket_issue_cb (void* cls,
146 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
147{
148 char* ticket_str;
149 if (NULL != ticket) {
150 ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
151 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
152 printf("%s\n",
153 ticket_str);
154 GNUNET_free (ticket_str);
155 }
156 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
157}
158
159static void
160store_attr_cont (void *cls,
161 int32_t success,
162 const char*emsg)
163{
164 if (GNUNET_SYSERR == success) {
165 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
166 "%s\n", emsg);
167 }
168 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
169}
170
171static void
172process_attrs (void *cls,
173 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
174 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
175{
176 char *value_str;
177 if (NULL == identity)
178 {
179 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
180 return;
181 }
182 if (NULL == attr)
183 {
184 ret = 1;
185 return;
186 }
187 value_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
188 attr->data,
189 attr->data_size);
190 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
191 "%s: %s\n", attr->name, value_str);
192}
193
194
195static void
196iter_error (void *cls)
197{
198 attr_iterator = NULL;
199 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200 "Failed to iterate over attributes\n");
201 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
202}
203
204static void
205process_rvk (void *cls, int success, const char* msg)
206{
207 if (GNUNET_OK != success)
208 {
209 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
210 "Revocation failed.\n");
211 ret = 1;
212 }
213 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
214}
215
216static void
217iter_finished (void *cls)
218{
219 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
220 char *data;
221 size_t data_size;
222 int type;
223
224 attr_iterator = NULL;
225 if (list)
226 {
227 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
228 return;
229 }
230
231 if (issue_attrs)
232 {
233 idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (idp_handle,
234 pkey,
235 &rp_key,
236 attr_list,
237 &ticket_issue_cb,
238 NULL);
239 return;
240 }
241 if (consume_ticket)
242 {
243 idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (idp_handle,
244 pkey,
245 &ticket,
246 &process_attrs,
247 NULL);
248 return;
249 }
250 if (revoke_ticket)
251 {
252 idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle,
253 pkey,
254 &ticket,
255 &process_rvk,
256 NULL);
257 return;
258 }
259 if (NULL == type_str)
260 type = GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING;
261 else
262 type = GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (type_str);
263
264 GNUNET_assert (GNUNET_SYSERR != GNUNET_IDENTITY_ATTRIBUTE_string_to_value (type,
265 attr_value,
266 (void**)&data,
267 &data_size));
268 claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
269 type,
270 data,
271 data_size);
272 idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
273 pkey,
274 claim,
275 &store_attr_cont,
276 NULL);
277
278
279}
280
281static void
282iter_cb (void *cls,
283 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
284 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
285{
286 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
287 char *attrs_tmp;
288 char *attr_str;
289
290 if (issue_attrs)
291 {
292 attrs_tmp = GNUNET_strdup (issue_attrs);
293 attr_str = strtok (attrs_tmp, ",");
294 while (NULL != attr_str) {
295 if (0 != strcmp (attr_str, attr->name)) {
296 attr_str = strtok (NULL, ",");
297 continue;
298 }
299 le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
300 le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name,
301 attr->type,
302 attr->data,
303 attr->data_size);
304 GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
305 attr_list->list_tail,
306 le);
307 break;
308 }
309 GNUNET_free (attrs_tmp);
310 } else if (list) {
311 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
312 "%s: %s\n", attr->name, (char*)attr->data);
313 }
314 GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
315}
316
317static void
318ego_cb (void *cls,
319 struct GNUNET_IDENTITY_Ego *ego,
320 void **ctx,
321 const char *name)
322{
323 if (NULL == name)
324 return;
325 if (0 != strcmp (name, ego_name))
326 return;
327 pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
328
329 if (NULL != rp)
330 GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
331 strlen (rp),
332 &rp_key);
333 if (NULL != consume_ticket)
334 GNUNET_STRINGS_string_to_data (consume_ticket,
335 strlen (consume_ticket),
336 &ticket,
337 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
338 if (NULL != revoke_ticket)
339 GNUNET_STRINGS_string_to_data (revoke_ticket,
340 strlen (revoke_ticket),
341 &ticket,
342 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
343
344
345 attr_list = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
346
347 attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
348 pkey,
349 &iter_error,
350 NULL,
351 &iter_cb,
352 NULL,
353 &iter_finished,
354 NULL);
355
356
357}
358
359static void
360run (void *cls,
361 char *const *args,
362 const char *cfgfile,
363 const struct GNUNET_CONFIGURATION_Handle *c)
364{
365 ret = 0;
366 if (NULL == ego_name)
367 {
368 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
369 _("Ego is required\n"));
370 return;
371 }
372
373 idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
374 //Get Ego
375 identity_handle = GNUNET_IDENTITY_connect (c,
376 &ego_cb,
377 NULL);
378
379
380}
381
382
383int
384main(int argc, char *const argv[])
385{
386 struct GNUNET_GETOPT_CommandLineOption options[] = {
387
388 GNUNET_GETOPT_option_string ('a',
389 "add",
390 NULL,
391 gettext_noop ("Add attribute"),
392 &attr_name),
393
394 GNUNET_GETOPT_option_string ('V',
395 "value",
396 NULL,
397 gettext_noop ("Attribute value"),
398 &attr_value),
399 GNUNET_GETOPT_option_string ('e',
400 "ego",
401 NULL,
402 gettext_noop ("Ego"),
403 &ego_name),
404 GNUNET_GETOPT_option_string ('r',
405 "rp",
406 NULL,
407 gettext_noop ("Audience (relying party)"),
408 &rp),
409 GNUNET_GETOPT_option_flag ('D',
410 "dump",
411 gettext_noop ("List attributes for Ego"),
412 &list),
413 GNUNET_GETOPT_option_string ('i',
414 "issue",
415 NULL,
416 gettext_noop ("Issue a ticket"),
417 &issue_attrs),
418 GNUNET_GETOPT_option_string ('C',
419 "consume",
420 NULL,
421 gettext_noop ("Consume a ticket"),
422 &consume_ticket),
423 GNUNET_GETOPT_option_string ('R',
424 "revoke",
425 NULL,
426 gettext_noop ("Revoke a ticket"),
427 &revoke_ticket),
428 GNUNET_GETOPT_option_string ('t',
429 "type",
430 NULL,
431 gettext_noop ("Type of attribute"),
432 &type_str),
433 GNUNET_GETOPT_OPTION_END
434 };
435 GNUNET_PROGRAM_run (argc, argv, "ct",
436 "ct", options,
437 &run, NULL);
438 return ret;
439}
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c
index 53fd02c9f..4e1de36cd 100644
--- a/src/identity-provider/gnunet-service-identity-provider.c
+++ b/src/identity-provider/gnunet-service-identity-provider.c
@@ -30,12 +30,14 @@
30#include "gnunet_identity_service.h" 30#include "gnunet_identity_service.h"
31#include "gnunet_gnsrecord_lib.h" 31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_namestore_service.h" 32#include "gnunet_namestore_service.h"
33#include "gnunet_abe_lib.h"
34#include "gnunet_credential_service.h"
33#include "gnunet_statistics_service.h" 35#include "gnunet_statistics_service.h"
34#include "gnunet_gns_service.h" 36#include "gnunet_gns_service.h"
37#include "gnunet_identity_provider_plugin.h"
38#include "gnunet_identity_attribute_lib.h"
35#include "gnunet_signatures.h" 39#include "gnunet_signatures.h"
36#include "identity_provider.h" 40#include "identity_provider.h"
37#include "identity_token.h"
38#include <inttypes.h>
39 41
40/** 42/**
41 * First pass state 43 * First pass state
@@ -58,24 +60,19 @@
58#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS 60#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
59 61
60/** 62/**
61 * Service state (to detect initial update pass) 63 * Identity handle
62 */
63static int state;
64
65/**
66 * Head of ego entry DLL
67 */ 64 */
68static struct EgoEntry *ego_head; 65static struct GNUNET_IDENTITY_Handle *identity_handle;
69 66
70/** 67/**
71 * Tail of ego entry DLL 68 * Database handle
72 */ 69 */
73static struct EgoEntry *ego_tail; 70static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
74 71
75/** 72/**
76 * Identity handle 73 * Name of DB plugin
77 */ 74 */
78static struct GNUNET_IDENTITY_Handle *identity_handle; 75static char *db_lib_name;
79 76
80/** 77/**
81 * Token expiration interval 78 * Token expiration interval
@@ -93,6 +90,16 @@ static struct GNUNET_NAMESTORE_Handle *ns_handle;
93static struct GNUNET_GNS_Handle *gns_handle; 90static struct GNUNET_GNS_Handle *gns_handle;
94 91
95/** 92/**
93 * Credential handle
94 */
95static struct GNUNET_CREDENTIAL_Handle *credential_handle;
96
97/**
98 * Stats handle
99 */
100static struct GNUNET_STATISTICS_Handle *stats_handle;
101
102/**
96 * Namestore qe 103 * Namestore qe
97 */ 104 */
98static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 105static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
@@ -112,11 +119,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task;
112 */ 119 */
113static struct GNUNET_SCHEDULER_Task *update_task; 120static struct GNUNET_SCHEDULER_Task *update_task;
114 121
115/**
116 * Timeout for next update pass
117 */
118static struct GNUNET_TIME_Relative min_rel_exp;
119
120 122
121/** 123/**
122 * Currently processed token 124 * Currently processed token
@@ -134,43 +136,260 @@ static char* label;
134static char* scopes; 136static char* scopes;
135 137
136/** 138/**
137 * Expiration for processed token 139 * Handle to the statistics service.
138 */ 140 */
139static uint64_t rd_exp; 141static struct GNUNET_STATISTICS_Handle *stats;
140 142
141/** 143/**
142 * ECDHE Privkey for processed token metadata 144 * Our configuration.
143 */ 145 */
144static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey; 146static const struct GNUNET_CONFIGURATION_Handle *cfg;
145 147
146/** 148/**
147 * Handle to the statistics service. 149 * An idp client
148 */ 150 */
149static struct GNUNET_STATISTICS_Handle *stats; 151struct IdpClient;
150 152
151/** 153/**
152 * Our configuration. 154 * A ticket iteration operation.
153 */ 155 */
154static const struct GNUNET_CONFIGURATION_Handle *cfg; 156struct TicketIteration
157{
158 /**
159 * DLL
160 */
161 struct TicketIteration *next;
162
163 /**
164 * DLL
165 */
166 struct TicketIteration *prev;
167
168 /**
169 * Client which intiated this zone iteration
170 */
171 struct IdpClient *client;
155 172
173 /**
174 * Key of the identity we are iterating over.
175 */
176 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
156 177
157struct ExchangeHandle 178 /**
179 * Identity is audience
180 */
181 uint32_t is_audience;
182
183 /**
184 * The operation id fot the iteration in the response for the client
185 */
186 uint32_t r_id;
187
188 /**
189 * Offset of the iteration used to address next result of the
190 * iteration in the store
191 *
192 * Initialy set to 0 in handle_iteration_start
193 * Incremented with by every call to handle_iteration_next
194 */
195 uint32_t offset;
196
197};
198
199
200
201/**
202 * Callback after an ABE bootstrap
203 *
204 * @param cls closure
205 * @param abe_key the ABE key that exists or was created
206 */
207typedef void
208(*AbeBootstrapResult) (void *cls,
209 struct GNUNET_ABE_AbeMasterKey *abe_key);
210
211
212struct AbeBootstrapHandle
158{ 213{
214 /**
215 * Function to call when finished
216 */
217 AbeBootstrapResult proc;
159 218
160 /** 219 /**
161 * Client connection 220 * Callback closure
221 */
222 char *proc_cls;
223
224 /**
225 * Key of the zone we are iterating over.
226 */
227 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
228
229 /**
230 * Namestore Queue Entry
231 */
232 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
233
234 /**
235 * The issuer egos ABE master key
236 */
237 struct GNUNET_ABE_AbeMasterKey *abe_key;
238};
239
240/**
241 * An attribute iteration operation.
242 */
243struct AttributeIterator
244{
245 /**
246 * Next element in the DLL
247 */
248 struct AttributeIterator *next;
249
250 /**
251 * Previous element in the DLL
252 */
253 struct AttributeIterator *prev;
254
255 /**
256 * IDP client which intiated this zone iteration
257 */
258 struct IdpClient *client;
259
260 /**
261 * Key of the zone we are iterating over.
262 */
263 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
264
265 /**
266 * The issuer egos ABE master key
267 */
268 struct GNUNET_ABE_AbeMasterKey *abe_key;
269
270 /**
271 * Namestore iterator
272 */
273 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
274
275 /**
276 * The operation id fot the zone iteration in the response for the client
277 */
278 uint32_t request_id;
279
280};
281
282
283
284/**
285 * An idp client
286 */
287struct IdpClient
288{
289
290 /**
291 * The client
162 */ 292 */
163 struct GNUNET_SERVICE_Client *client; 293 struct GNUNET_SERVICE_Client *client;
164 294
165 /** 295 /**
166 * Ticket 296 * Message queue for transmission to @e client
297 */
298 struct GNUNET_MQ_Handle *mq;
299
300 /**
301 * Head of the DLL of
302 * Attribute iteration operations in
303 * progress initiated by this client
304 */
305 struct AttributeIterator *op_head;
306
307 /**
308 * Tail of the DLL of
309 * Attribute iteration operations
310 * in progress initiated by this client
311 */
312 struct AttributeIterator *op_tail;
313
314 /**
315 * Head of DLL of ticket iteration ops
316 */
317 struct TicketIteration *ticket_iter_head;
318
319 /**
320 * Tail of DLL of ticket iteration ops
321 */
322 struct TicketIteration *ticket_iter_tail;
323
324
325 /**
326 * Head of DLL of ticket revocation ops
327 */
328 struct TicketRevocationHandle *revocation_list_head;
329
330 /**
331 * Tail of DLL of ticket revocation ops
332 */
333 struct TicketRevocationHandle *revocation_list_tail;
334};
335
336
337
338struct AttributeStoreHandle
339{
340
341 /**
342 * Client connection
343 */
344 struct IdpClient *client;
345
346 /**
347 * Identity
348 */
349 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
350
351 /**
352 * Identity pubkey
353 */
354 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
355
356 /**
357 * The issuer egos ABE master key
358 */
359 struct GNUNET_ABE_AbeMasterKey *abe_key;
360
361 /**
362 * QueueEntry
363 */
364 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
365
366 /**
367 * The attribute to store
368 */
369 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
370
371 /**
372 * request id
373 */
374 uint32_t r_id;
375};
376
377
378/* Prototype */
379struct ParallelLookup;
380
381struct ConsumeTicketHandle
382{
383
384 /**
385 * Client connection
167 */ 386 */
168 struct TokenTicket *ticket; 387 struct IdpClient *client;
169 388
170 /** 389 /**
171 * Token returned 390 * Ticket
172 */ 391 */
173 struct IdentityToken *token; 392 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
174 393
175 /** 394 /**
176 * LookupRequest 395 * LookupRequest
@@ -180,86 +399,173 @@ struct ExchangeHandle
180 /** 399 /**
181 * Audience Key 400 * Audience Key
182 */ 401 */
183 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey; 402 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
184 403
185 /** 404 /**
186 * Label to return 405 * Audience Key
187 */ 406 */
188 char *label; 407 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
189 408
190 /** 409 /**
410 * Lookup DLL
411 */
412 struct ParallelLookup *parallel_lookups_head;
413
414 /**
415 * Lookup DLL
416 */
417 struct ParallelLookup *parallel_lookups_tail;
418
419 /**
420 * Kill task
421 */
422 struct GNUNET_SCHEDULER_Task *kill_task;
423
424 /**
425 * The ABE key
426 */
427 struct GNUNET_ABE_AbeKey *key;
428
429 /**
430 * Attributes
431 */
432 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
433
434 /**
435 * Lookup time
436 */
437 struct GNUNET_TIME_Absolute lookup_start_time;
438
439 /**
191 * request id 440 * request id
192 */ 441 */
193 uint32_t r_id; 442 uint32_t r_id;
194}; 443};
195 444
196struct IssueHandle 445/**
446 * Handle for a parallel GNS lookup job
447 */
448struct ParallelLookup
197{ 449{
450 /* DLL */
451 struct ParallelLookup *next;
452
453 /* DLL */
454 struct ParallelLookup *prev;
455
456 /* The GNS request */
457 struct GNUNET_GNS_LookupRequest *lookup_request;
458
459 /* The handle the return to */
460 struct ConsumeTicketHandle *handle;
461
462 /**
463 * Lookup time
464 */
465 struct GNUNET_TIME_Absolute lookup_start_time;
466
467 /* The label to look up */
468 char *label;
469};
470
471/**
472 * Ticket revocation request handle
473 */
474struct TicketRevocationHandle
475{
476 /**
477 * DLL
478 */
479 struct TicketRevocationHandle *next;
480
481 /**
482 * DLL
483 */
484 struct TicketRevocationHandle *prev;
198 485
199 /** 486 /**
200 * Client connection 487 * Client connection
201 */ 488 */
202 struct GNUNET_SERVICE_Client *client; 489 struct IdpClient *client;
490
491 /**
492 * Attributes to reissue
493 */
494 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
495
496 /**
497 * Attributes to revoke
498 */
499 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs;
203 500
204 /** 501 /**
205 * Issuer Key 502 * Issuer Key
206 */ 503 */
207 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key; 504 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
208 505
209 /** 506 /**
210 * Issue pubkey 507 * Ticket to issue
211 */ 508 */
212 struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey; 509 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
213 510
214 /** 511 /**
215 * Audience Key 512 * QueueEntry
216 */ 513 */
217 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 514 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
218 515
219 /** 516 /**
220 * Expiration 517 * Namestore iterator
221 */ 518 */
222 struct GNUNET_TIME_Absolute expiration; 519 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
223 520
224 /** 521 /**
225 * Scopes 522 * The ABE master key
226 */ 523 */
227 char *scopes; 524 struct GNUNET_ABE_AbeMasterKey *abe_key;
228 525
229 /** 526 /**
230 * nonce 527 * Offset
231 */ 528 */
232 uint64_t nonce; 529 uint32_t offset;
233 530
234 /** 531 /**
235 * NS iterator 532 * request id
236 */ 533 */
237 struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 534 uint32_t r_id;
535};
536
537
538
539/**
540 * Ticket issue request handle
541 */
542struct TicketIssueHandle
543{
238 544
239 /** 545 /**
240 * Attribute map 546 * Client connection
241 */ 547 */
242 struct GNUNET_CONTAINER_MultiHashMap *attr_map; 548 struct IdpClient *client;
243 549
244 /** 550 /**
245 * Token 551 * Attributes to issue
246 */ 552 */
247 struct IdentityToken *token; 553 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
248 554
249 /** 555 /**
250 * Ticket 556 * Issuer Key
251 */ 557 */
252 struct TokenTicket *ticket; 558 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
253 559
254 /** 560 /**
255 * QueueEntry 561 * Ticket to issue
256 */ 562 */
257 struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 563 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
258 564
259 /** 565 /**
260 * The label the token is stored under 566 * QueueEntry
261 */ 567 */
262 char *label; 568 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
263 569
264 /** 570 /**
265 * request id 571 * request id
@@ -267,6 +573,7 @@ struct IssueHandle
267 uint32_t r_id; 573 uint32_t r_id;
268}; 574};
269 575
576
270/** 577/**
271 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format 578 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
272 * 579 *
@@ -293,1303 +600,1774 @@ struct EgoEntry
293 */ 600 */
294 struct GNUNET_CONTAINER_MultiHashMap *attr_map; 601 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
295 602
296 /**
297 * Attributes are old and should be updated if GNUNET_YES
298 */
299 int attributes_dirty;
300}; 603};
301 604
302/** 605/**
303 * Continuation for token store call 606 * Cleanup task
607 */
608static void
609cleanup()
610{
611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
612 "Cleaning up\n");
613 if (NULL != stats)
614 {
615 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
616 stats = NULL;
617 }
618 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
619 TKT_database));
620 GNUNET_free (db_lib_name);
621 db_lib_name = NULL;
622 if (NULL != timeout_task)
623 GNUNET_SCHEDULER_cancel (timeout_task);
624 if (NULL != update_task)
625 GNUNET_SCHEDULER_cancel (update_task);
626 if (NULL != identity_handle)
627 GNUNET_IDENTITY_disconnect (identity_handle);
628 if (NULL != gns_handle)
629 GNUNET_GNS_disconnect (gns_handle);
630 if (NULL != credential_handle)
631 GNUNET_CREDENTIAL_disconnect (credential_handle);
632 if (NULL != ns_it)
633 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
634 if (NULL != ns_qe)
635 GNUNET_NAMESTORE_cancel (ns_qe);
636 if (NULL != ns_handle)
637 GNUNET_NAMESTORE_disconnect (ns_handle);
638 if (NULL != stats_handle)
639 GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO);
640 GNUNET_free_non_null (token);
641 GNUNET_free_non_null (label);
642
643}
644
645/**
646 * Shutdown task
304 * 647 *
305 * @param cls NULL 648 * @param cls NULL
306 * @param success error code
307 * @param emsg error message
308 */ 649 */
309static void 650static void
310store_token_cont (void *cls, 651do_shutdown (void *cls)
311 int32_t success, 652{
312 const char *emsg) 653 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
654 "Shutting down...\n");
655 cleanup();
656}
657
658/**
659 * Finished storing newly bootstrapped ABE key
660 */
661static void
662bootstrap_store_cont (void *cls,
663 int32_t success,
664 const char *emsg)
313{ 665{
314 ns_qe = NULL; 666 struct AbeBootstrapHandle *abh = cls;
315 if (GNUNET_SYSERR == success) 667 if (GNUNET_SYSERR == success)
316 { 668 {
317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 669 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
318 "Failed to update token: %s\n", 670 "Failed to bootstrap ABE master %s\n",
319 emsg); 671 emsg);
672 abh->proc (abh->proc_cls, NULL);
673 GNUNET_free (abh->abe_key);
674 GNUNET_free (abh);
320 return; 675 return;
321 } 676 }
322 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 677 abh->proc (abh->proc_cls, abh->abe_key);
678 GNUNET_free (abh);
323} 679}
324 680
325
326/** 681/**
327 * This function updates the old token with new attributes, 682 * Generates and stores a new ABE key
328 * removes deleted attributes and expiration times.
329 *
330 * @param cls the ego entry
331 */ 683 */
332static void 684static void
333handle_token_update (void *cls) 685bootstrap_store_task (void *cls)
334{ 686{
335 char *token_metadata; 687 struct AbeBootstrapHandle *abh = cls;
336 char *write_ptr; 688 struct GNUNET_GNSRECORD_Data rd[1];
337 char *enc_token_str; 689 char *key;
338 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 690
339 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 691 rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
340 struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey; 692 (void**)&key);
341 struct EgoEntry *ego_entry = cls; 693 rd[0].data = key;
342 struct GNUNET_GNSRECORD_Data token_record[2]; 694 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
343 struct GNUNET_HashCode key_hash; 695 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
344 struct GNUNET_TIME_Relative token_rel_exp; 696 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
345 struct GNUNET_TIME_Relative token_ttl; 697 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
346 struct GNUNET_TIME_Absolute token_exp; 698 &abh->identity,
347 struct GNUNET_TIME_Absolute token_nbf; 699 "+",
348 struct GNUNET_TIME_Absolute new_exp; 700 1,
349 struct GNUNET_TIME_Absolute new_iat; 701 rd,
350 struct GNUNET_TIME_Absolute new_nbf; 702 &bootstrap_store_cont,
351 struct IdentityToken *new_token; 703 abh);
352 struct TokenAttr *cur_value; 704 GNUNET_free (key);
353 struct TokenAttr *attr; 705}
354 size_t token_metadata_len;
355
356 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
357 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
358 &pub_key);
359
360 //Note: We need the token expiration time here. Not the record expiration
361 //time.
362 //There are two types of tokens: Token that expire on GNS level with
363 //an absolute expiration time. Those are basically tokens that will
364 //be automatically revoked on (record)expiration.
365 //Tokens stored with relative expiration times will expire on the token level (token expiration)
366 //but this service will reissue new tokens that can be retrieved from GNS
367 //automatically.
368
369 for (attr = token->attr_head; NULL != attr; attr = attr->next)
370 {
371 if (0 == strcmp (attr->name, "exp"))
372 {
373 GNUNET_assert (1 == sscanf (attr->val_head->value,
374 "%"SCNu64,
375 &token_exp.abs_value_us));
376 } else if (0 == strcmp (attr->name, "nbf")) {
377 GNUNET_assert (1 == sscanf (attr->val_head->value,
378 "%"SCNu64,
379 &token_nbf.abs_value_us));
380 }
381 }
382 token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp);
383
384 token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp);
385 if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us)
386 {
387 //This token is not yet expired! Save and skip
388 if (min_rel_exp.rel_value_us > token_ttl.rel_value_us)
389 {
390 min_rel_exp = token_ttl;
391 }
392 GNUNET_free (token);
393 token = NULL;
394 GNUNET_free (label);
395 label = NULL;
396 GNUNET_free (scopes);
397 scopes = NULL;
398 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
399 return;
400 }
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
402 "Token is expired. Create a new one\n");
403 new_token = token_create (&pub_key,
404 &token->aud_key);
405 new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
406 new_nbf = GNUNET_TIME_absolute_get ();
407 new_iat = new_nbf;
408 for (attr = token->attr_head; NULL != attr; attr = attr->next)
409 {
410 if (0 == strcmp (attr->name, "exp"))
411 {
412 token_add_attr_int (new_token, attr->name, new_exp.abs_value_us);
413 }
414 else if (0 == strcmp (attr->name, "nbf"))
415 {
416 token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us);
417 }
418 else if (0 == strcmp (attr->name, "iat"))
419 {
420 token_add_attr_int (new_token, attr->name, new_iat.abs_value_us);
421 }
422 else if ((0 == strcmp (attr->name, "iss"))
423 || (0 == strcmp (attr->name, "aud")))
424 {
425 //Omit
426 }
427 else if (0 == strcmp (attr->name, "sub"))
428 {
429 token_add_attr (new_token,
430 attr->name,
431 attr->val_head->value);
432 }
433 else
434 {
435 GNUNET_CRYPTO_hash (attr->name,
436 strlen (attr->name),
437 &key_hash);
438 //Check if attr still exists. omit of not
439 if (GNUNET_NO !=
440 GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
441 &key_hash))
442 {
443 cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
444 &key_hash);
445 GNUNET_assert (NULL != cur_value);
446 GNUNET_CONTAINER_DLL_insert (new_token->attr_head,
447 new_token->attr_tail,
448 cur_value);
449 }
450 }
451 }
452 706
453 // reassemble and set 707/**
454 GNUNET_assert (token_serialize (new_token, 708 * Error checking for ABE master
455 priv_key, 709 */
456 &new_ecdhe_privkey, 710static void
457 &enc_token_str)); 711bootstrap_abe_error (void *cls)
458 712{
459 token_record[0].data = enc_token_str; 713 struct AbeBootstrapHandle *abh = cls;
460 token_record[0].data_size = strlen (enc_token_str) + 1; 714 GNUNET_free (abh);
461 token_record[0].expiration_time = rd_exp; //Old expiration time 715 abh->proc (abh->proc_cls, NULL);
462 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; 716 GNUNET_free (abh);
463 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
464
465 //Meta
466 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
467 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
468 + strlen (scopes) + 1; //With 0-Terminator
469 token_metadata = GNUNET_malloc (token_metadata_len);
470 write_ptr = token_metadata;
471 GNUNET_memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
472 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
473 GNUNET_memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
474 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
475 GNUNET_memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
476
477 token_record[1].data = token_metadata;
478 token_record[1].data_size = token_metadata_len;
479 token_record[1].expiration_time = rd_exp;
480 token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
481 token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
482
483 ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
484 priv_key,
485 label,
486 2,
487 token_record,
488 &store_token_cont,
489 ego_entry);
490 token_destroy (new_token);
491 token_destroy (token);
492 GNUNET_free (new_ecdhe_privkey);
493 GNUNET_free (enc_token_str);
494 token = NULL;
495 GNUNET_free (label);
496 label = NULL;
497 GNUNET_free (scopes);
498 scopes = NULL;
499} 717}
500 718
501 719
720/**
721 * Handle ABE lookup in namestore
722 */
502static void 723static void
503update_identities(void *cls); 724bootstrap_abe_result (void *cls,
725 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
726 const char *label,
727 unsigned int rd_count,
728 const struct GNUNET_GNSRECORD_Data *rd)
729{
730 struct AbeBootstrapHandle *abh = cls;
731 struct GNUNET_ABE_AbeMasterKey *abe_key;
732
733 for (uint32_t i=0;i<rd_count;i++) {
734 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
735 continue;
736 abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
737 rd[i].data_size);
738 abh->proc (abh->proc_cls, abe_key);
739 GNUNET_free (abh);
740 return;
741 }
504 742
743 //No ABE master found, bootstrapping...
744 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
745 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
746}
505 747
506/** 748/**
507 * 749 * Bootstrap ABE master if it does not yet exists.
508 * Cleanup attr_map 750 * Will call the AbeBootstrapResult processor when done.
509 * 751 * will always recreate the ABE key of GNUNET_YES == recreate
510 * @param cls NULL
511 * @param key the key
512 * @param value the json_t attribute value
513 * @return #GNUNET_YES
514 */ 752 */
515static int 753static void
516clear_ego_attrs (void *cls, 754bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
517 const struct GNUNET_HashCode *key, 755 AbeBootstrapResult proc,
518 void *value) 756 void* cls,
519{ 757 int recreate)
520 struct TokenAttr *attr = value; 758{
521 struct TokenAttrValue *val; 759 struct AbeBootstrapHandle *abh;
522 struct TokenAttrValue *tmp_val; 760
523 for (val = attr->val_head; NULL != val;) 761 abh = GNUNET_new (struct AbeBootstrapHandle);
762 abh->proc = proc;
763 abh->proc_cls = cls;
764 abh->identity = *identity;
765 if (GNUNET_YES == recreate)
524 { 766 {
525 tmp_val = val->next; 767 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
526 GNUNET_CONTAINER_DLL_remove (attr->val_head, 768 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
527 attr->val_tail, 769 } else {
528 val); 770 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
529 GNUNET_free (val->value); 771 identity,
530 GNUNET_free (val); 772 "+",
531 val = tmp_val; 773 &bootstrap_abe_error,
774 abh,
775 &bootstrap_abe_result,
776 abh);
532 } 777 }
533 GNUNET_free (attr->name);
534 GNUNET_free (attr);
535
536 return GNUNET_YES;
537} 778}
538 779
539 780
540static void
541token_collect_error_cb (void *cls)
542{
543 struct EgoEntry *ego_entry = cls;
544 781
545 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 782static int
546 ">>> Updating Ego failed!\n"); 783create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
547 //Clear attribute map for ego 784 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
548 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, 785 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
549 &clear_ego_attrs, 786{
550 ego_entry); 787 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
551 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); 788
552 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 789 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
553 ego_entry->next); 790 &new_key_hash_str);
791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
792 static const char ctx_key[] = "gnuid-aes-ctx-key";
793 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
794 new_key_hash, sizeof (struct GNUNET_HashCode),
795 ctx_key, strlen (ctx_key),
796 NULL, 0);
797 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
798 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
799 new_key_hash, sizeof (struct GNUNET_HashCode),
800 ctx_iv, strlen (ctx_iv),
801 NULL, 0);
802 return GNUNET_OK;
803}
554 804
805static void
806cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
807{
808 if (NULL != handle->attrs)
809 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
810 if (NULL != handle->ns_qe)
811 GNUNET_NAMESTORE_cancel (handle->ns_qe);
812 GNUNET_free (handle);
555} 813}
556 814
557 815
558static void 816static void
559token_collect_finished_cb (void *cls) 817send_ticket_result (struct IdpClient *client,
818 uint32_t r_id,
819 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
820 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
560{ 821{
561 struct EgoEntry *ego_entry = cls; 822 struct TicketResultMessage *irm;
823 struct GNUNET_MQ_Envelope *env;
824 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
562 825
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 826 /* store ticket in DB */
564 ">>> Updating Ego finished\n"); 827 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
565 //Clear attribute map for ego 828 ticket,
566 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, 829 attrs))
567 &clear_ego_attrs, 830 {
568 ego_entry); 831 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
569 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); 832 "Unable to store ticket after issue\n");
570 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 833 GNUNET_break (0);
571 ego_entry->next); 834 }
572}
573 835
836 env = GNUNET_MQ_msg_extra (irm,
837 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
838 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
839 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
840 *ticket_buf = *ticket;
841 irm->id = htonl (r_id);
842 GNUNET_MQ_send (client->mq,
843 env);
844}
574 845
575/**
576 *
577 * Update all ID_TOKEN records for an identity and store them
578 *
579 * @param cls the identity entry
580 * @param zone the identity
581 * @param lbl the name of the record
582 * @param rd_count number of records
583 * @param rd record data
584 */
585static void 846static void
586token_collect (void *cls, 847store_ticket_issue_cont (void *cls,
587 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 848 int32_t success,
588 const char *lbl, 849 const char *emsg)
589 unsigned int rd_count, 850{
590 const struct GNUNET_GNSRECORD_Data *rd) 851 struct TicketIssueHandle *handle = cls;
591{ 852
592 struct EgoEntry *ego_entry = cls; 853 handle->ns_qe = NULL;
593 const struct GNUNET_GNSRECORD_Data *token_record; 854 if (GNUNET_SYSERR == success)
594 const struct GNUNET_GNSRECORD_Data *token_metadata_record;
595 struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
596 struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key;
597
598 //There should be only a single record for a token under a label
599 if (2 != rd_count)
600 { 855 {
601 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 856 cleanup_ticket_issue_handle (handle);
857 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
858 "Unknown Error\n");
859 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
602 return; 860 return;
603 } 861 }
862 send_ticket_result (handle->client,
863 handle->r_id,
864 &handle->ticket,
865 handle->attrs);
866 cleanup_ticket_issue_handle (handle);
867}
604 868
605 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 869
606 { 870
607 token_metadata_record = &rd[0]; 871int
608 token_record = &rd[1]; 872serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
873 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
874 const struct GNUNET_ABE_AbeKey *rp_key,
875 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
876 char **result)
877{
878 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
879 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
880 char *enc_keyinfo;
881 char *serialized_key;
882 char *buf;
883 char *write_ptr;
884 char attrs_str_len;
885 ssize_t size;
886
887 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
888 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
889 struct GNUNET_HashCode new_key_hash;
890 ssize_t enc_size;
891
892 size = GNUNET_ABE_cpabe_serialize_key (rp_key,
893 (void**)&serialized_key);
894 attrs_str_len = 0;
895 for (le = attrs->list_head; NULL != le; le = le->next) {
896 attrs_str_len += strlen (le->claim->name) + 1;
609 } 897 }
610 else 898 buf = GNUNET_malloc (attrs_str_len + size);
611 { 899 write_ptr = buf;
612 token_record = &rd[0]; 900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
613 token_metadata_record = &rd[1]; 901 "Writing attributes\n");
902 for (le = attrs->list_head; NULL != le; le = le->next) {
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904 "%s\n", le->claim->name);
905
906
907 GNUNET_memcpy (write_ptr,
908 le->claim->name,
909 strlen (le->claim->name));
910 write_ptr[strlen (le->claim->name)] = ',';
911 write_ptr += strlen (le->claim->name) + 1;
614 } 912 }
615 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 913 write_ptr--;
616 { 914 write_ptr[0] = '\0'; //replace last , with a 0-terminator
617 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 915 write_ptr++;
618 return; 916 GNUNET_memcpy (write_ptr,
917 serialized_key,
918 size);
919 GNUNET_free (serialized_key);
920 // ECDH keypair E = eG
921 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
922 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
923 &ecdh_pubkey);
924 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
925 // Derived key K = H(eB)
926 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
927 &ticket->audience,
928 &new_key_hash));
929 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
930 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
931 size + attrs_str_len,
932 &skey, &iv,
933 enc_keyinfo);
934 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
935 enc_size);
936 GNUNET_memcpy (*result,
937 &ecdh_pubkey,
938 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
939 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
940 enc_keyinfo,
941 enc_size);
942 GNUNET_free (enc_keyinfo);
943 GNUNET_free (buf);
944 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
945}
946
947
948
949static void
950issue_ticket_after_abe_bootstrap (void *cls,
951 struct GNUNET_ABE_AbeMasterKey *abe_key)
952{
953 struct TicketIssueHandle *ih = cls;
954 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
955 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
956 struct GNUNET_GNSRECORD_Data code_record[1];
957 struct GNUNET_ABE_AbeKey *rp_key;
958 char *code_record_data;
959 char **attrs;
960 char *label;
961 char *policy;
962 int attrs_len;
963 uint32_t i;
964 size_t code_record_len;
965
966 //Create new ABE key for RP
967 attrs_len = 0;
968 for (le = ih->attrs->list_head; NULL != le; le = le->next)
969 attrs_len++;
970 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
971 i = 0;
972 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
973 GNUNET_asprintf (&policy, "%s_%lu",
974 le->claim->name,
975 le->claim->version);
976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
977 "Adding attribute to key: %s\n",
978 policy);
979 attrs[i] = policy;
980 i++;
619 } 981 }
620 if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN) 982 attrs[i] = NULL;
983 rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
984 attrs);
985
986 //TODO review this wireformat
987 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
988 ih->attrs,
989 rp_key,
990 &ecdhe_privkey,
991 &code_record_data);
992 code_record[0].data = code_record_data;
993 code_record[0].data_size = code_record_len;
994 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
995 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
996 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
997
998 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
999 sizeof (uint64_t));
1000 //Publish record
1001 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1002 &ih->identity,
1003 label,
1004 1,
1005 code_record,
1006 &store_ticket_issue_cont,
1007 ih);
1008 //for (; i > 0; i--)
1009 // GNUNET_free (attrs[i-1]);
1010 GNUNET_free (ecdhe_privkey);
1011 GNUNET_free (label);
1012 GNUNET_free (attrs);
1013 GNUNET_free (code_record_data);
1014 GNUNET_ABE_cpabe_delete_key (rp_key,
1015 GNUNET_YES);
1016 GNUNET_ABE_cpabe_delete_master_key (abe_key);
1017}
1018
1019
1020static int
1021check_issue_ticket_message(void *cls,
1022 const struct IssueTicketMessage *im)
1023{
1024 uint16_t size;
1025
1026 size = ntohs (im->header.size);
1027 if (size <= sizeof (struct IssueTicketMessage))
621 { 1028 {
622 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1029 GNUNET_break (0);
623 return; 1030 return GNUNET_SYSERR;
624 } 1031 }
1032 return GNUNET_OK;
1033}
625 1034
626 //Get metadata and decrypt token
627 priv_key = (struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data;
628 ecdhe_privkey = *priv_key;
629 aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&priv_key[1];
630 scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
631 1035
632 token_parse2 (token_record->data, 1036static void
633 &ecdhe_privkey, 1037handle_issue_ticket_message (void *cls,
634 aud_key, 1038 const struct IssueTicketMessage *im)
635 &token); 1039{
1040 struct TicketIssueHandle *ih;
1041 struct IdpClient *idp = cls;
1042 size_t attrs_len;
1043
1044 ih = GNUNET_new (struct TicketIssueHandle);
1045 attrs_len = ntohs (im->attr_len);
1046 ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
1047 ih->r_id = ntohl (im->id);
1048 ih->client = idp;
1049 ih->identity = im->identity;
1050 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1051 &ih->ticket.identity);
1052 ih->ticket.audience = im->rp;
1053 ih->ticket.rnd =
1054 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1055 UINT64_MAX);
1056 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1057 GNUNET_SERVICE_client_continue (idp->client);
636 1058
637 label = GNUNET_strdup (lbl); 1059}
638 rd_exp = token_record->expiration_time;
639 1060
640 GNUNET_SCHEDULER_add_now (&handle_token_update, 1061/**********************************************************
641 ego_entry); 1062 * Revocation
1063 **********************************************************/
1064
1065/**
1066 * Cleanup revoke handle
1067 *
1068 * @param rh the ticket revocation handle
1069 */
1070static void
1071cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
1072{
1073 if (NULL != rh->attrs)
1074 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->attrs);
1075 if (NULL != rh->rvk_attrs)
1076 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->rvk_attrs);
1077 if (NULL != rh->abe_key)
1078 GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
1079 if (NULL != rh->ns_qe)
1080 GNUNET_NAMESTORE_cancel (rh->ns_qe);
1081 if (NULL != rh->ns_it)
1082 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
1083 GNUNET_free (rh);
642} 1084}
643 1085
644 1086
1087/**
1088 * Send revocation result
1089 *
1090 * @param rh ticket revocation handle
1091 * @param success GNUNET_OK if successful result
1092 */
645static void 1093static void
646attribute_collect_error_cb (void *cls) 1094send_revocation_finished (struct TicketRevocationHandle *rh,
1095 uint32_t success)
647{ 1096{
648 struct EgoEntry *ego_entry = cls; 1097 struct GNUNET_MQ_Envelope *env;
1098 struct RevokeTicketResultMessage *trm;
649 1099
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1100 env = GNUNET_MQ_msg (trm,
651 ">>> Updating Attributes failed!\n"); 1101 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
652 ego_entry->attributes_dirty = GNUNET_NO; 1102 trm->id = htonl (rh->r_id);
653 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1103 trm->success = htonl (success);
654 ego_entry); 1104 GNUNET_MQ_send (rh->client->mq,
1105 env);
1106 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1107 rh->client->revocation_list_tail,
1108 rh);
655} 1109}
656 1110
657 1111
1112/**
1113 * Process ticket from database
1114 *
1115 * @param cls struct TicketIterationProcResult
1116 * @param ticket the ticket
1117 * @param attrs the attributes
1118 */
1119static void
1120ticket_reissue_proc (void *cls,
1121 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1122 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
1123
658static void 1124static void
659attribute_collect_finished_cb (void *cls) 1125revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1126
1127
1128static void reissue_next (void *cls)
660{ 1129{
661 struct EgoEntry *ego_entry = cls; 1130 struct TicketRevocationHandle *rh = cls;
1131 revocation_reissue_tickets (rh);
1132}
662 1133
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1134
664 ">>> Updating Attributes finished\n"); 1135static void
665 ego_entry->attributes_dirty = GNUNET_NO; 1136reissue_ticket_cont (void *cls,
666 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1137 int32_t success,
667 ego_entry); 1138 const char *emsg)
1139{
1140 struct TicketRevocationHandle *rh = cls;
1141
1142 rh->ns_qe = NULL;
1143 if (GNUNET_SYSERR == success)
1144 {
1145 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1146 "Unknown Error\n");
1147 send_revocation_finished (rh, GNUNET_SYSERR);
1148 cleanup_revoke_ticket_handle (rh);
1149 return;
1150 }
1151 rh->offset++;
1152 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
668} 1153}
669 1154
670 1155
671/** 1156/**
1157 * Process ticket from database
672 * 1158 *
673 * Collect all ID_ATTR records for an identity and store them 1159 * @param cls struct TicketIterationProcResult
674 * 1160 * @param ticket the ticket
675 * @param cls the identity entry 1161 * @param attrs the attributes
676 * @param zone the identity
677 * @param lbl the name of the record
678 * @param rd_count number of records
679 * @param rd record data
680 *
681 */ 1162 */
682static void 1163static void
683attribute_collect (void *cls, 1164ticket_reissue_proc (void *cls,
684 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1165 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
685 const char *lbl, 1166 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
686 unsigned int rd_count, 1167{
687 const struct GNUNET_GNSRECORD_Data *rd) 1168 struct TicketRevocationHandle *rh = cls;
688{ 1169 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
689 struct EgoEntry *ego_entry = cls; 1170 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover;
690 struct GNUNET_HashCode key; 1171 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
691 struct TokenAttr *attr; 1172 struct GNUNET_GNSRECORD_Data code_record[1];
692 struct TokenAttrValue *val; 1173 struct GNUNET_ABE_AbeKey *rp_key;
693 char *val_str; 1174 char *code_record_data;
694 int i; 1175 char **attr_arr;
695 1176 char *label;
696 if (0 == rd_count) 1177 char *policy;
1178 int attrs_len;
1179 uint32_t i;
1180 int reissue_ticket;
1181 size_t code_record_len;
1182
1183
1184 if (NULL == ticket)
697 { 1185 {
698 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "Iteration done\n");
699 return; 1188 return;
700 } 1189 }
701 GNUNET_CRYPTO_hash (lbl, 1190
702 strlen (lbl), 1191 if (0 == memcmp (&ticket->audience,
703 &key); 1192 &rh->ticket.audience,
704 if (1 == rd_count) 1193 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
705 { 1194 {
706 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 { 1196 "Do not reissue for this identity.!\n");
708 val_str = GNUNET_GNSRECORD_value_to_string (rd->record_type,
709 rd->data,
710 rd->data_size);
711 attr = GNUNET_malloc (sizeof (struct TokenAttr));
712 attr->name = GNUNET_strdup (lbl);
713 val = GNUNET_malloc (sizeof (struct TokenAttrValue));
714 val->value = val_str;
715 GNUNET_CONTAINER_DLL_insert (attr->val_head,
716 attr->val_tail,
717 val);
718 GNUNET_assert (GNUNET_OK ==
719 GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
720 &key,
721 attr,
722 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
723 }
724 1197
725 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1198 rh->offset++;
1199 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
726 return; 1200 return;
727 } 1201 }
728 1202
729 attr = GNUNET_malloc (sizeof (struct TokenAttr)); 1203 /*
730 attr->name = GNUNET_strdup (lbl); 1204 * Check if any attribute of this ticket intersects with a rollover attribute
731 for (i = 0; i < rd_count; i++) 1205 */
1206 reissue_ticket = GNUNET_NO;
1207 for (le = attrs->list_head; NULL != le; le = le->next)
732 { 1208 {
733 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1209 for (le_rollover = rh->rvk_attrs->list_head;
1210 NULL != le_rollover;
1211 le_rollover = le_rollover->next)
734 { 1212 {
735 val_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, 1213 if (0 == strcmp (le_rollover->claim->name,
736 rd[i].data, 1214 le->claim->name))
737 rd[i].data_size); 1215 {
738 val = GNUNET_malloc (sizeof (struct TokenAttrValue)); 1216 reissue_ticket = GNUNET_YES;
739 val->value = val_str; 1217 le->claim->version = le_rollover->claim->version;
740 GNUNET_CONTAINER_DLL_insert (attr->val_head, 1218 }
741 attr->val_tail,
742 val);
743 } 1219 }
744 } 1220 }
745 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
746 &key,
747 attr,
748 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
749 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
750}
751
752/**
753 *
754 * Update identity information for ego. If attribute map is
755 * dirty, first update the attributes.
756 *
757 * @param cls the ego to update
758 */
759static void
760update_identities(void *cls)
761{
762 struct EgoEntry *next_ego = cls;
763 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
764 1221
765 update_task = NULL; 1222 if (GNUNET_NO == reissue_ticket)
766 if (NULL == next_ego)
767 { 1223 {
768 if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
769 min_rel_exp = MIN_WAIT_TIME;
770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
771 ">>> Finished. Rescheduling in %"SCNu64"\n", 1225 "Skipping ticket.\n");
772 min_rel_exp.rel_value_us); 1226
773 ns_it = NULL; 1227 rh->offset++;
774 //finished -> reschedule 1228 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
775 update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, 1229
776 &update_identities, 1230
777 ego_head);
778 min_rel_exp.rel_value_us = 0;
779 return; 1231 return;
780 } 1232 }
781 priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
782 if (GNUNET_YES == next_ego->attributes_dirty)
783 {
784 //Starting over. We must update the Attributes for they might have changed.
785 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
786 priv_key,
787 &attribute_collect_error_cb,
788 next_ego,
789 &attribute_collect,
790 next_ego,
791 &attribute_collect_finished_cb,
792 next_ego);
793 1233
1234 //Create new ABE key for RP
1235 attrs_len = 0;
1236
1237 /* If this is the RP we want to revoke attributes of, the do so */
1238
1239 for (le = attrs->list_head; NULL != le; le = le->next)
1240 attrs_len++;
1241 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1242 i = 0;
1243 for (le = attrs->list_head; NULL != le; le = le->next) {
1244 GNUNET_asprintf (&policy, "%s_%lu",
1245 le->claim->name,
1246 le->claim->version);
1247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1248 "Recreating key with %s\n", policy);
1249 attr_arr[i] = policy;
1250 i++;
794 } 1251 }
795 else 1252 attr_arr[i] = NULL;
1253 rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
1254 attr_arr);
1255
1256 //TODO review this wireformat
1257 code_record_len = serialize_abe_keyinfo2 (ticket,
1258 attrs,
1259 rp_key,
1260 &ecdhe_privkey,
1261 &code_record_data);
1262 code_record[0].data = code_record_data;
1263 code_record[0].data_size = code_record_len;
1264 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1265 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1266 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1267
1268 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1269 sizeof (uint64_t));
1270 //Publish record
1271 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1272 &rh->identity,
1273 label,
1274 1,
1275 code_record,
1276 &reissue_ticket_cont,
1277 rh);
1278 //for (; i > 0; i--)
1279 // GNUNET_free (attr_arr[i-1]);
1280 GNUNET_free (ecdhe_privkey);
1281 GNUNET_free (label);
1282 GNUNET_free (attr_arr);
1283 GNUNET_free (code_record_data);
1284 GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
1285}
1286
1287
1288/* Prototype for below function */
1289static void
1290attr_reenc_cont (void *cls,
1291 int32_t success,
1292 const char *emsg);
1293
1294static void
1295revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1296{
1297 int ret;
1298 /* Done, issue new keys */
1299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1300 "Revocation Phase III: Reissuing Tickets\n");
1301 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1302 &rh->ticket.identity,
1303 GNUNET_NO,
1304 rh->offset,
1305 &ticket_reissue_proc,
1306 rh)))
796 { 1307 {
797 //Ego will be dirty next time 1308 GNUNET_break (0);
798 next_ego->attributes_dirty = GNUNET_YES; 1309 }
799 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, 1310 if (GNUNET_NO == ret)
800 priv_key, 1311 {
801 &token_collect_error_cb, 1312 send_revocation_finished (rh, GNUNET_OK);
802 next_ego, 1313 cleanup_revoke_ticket_handle (rh);
803 &token_collect, 1314 return;
804 next_ego,
805 &token_collect_finished_cb,
806 next_ego);
807 } 1315 }
808} 1316}
809 1317
810
811/** 1318/**
812 * Function called initially to start update task 1319 * Revoke next attribte by reencryption with
1320 * new ABE master
813 */ 1321 */
814static void 1322static void
815init_cont () 1323reenc_next_attribute (struct TicketRevocationHandle *rh)
816{ 1324{
817 GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n"); 1325 struct GNUNET_GNSRECORD_Data rd[1];
818 //Initially iterate all itenties and refresh all tokens 1326 char* buf;
819 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1327 char* enc_buf;
820 ego_head); 1328 size_t enc_size;
1329 char* rd_buf;
1330 size_t buf_size;
1331 char* policy;
1332 uint32_t attr_ver;
1333
1334 if (NULL == rh->attrs->list_head)
1335 {
1336 revocation_reissue_tickets (rh);
1337 return;
1338 }
1339 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1340 buf = GNUNET_malloc (buf_size);
1341 GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1342 buf);
1343 rh->attrs->list_head->claim->version++;
1344 GNUNET_asprintf (&policy, "%s_%lu",
1345 rh->attrs->list_head->claim->name,
1346 rh->attrs->list_head->claim->version);
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1348 "Encrypting with policy %s\n", policy);
1349 /**
1350 * Encrypt the attribute value and store in namestore
1351 */
1352 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1353 buf_size,
1354 policy, //Policy
1355 rh->abe_key,
1356 (void**)&enc_buf);
1357 GNUNET_free (buf);
1358 GNUNET_free (policy);
1359 rd[0].data_size = enc_size + sizeof (uint32_t);
1360 rd_buf = GNUNET_malloc (rd[0].data_size);
1361 attr_ver = htonl (rh->attrs->list_head->claim->version);
1362 GNUNET_memcpy (rd_buf,
1363 &attr_ver,
1364 sizeof (uint32_t));
1365 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1366 enc_buf,
1367 enc_size);
1368 rd[0].data = rd_buf;
1369 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1370 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1371 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1372 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1373 &rh->identity,
1374 rh->attrs->list_head->claim->name,
1375 1,
1376 rd,
1377 &attr_reenc_cont,
1378 rh);
1379 GNUNET_free (enc_buf);
1380 GNUNET_free (rd_buf);
821} 1381}
822 1382
823
824/** 1383/**
825 * Initial ego collection function. 1384 * Namestore callback after revoked attribute
826 * 1385 * is stored
827 * @param cls NULL
828 * @param ego ego
829 * @param ctx context
830 * @param identifier ego name
831 */ 1386 */
832static void 1387static void
833list_ego (void *cls, 1388attr_reenc_cont (void *cls,
834 struct GNUNET_IDENTITY_Ego *ego, 1389 int32_t success,
835 void **ctx, 1390 const char *emsg)
836 const char *identifier)
837{ 1391{
838 struct EgoEntry *new_entry; 1392 struct TicketRevocationHandle *rh = cls;
839 if ((NULL == ego) && (STATE_INIT == state)) 1393 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
1394
1395 if (GNUNET_SYSERR == success)
840 { 1396 {
841 state = STATE_POST_INIT; 1397 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
842 init_cont (); 1398 "Failed to reencrypt attribute %s\n",
1399 emsg);
1400 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
843 return; 1401 return;
844 } 1402 }
845 if (STATE_INIT == state) { 1403 if (NULL == rh->attrs->list_head)
846 new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); 1404 {
847 new_entry->ego = ego; 1405 revocation_reissue_tickets (rh);
848 new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5, 1406 return;
849 GNUNET_NO);
850 new_entry->attributes_dirty = GNUNET_YES;
851 GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
852 } 1407 }
1408 le = rh->attrs->list_head;
1409 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1410 rh->attrs->list_tail,
1411 le);
1412 GNUNET_assert (NULL != rh->rvk_attrs);
1413 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1414 rh->rvk_attrs->list_tail,
1415 le);
1416
1417
1418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1419 "Re-encrypting next attribute\n");
1420 reenc_next_attribute (rh);
853} 1421}
854 1422
855/** 1423
856 * Cleanup task
857 */
858static void 1424static void
859cleanup() 1425process_attributes_to_update (void *cls,
1426 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1427 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
860{ 1428{
861 struct EgoEntry *ego_entry; 1429 struct TicketRevocationHandle *rh = cls;
862 struct EgoEntry *ego_tmp;
863 1430
1431 rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs);
864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
865 "Cleaning up\n"); 1433 "Revocation Phase I: Collecting attributes\n");
866 if (NULL != stats) 1434 /* Reencrypt all attributes with new key */
1435 if (NULL == rh->attrs->list_head)
867 { 1436 {
868 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 1437 /* No attributes to reencrypt */
869 stats = NULL; 1438 send_revocation_finished (rh, GNUNET_OK);
1439 cleanup_revoke_ticket_handle (rh);
1440 return;
1441 } else {
1442 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1443 "Revocation Phase II: Re-encrypting attributes\n");
1444 reenc_next_attribute (rh);
870 } 1445 }
871 1446
872 if (NULL != timeout_task) 1447}
873 GNUNET_SCHEDULER_cancel (timeout_task);
874 if (NULL != update_task)
875 GNUNET_SCHEDULER_cancel (update_task);
876 if (NULL != identity_handle)
877 GNUNET_IDENTITY_disconnect (identity_handle);
878 if (NULL != gns_handle)
879 GNUNET_GNS_disconnect (gns_handle);
880 if (NULL != ns_it)
881 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
882 if (NULL != ns_qe)
883 GNUNET_NAMESTORE_cancel (ns_qe);
884 if (NULL != ns_handle)
885 GNUNET_NAMESTORE_disconnect (ns_handle);
886 if (NULL != token)
887 GNUNET_free (token);
888 if (NULL != label)
889 GNUNET_free (label);
890 1448
891 for (ego_entry = ego_head;
892 NULL != ego_entry;)
893 {
894 ego_tmp = ego_entry;
895 if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
896 {
897 GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
898 &clear_ego_attrs,
899 ego_tmp);
900 1449
901 } 1450
902 GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map); 1451static void
903 ego_entry = ego_entry->next; 1452get_ticket_after_abe_bootstrap (void *cls,
904 GNUNET_free (ego_tmp); 1453 struct GNUNET_ABE_AbeMasterKey *abe_key)
1454{
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1456 "Finished ABE bootstrap\n");
1457 struct TicketRevocationHandle *rh = cls;
1458 rh->abe_key = abe_key;
1459 TKT_database->get_ticket_attributes (TKT_database->cls,
1460 &rh->ticket,
1461 &process_attributes_to_update,
1462 rh);
1463}
1464
1465static int
1466check_revoke_ticket_message(void *cls,
1467 const struct RevokeTicketMessage *im)
1468{
1469 uint16_t size;
1470
1471 size = ntohs (im->header.size);
1472 if (size <= sizeof (struct RevokeTicketMessage))
1473 {
1474 GNUNET_break (0);
1475 return GNUNET_SYSERR;
905 } 1476 }
1477 return GNUNET_OK;
906} 1478}
907 1479
908/**
909 * Shutdown task
910 *
911 * @param cls NULL
912 * @param tc task context
913 */
914static void 1480static void
915do_shutdown (void *cls) 1481handle_revoke_ticket_message (void *cls,
1482 const struct RevokeTicketMessage *rm)
916{ 1483{
917 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1484 struct TicketRevocationHandle *rh;
918 "Shutting down...\n"); 1485 struct IdpClient *idp = cls;
919 cleanup(); 1486 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1487
1488 rh = GNUNET_new (struct TicketRevocationHandle);
1489 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1490 rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1491 rh->ticket = *ticket;
1492 rh->r_id = ntohl (rm->id);
1493 rh->client = idp;
1494 rh->identity = rm->identity;
1495 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1496 &rh->ticket.identity);
1497 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1498 idp->revocation_list_tail,
1499 rh);
1500 bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1501 GNUNET_SERVICE_client_continue (idp->client);
1502
920} 1503}
921 1504
922 1505
923static struct GNUNET_MQ_Envelope* 1506static void
924create_exchange_result_message (const char* token, 1507cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
925 const char* label,
926 uint64_t ticket_nonce,
927 uint64_t id)
928{ 1508{
929 struct GNUNET_MQ_Envelope *env; 1509 if (NULL != handle->key)
930 struct ExchangeResultMessage *erm; 1510 GNUNET_ABE_cpabe_delete_key (handle->key,
931 uint16_t token_len = strlen (token) + 1; 1511 GNUNET_YES);
932 1512 if (NULL != handle->attrs)
933 env = GNUNET_MQ_msg_extra (erm, 1513 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
934 token_len, 1514 GNUNET_free (handle);
935 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
936 erm->ticket_nonce = htonl (ticket_nonce);
937 erm->id = id;
938 GNUNET_memcpy (&erm[1], token, token_len);
939 return env;
940} 1515}
941 1516
942 1517
943static struct GNUNET_MQ_Envelope* 1518
944create_issue_result_message (const char* label, 1519static int
945 const char* ticket, 1520check_consume_ticket_message(void *cls,
946 const char* token, 1521 const struct ConsumeTicketMessage *cm)
947 uint64_t id)
948{ 1522{
949 struct GNUNET_MQ_Envelope *env; 1523 uint16_t size;
950 struct IssueResultMessage *irm;
951 char *tmp_str;
952 size_t len;
953 1524
954 GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token); 1525 size = ntohs (cm->header.size);
955 len = strlen (tmp_str) + 1; 1526 if (size <= sizeof (struct ConsumeTicketMessage))
956 env = GNUNET_MQ_msg_extra (irm, 1527 {
957 len, 1528 GNUNET_break (0);
958 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT); 1529 return GNUNET_SYSERR;
959 irm->id = id; 1530 }
960 GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1); 1531 return GNUNET_OK;
961 GNUNET_free (tmp_str);
962 return env;
963} 1532}
964 1533
965static void 1534static void
966cleanup_issue_handle (struct IssueHandle *handle) 1535process_parallel_lookup2 (void *cls, uint32_t rd_count,
967{ 1536 const struct GNUNET_GNSRECORD_Data *rd)
968 if (NULL != handle->attr_map) 1537{
969 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map); 1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
970 if (NULL != handle->scopes) 1539 "Parallel lookup finished (count=%u)\n", rd_count);
971 GNUNET_free (handle->scopes); 1540 struct ParallelLookup *parallel_lookup = cls;
972 if (NULL != handle->token) 1541 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
973 token_destroy (handle->token); 1542 struct ConsumeTicketResultMessage *crm;
974 if (NULL != handle->ticket) 1543 struct GNUNET_MQ_Envelope *env;
975 ticket_destroy (handle->ticket); 1544 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le;
976 if (NULL != handle->label) 1545 struct GNUNET_TIME_Absolute decrypt_duration;
977 GNUNET_free (handle->label); 1546 char *data;
978 GNUNET_free (handle); 1547 char *data_tmp;
1548 ssize_t attr_len;
1549 size_t attrs_len;
1550
1551 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1552 handle->parallel_lookups_tail,
1553 parallel_lookup);
1554 GNUNET_free (parallel_lookup->label);
1555
1556 GNUNET_STATISTICS_update (stats_handle,
1557 "attribute_lookup_time_total",
1558 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
1559 GNUNET_YES);
1560 GNUNET_STATISTICS_update (stats_handle,
1561 "attribute_lookups_count",
1562 1,
1563 GNUNET_YES);
1564
1565
1566 GNUNET_free (parallel_lookup);
1567 if (1 != rd_count)
1568 GNUNET_break(0);//TODO
1569 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1570 {
1571 decrypt_duration = GNUNET_TIME_absolute_get ();
1572 attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
1573 rd->data_size - sizeof (uint32_t),
1574 handle->key,
1575 (void**)&data);
1576 if (GNUNET_SYSERR != attr_len)
1577 {
1578 GNUNET_STATISTICS_update (stats_handle,
1579 "abe_decrypt_time_total",
1580 GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
1581 GNUNET_YES);
1582 GNUNET_STATISTICS_update (stats_handle,
1583 "abe_decrypt_count",
1584 1,
1585 GNUNET_YES);
1586
1587 attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
1588 attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data,
1589 attr_len);
1590 attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
1591 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1592 handle->attrs->list_tail,
1593 attr_le);
1594 GNUNET_free (data);
1595 }
1596 }
1597 if (NULL != handle->parallel_lookups_head)
1598 return; //Wait for more
1599 /* Else we are done */
1600
1601 /* Store ticket in DB */
1602 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1603 &handle->ticket,
1604 handle->attrs))
1605 {
1606 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1607 "Unable to store ticket after consume\n");
1608 GNUNET_break (0);
1609 }
1610
1611 GNUNET_SCHEDULER_cancel (handle->kill_task);
1612 attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs);
1613 env = GNUNET_MQ_msg_extra (crm,
1614 attrs_len,
1615 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1616 crm->id = htonl (handle->r_id);
1617 crm->attrs_len = htons (attrs_len);
1618 crm->identity = handle->ticket.identity;
1619 data_tmp = (char *) &crm[1];
1620 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs,
1621 data_tmp);
1622 GNUNET_MQ_send (handle->client->mq, env);
1623 cleanup_consume_ticket_handle (handle);
979} 1624}
980 1625
981static void 1626void
982store_token_issue_cont (void *cls, 1627abort_parallel_lookups2 (void *cls)
983 int32_t success,
984 const char *emsg)
985{ 1628{
986 struct IssueHandle *handle = cls; 1629 struct ConsumeTicketHandle *handle = cls;
1630 struct ParallelLookup *lu;
1631 struct ParallelLookup *tmp;
1632 struct AttributeResultMessage *arm;
987 struct GNUNET_MQ_Envelope *env; 1633 struct GNUNET_MQ_Envelope *env;
988 char *ticket_str;
989 char *token_str;
990 1634
991 handle->ns_qe = NULL; 1635 for (lu = handle->parallel_lookups_head;
992 if (GNUNET_SYSERR == success) 1636 NULL != lu;) {
1637 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1638 GNUNET_free (lu->label);
1639 tmp = lu->next;
1640 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1641 handle->parallel_lookups_tail,
1642 lu);
1643 GNUNET_free (lu);
1644 lu = tmp;
1645 }
1646 env = GNUNET_MQ_msg (arm,
1647 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1648 arm->id = htonl (handle->r_id);
1649 arm->attr_len = htons (0);
1650 GNUNET_MQ_send (handle->client->mq, env);
1651
1652}
1653
1654
1655static void
1656process_consume_abe_key (void *cls, uint32_t rd_count,
1657 const struct GNUNET_GNSRECORD_Data *rd)
1658{
1659 struct ConsumeTicketHandle *handle = cls;
1660 struct GNUNET_HashCode new_key_hash;
1661 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1662 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1663 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1664 struct ParallelLookup *parallel_lookup;
1665 size_t size;
1666 char *buf;
1667 char *scope;
1668 char *lookup_query;
1669
1670 handle->lookup_request = NULL;
1671 if (1 != rd_count)
993 { 1672 {
994 cleanup_issue_handle (handle); 1673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
995 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1674 "Number of keys %d != 1.",
996 "Unknown Error\n"); 1675 rd_count);
1676 cleanup_consume_ticket_handle (handle);
997 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1677 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
998 return; 1678 return;
999 } 1679 }
1000 if (GNUNET_OK != ticket_serialize (handle->ticket, 1680
1001 &handle->iss_key, 1681 //Decrypt
1002 &ticket_str)) 1682 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1683
1684 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1685
1686 //Calculate symmetric key from ecdh parameters
1687 GNUNET_assert (GNUNET_OK ==
1688 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1689 ecdh_key,
1690 &new_key_hash));
1691 create_sym_key_from_ecdh (&new_key_hash,
1692 &enc_key,
1693 &enc_iv);
1694 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1695 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1696 &enc_key,
1697 &enc_iv,
1698 buf);
1699
1700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1701 "Decrypted bytes: %zd Expected bytes: %zd\n",
1702 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1703 GNUNET_STATISTICS_update (stats_handle,
1704 "abe_key_lookup_time_total",
1705 GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
1706 GNUNET_YES);
1707 GNUNET_STATISTICS_update (stats_handle,
1708 "abe_key_lookups_count",
1709 1,
1710 GNUNET_YES);
1711 scopes = GNUNET_strdup (buf);
1712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1713 "Scopes %s\n", scopes);
1714 handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1715 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1716 - strlen (scopes) - 1);
1717
1718 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1003 { 1719 {
1004 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1720 GNUNET_asprintf (&lookup_query,
1005 "Error serializing ticket\n"); 1721 "%s.gnu",
1006 cleanup_issue_handle (handle); 1722 scope);
1007 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 return; 1724 "Looking up %s\n", lookup_query);
1725 parallel_lookup = GNUNET_new (struct ParallelLookup);
1726 parallel_lookup->handle = handle;
1727 parallel_lookup->label = GNUNET_strdup (scope);
1728 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
1729 parallel_lookup->lookup_request
1730 = GNUNET_GNS_lookup (gns_handle,
1731 lookup_query,
1732 &handle->ticket.identity,
1733 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1734 GNUNET_GNS_LO_DEFAULT,
1735 &process_parallel_lookup2,
1736 parallel_lookup);
1737 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1738 handle->parallel_lookups_tail,
1739 parallel_lookup);
1740 GNUNET_free (lookup_query);
1009 } 1741 }
1010 if (GNUNET_OK != token_to_string (handle->token, 1742 GNUNET_free (scopes);
1011 &handle->iss_key, 1743 GNUNET_free (buf);
1012 &token_str)) 1744 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1745 &abort_parallel_lookups2,
1746 handle);
1747}
1748
1749
1750static void
1751handle_consume_ticket_message (void *cls,
1752 const struct ConsumeTicketMessage *cm)
1753{
1754 struct ConsumeTicketHandle *ch;
1755 struct IdpClient *idp = cls;
1756 char* lookup_query;
1757 char* rnd_label;
1758
1759 ch = GNUNET_new (struct ConsumeTicketHandle);
1760 ch->r_id = ntohl (cm->id);
1761 ch->client = idp;
1762 ch->identity = cm->identity;
1763 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1764 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1765 &ch->identity_pub);
1766 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1767 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1768 sizeof (uint64_t));
1769 GNUNET_asprintf (&lookup_query,
1770 "%s.gnu",
1771 rnd_label);
1772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1773 "Looking for ABE key under %s\n", lookup_query);
1774 ch->lookup_start_time = GNUNET_TIME_absolute_get ();
1775 ch->lookup_request
1776 = GNUNET_GNS_lookup (gns_handle,
1777 lookup_query,
1778 &ch->ticket.identity,
1779 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1780 GNUNET_GNS_LO_DEFAULT,
1781 &process_consume_abe_key,
1782 ch);
1783 GNUNET_free (rnd_label);
1784 GNUNET_free (lookup_query);
1785 GNUNET_SERVICE_client_continue (idp->client);
1786}
1787
1788static void
1789cleanup_as_handle (struct AttributeStoreHandle *handle)
1790{
1791 if (NULL != handle->claim)
1792 GNUNET_free (handle->claim);
1793 if (NULL != handle->abe_key)
1794 GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
1795 GNUNET_free (handle);
1796}
1797
1798static void
1799attr_store_cont (void *cls,
1800 int32_t success,
1801 const char *emsg)
1802{
1803 struct AttributeStoreHandle *as_handle = cls;
1804 struct GNUNET_MQ_Envelope *env;
1805 struct AttributeStoreResultMessage *acr_msg;
1806
1807 if (GNUNET_SYSERR == success)
1013 { 1808 {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1809 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1015 "Error serializing token\n"); 1810 "Failed to store attribute %s\n",
1016 GNUNET_free (ticket_str); 1811 emsg);
1017 cleanup_issue_handle (handle); 1812 cleanup_as_handle (as_handle);
1018 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1813 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1019 return; 1814 return;
1020 } 1815 }
1021 env = create_issue_result_message (handle->label, 1816
1022 ticket_str, 1817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1023 token_str, 1818 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1024 handle->r_id); 1819 env = GNUNET_MQ_msg (acr_msg,
1025 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client), 1820 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1821 acr_msg->id = htonl (as_handle->r_id);
1822 acr_msg->op_result = htonl (GNUNET_OK);
1823 GNUNET_MQ_send (as_handle->client->mq,
1026 env); 1824 env);
1027 cleanup_issue_handle (handle); 1825 cleanup_as_handle (as_handle);
1028 GNUNET_free (ticket_str);
1029 GNUNET_free (token_str);
1030} 1826}
1031 1827
1032
1033/**
1034 * Build a token and store it
1035 *
1036 * @param cls the IssueHandle
1037 */
1038static void 1828static void
1039sign_and_return_token (void *cls) 1829attr_store_task (void *cls)
1040{ 1830{
1041 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 1831 struct AttributeStoreHandle *as_handle = cls;
1042 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; 1832 struct GNUNET_GNSRECORD_Data rd[1];
1043 struct IssueHandle *handle = cls; 1833 char* buf;
1044 struct GNUNET_GNSRECORD_Data token_record[2]; 1834 char* policy;
1045 char *nonce_str; 1835 char* enc_buf;
1046 char *enc_token_str; 1836 char* rd_buf;
1047 char *token_metadata; 1837 size_t enc_size;
1048 char* write_ptr; 1838 size_t buf_size;
1049 uint64_t time; 1839 uint32_t attr_ver;
1050 uint64_t exp_time; 1840
1051 size_t token_metadata_len; 1841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1052 1842 "Storing attribute\n");
1053 //Remote nonce 1843 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim);
1054 nonce_str = NULL; 1844 buf = GNUNET_malloc (buf_size);
1055 GNUNET_asprintf (&nonce_str, "%lu", handle->nonce); 1845
1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str); 1846 GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim,
1057 1847 buf);
1058 GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key, 1848
1059 &pub_key); 1849 GNUNET_asprintf (&policy,
1060 handle->ticket = ticket_create (handle->nonce, 1850 "%s_%lu",
1061 &pub_key, 1851 as_handle->claim->name,
1062 handle->label, 1852 as_handle->claim->version);
1063 &handle->aud_key); 1853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1064 1854 "Encrypting with policy %s\n", policy);
1065 time = GNUNET_TIME_absolute_get().abs_value_us; 1855 /**
1066 exp_time = time + token_expiration_interval.rel_value_us; 1856 * Encrypt the attribute value and store in namestore
1067 1857 */
1068 token_add_attr_int (handle->token, "nbf", time); 1858 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1069 token_add_attr_int (handle->token, "iat", time); 1859 buf_size,
1070 token_add_attr_int (handle->token, "exp", exp_time); 1860 policy, //Policy
1071 token_add_attr (handle->token, "nonce", nonce_str); 1861 as_handle->abe_key,
1072 1862 (void**)&enc_buf);
1073 //Token in a serialized encrypted format 1863 GNUNET_free (buf);
1074 GNUNET_assert (token_serialize (handle->token, 1864 GNUNET_free (policy);
1075 &handle->iss_key, 1865 rd[0].data_size = enc_size + sizeof (uint32_t);
1076 &ecdhe_privkey, 1866 rd_buf = GNUNET_malloc (rd[0].data_size);
1077 &enc_token_str)); 1867 attr_ver = htonl (as_handle->claim->version);
1078 1868 GNUNET_memcpy (rd_buf,
1079 //Token record E,E_K (Token) 1869 &attr_ver,
1080 token_record[0].data = enc_token_str; 1870 sizeof (uint32_t));
1081 token_record[0].data_size = strlen (enc_token_str) + 1; 1871 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1082 token_record[0].expiration_time = exp_time; 1872 enc_buf,
1083 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; 1873 enc_size);
1084 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE; 1874 rd[0].data = rd_buf;
1085 1875 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1086 1876 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1087 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) 1877 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1088 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) 1878 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1089 + strlen (handle->scopes) + 1; //With 0-Terminator 1879 &as_handle->identity,
1090 token_metadata = GNUNET_malloc (token_metadata_len); 1880 as_handle->claim->name,
1091 write_ptr = token_metadata; 1881 1,
1092 GNUNET_memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); 1882 rd,
1093 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); 1883 &attr_store_cont,
1094 GNUNET_memcpy (write_ptr, &handle->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 1884 as_handle);
1095 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); 1885 GNUNET_free (enc_buf);
1096 GNUNET_memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); //with 0-Terminator; 1886 GNUNET_free (rd_buf);
1097
1098 token_record[1].data = token_metadata;
1099 token_record[1].data_size = token_metadata_len;
1100 token_record[1].expiration_time = exp_time;
1101 token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
1102 token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1103
1104 //Persist token
1105 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1106 &handle->iss_key,
1107 handle->label,
1108 2,
1109 token_record,
1110 &store_token_issue_cont,
1111 handle);
1112 GNUNET_free (ecdhe_privkey);
1113 GNUNET_free (nonce_str);
1114 GNUNET_free (enc_token_str);
1115 GNUNET_free (token_metadata);
1116} 1887}
1117 1888
1118 1889
1119static void 1890static void
1120attr_collect_error (void *cls) 1891store_after_abe_bootstrap (void *cls,
1892 struct GNUNET_ABE_AbeMasterKey *abe_key)
1121{ 1893{
1122 struct IssueHandle *handle = cls; 1894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1895 "Finished ABE bootstrap\n");
1896 struct AttributeStoreHandle *ash = cls;
1897 ash->abe_key = abe_key;
1898 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1899}
1123 1900
1124 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n"); 1901static int
1125 handle->ns_it = NULL; 1902check_attribute_store_message(void *cls,
1126 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); 1903 const struct AttributeStoreMessage *sam)
1904{
1905 uint16_t size;
1906
1907 size = ntohs (sam->header.size);
1908 if (size <= sizeof (struct AttributeStoreMessage))
1909 {
1910 GNUNET_break (0);
1911 return GNUNET_SYSERR;
1912 }
1913 return GNUNET_OK;
1127} 1914}
1128 1915
1129 1916
1130static void 1917static void
1131attr_collect_finished (void *cls) 1918handle_attribute_store_message (void *cls,
1919 const struct AttributeStoreMessage *sam)
1132{ 1920{
1133 struct IssueHandle *handle = cls; 1921 struct AttributeStoreHandle *as_handle;
1922 struct IdpClient *idp = cls;
1923 size_t data_len;
1924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1925 "Received ATTRIBUTE_STORE message\n");
1926
1927 data_len = ntohs (sam->attr_len);
1928
1929 as_handle = GNUNET_new (struct AttributeStoreHandle);
1930 as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1],
1931 data_len);
1932
1933 as_handle->r_id = ntohl (sam->id);
1934 as_handle->identity = sam->identity;
1935 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1936 &as_handle->identity_pkey);
1134 1937
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n"); 1938 GNUNET_SERVICE_client_continue (idp->client);
1136 handle->ns_it = NULL; 1939 as_handle->client = idp;
1137 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); 1940 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
1138} 1941}
1139 1942
1943static void
1944cleanup_iter_handle (struct AttributeIterator *ai)
1945{
1946 if (NULL != ai->abe_key)
1947 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
1948 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1949 ai->client->op_tail,
1950 ai);
1951 GNUNET_free (ai);
1952}
1953
1954static void
1955attr_iter_error (void *cls)
1956{
1957 struct AttributeIterator *ai = cls;
1958 //TODO
1959 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1960 "Failed to iterate over attributes\n");
1961 cleanup_iter_handle (ai);
1962 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1963}
1964
1965static void
1966attr_iter_finished (void *cls)
1967{
1968 struct AttributeIterator *ai = cls;
1969 struct GNUNET_MQ_Envelope *env;
1970 struct AttributeResultMessage *arm;
1971
1972 env = GNUNET_MQ_msg (arm,
1973 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1974 arm->id = htonl (ai->request_id);
1975 arm->attr_len = htons (0);
1976 GNUNET_MQ_send (ai->client->mq, env);
1977 cleanup_iter_handle (ai);
1978}
1140 1979
1141/**
1142 * Collect attributes for token
1143 */
1144static void 1980static void
1145attr_collect (void *cls, 1981attr_iter_cb (void *cls,
1146 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1982 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1147 const char *label, 1983 const char *label,
1148 unsigned int rd_count, 1984 unsigned int rd_count,
1149 const struct GNUNET_GNSRECORD_Data *rd) 1985 const struct GNUNET_GNSRECORD_Data *rd)
1150{ 1986{
1151 struct IssueHandle *handle = cls; 1987 struct AttributeIterator *ai = cls;
1152 int i; 1988 struct AttributeResultMessage *arm;
1153 char* data; 1989 struct GNUNET_ABE_AbeKey *key;
1154 struct GNUNET_HashCode key; 1990 struct GNUNET_MQ_Envelope *env;
1155 1991 ssize_t msg_extra_len;
1156 GNUNET_CRYPTO_hash (label, 1992 char* attr_ser;
1157 strlen (label), 1993 char* attrs[2];
1158 &key); 1994 char* data_tmp;
1159 1995 char* policy;
1160 if (0 == rd_count || 1996 uint32_t attr_ver;
1161 ( (NULL != handle->attr_map) && 1997
1162 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, 1998 if (rd_count != 1)
1163 &key))
1164 )
1165 )
1166 { 1999 {
1167 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2000 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1168 return; 2001 return;
1169 } 2002 }
1170 2003
1171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label); 2004 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1172 2005 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1173 if (1 == rd_count)
1174 {
1175 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1176 {
1177 data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
1178 rd->data,
1179 rd->data_size);
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1181 token_add_attr (handle->token,
1182 label,
1183 data);
1184 GNUNET_free (data);
1185 }
1186 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1187 return; 2006 return;
1188 } 2007 }
2008 attr_ver = ntohl(*((uint32_t*)rd->data));
2009 GNUNET_asprintf (&policy, "%s_%lu",
2010 label, attr_ver);
2011 attrs[0] = policy;
2012 attrs[1] = 0;
2013 key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
2014 attrs);
2015 msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
2016 rd->data_size-sizeof (uint32_t),
2017 key,
2018 (void**)&attr_ser);
2019
2020 GNUNET_ABE_cpabe_delete_key (key,
2021 GNUNET_YES);
2022 //GNUNET_free (policy);
2023 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2024 "Found attribute: %s\n", label);
2025 env = GNUNET_MQ_msg_extra (arm,
2026 msg_extra_len,
2027 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2028 arm->id = htonl (ai->request_id);
2029 arm->attr_len = htons (msg_extra_len);
2030 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2031 &arm->identity);
2032 data_tmp = (char *) &arm[1];
2033 GNUNET_memcpy (data_tmp,
2034 attr_ser,
2035 msg_extra_len);
2036 GNUNET_MQ_send (ai->client->mq, env);
2037 GNUNET_free (attr_ser);
2038 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2039 ai->abe_key = NULL;
2040}
1189 2041
1190 i = 0;
1191 for (; i < rd_count; i++)
1192 {
1193 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1194 {
1195 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
1196 rd[i].data,
1197 rd[i].data_size);
1198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1199 token_add_attr (handle->token, label, data);
1200 GNUNET_free (data);
1201 }
1202 }
1203 2042
1204 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2043void
2044iterate_after_abe_bootstrap (void *cls,
2045 struct GNUNET_ABE_AbeMasterKey *abe_key)
2046{
2047 struct AttributeIterator *ai = cls;
2048 ai->abe_key = abe_key;
2049 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2050 &ai->identity,
2051 &attr_iter_error,
2052 ai,
2053 &attr_iter_cb,
2054 ai,
2055 &attr_iter_finished,
2056 ai);
1205} 2057}
1206 2058
2059void
2060iterate_next_after_abe_bootstrap (void *cls,
2061 struct GNUNET_ABE_AbeMasterKey *abe_key)
2062{
2063 struct AttributeIterator *ai = cls;
2064 ai->abe_key = abe_key;
2065 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2066}
2067
2068
2069
1207static void 2070static void
1208cleanup_exchange_handle (struct ExchangeHandle *handle) 2071handle_iteration_start (void *cls,
2072 const struct AttributeIterationStartMessage *ais_msg)
1209{ 2073{
1210 if (NULL != handle->ticket) 2074 struct IdpClient *idp = cls;
1211 ticket_destroy (handle->ticket); 2075 struct AttributeIterator *ai;
1212 if (NULL != handle->token) 2076
1213 token_destroy (handle->token); 2077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1214 GNUNET_free (handle); 2078 "Received ATTRIBUTE_ITERATION_START message\n");
2079 ai = GNUNET_new (struct AttributeIterator);
2080 ai->request_id = ntohl (ais_msg->id);
2081 ai->client = idp;
2082 ai->identity = ais_msg->identity;
2083
2084 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2085 idp->op_tail,
2086 ai);
2087 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2088 GNUNET_SERVICE_client_continue (idp->client);
1215} 2089}
1216 2090
2091
1217static void 2092static void
1218process_lookup_result (void *cls, uint32_t rd_count, 2093handle_iteration_stop (void *cls,
1219 const struct GNUNET_GNSRECORD_Data *rd) 2094 const struct AttributeIterationStopMessage *ais_msg)
1220{ 2095{
1221 struct ExchangeHandle *handle = cls; 2096 struct IdpClient *idp = cls;
1222 struct GNUNET_MQ_Envelope *env; 2097 struct AttributeIterator *ai;
1223 char* token_str; 2098 uint32_t rid;
1224 char* record_str;
1225 2099
1226 handle->lookup_request = NULL; 2100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1227 if (2 != rd_count) 2101 "Received `%s' message\n",
2102 "ATTRIBUTE_ITERATION_STOP");
2103 rid = ntohl (ais_msg->id);
2104 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2105 if (ai->request_id == rid)
2106 break;
2107 if (NULL == ai)
1228 { 2108 {
1229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2109 GNUNET_break (0);
1230 "Number of tokens %d != 2.", 2110 GNUNET_SERVICE_client_drop (idp->client);
1231 rd_count);
1232 cleanup_exchange_handle (handle);
1233 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1234 return; 2111 return;
1235 } 2112 }
1236 2113 GNUNET_CONTAINER_DLL_remove (idp->op_head,
1237 record_str = 2114 idp->op_tail,
1238 GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN, 2115 ai);
1239 rd->data, 2116 GNUNET_free (ai);
1240 rd->data_size); 2117 GNUNET_SERVICE_client_continue (idp->client);
1241
1242 //Decrypt and parse
1243 GNUNET_assert (GNUNET_OK == token_parse (record_str,
1244 &handle->aud_privkey,
1245 &handle->token));
1246
1247 //Readable
1248 GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
1249 &handle->aud_privkey,
1250 &token_str));
1251
1252 env = create_exchange_result_message (token_str,
1253 handle->label,
1254 handle->ticket->payload->nonce,
1255 handle->r_id);
1256 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
1257 env);
1258 cleanup_exchange_handle (handle);
1259 GNUNET_free (record_str);
1260 GNUNET_free (token_str);
1261} 2118}
1262 2119
1263/** 2120
1264 * Checks a exchange message 2121static void
1265 * 2122handle_iteration_next (void *cls,
1266 * @param cls client sending the message 2123 const struct AttributeIterationNextMessage *ais_msg)
1267 * @param xm message of type `struct ExchangeMessage`
1268 * @return #GNUNET_OK if @a xm is well-formed
1269 */
1270static int
1271check_exchange_message (void *cls,
1272 const struct ExchangeMessage *xm)
1273{ 2124{
1274 uint16_t size; 2125 struct IdpClient *idp = cls;
2126 struct AttributeIterator *ai;
2127 uint32_t rid;
1275 2128
1276 size = ntohs (xm->header.size); 2129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1277 if (size <= sizeof (struct ExchangeMessage)) 2130 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2131 rid = ntohl (ais_msg->id);
2132 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2133 if (ai->request_id == rid)
2134 break;
2135 if (NULL == ai)
1278 { 2136 {
1279 GNUNET_break (0); 2137 GNUNET_break (0);
1280 return GNUNET_SYSERR; 2138 GNUNET_SERVICE_client_drop (idp->client);
2139 return;
1281 } 2140 }
1282 return GNUNET_OK; 2141 bootstrap_abe (&ai->identity,
2142 &iterate_next_after_abe_bootstrap,
2143 ai,
2144 GNUNET_NO);
2145 GNUNET_SERVICE_client_continue (idp->client);
1283} 2146}
1284 2147
1285/** 2148/**
1286 * 2149 * Ticket iteration processor result
1287 * Handler for exchange message
1288 *
1289 * @param cls unused
1290 * @param client who sent the message
1291 * @param message the message
1292 */ 2150 */
1293static void 2151enum ZoneIterationResult
1294handle_exchange_message (void *cls,
1295 const struct ExchangeMessage *xm)
1296{ 2152{
1297 struct ExchangeHandle *xchange_handle; 2153 /**
1298 struct GNUNET_SERVICE_Client *client = cls; 2154 * Iteration start.
1299 const char *ticket; 2155 */
1300 char *lookup_query; 2156 IT_START = 0,
1301 2157
1302 ticket = (const char *) &xm[1]; 2158 /**
1303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2159 * Found tickets,
1304 "Received EXCHANGE of `%s' from client\n", 2160 * Continue to iterate with next iteration_next call
1305 ticket); 2161 */
1306 xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle)); 2162 IT_SUCCESS_MORE_AVAILABLE = 1,
1307 xchange_handle->aud_privkey = xm->aud_privkey;
1308 xchange_handle->r_id = xm->id;
1309 if (GNUNET_SYSERR == ticket_parse (ticket,
1310 &xchange_handle->aud_privkey,
1311 &xchange_handle->ticket))
1312 {
1313 GNUNET_free (xchange_handle);
1314 GNUNET_SERVICE_client_drop (client);
1315 return;
1316 }
1317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for token under %s\n",
1318 xchange_handle->ticket->payload->label);
1319 GNUNET_asprintf (&lookup_query,
1320 "%s.gnu",
1321 xchange_handle->ticket->payload->label);
1322 GNUNET_SERVICE_client_continue (client);
1323 xchange_handle->client = client;
1324 xchange_handle->lookup_request
1325 = GNUNET_GNS_lookup (gns_handle,
1326 lookup_query,
1327 &xchange_handle->ticket->payload->identity_key,
1328 GNUNET_GNSRECORD_TYPE_ID_TOKEN,
1329 GNUNET_GNS_LO_LOCAL_MASTER,
1330 &process_lookup_result,
1331 xchange_handle);
1332 GNUNET_free (lookup_query);
1333 2163
1334} 2164 /**
2165 * Iteration complete
2166 */
2167 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2168};
1335 2169
1336 2170
1337static void 2171/**
1338find_existing_token_error (void *cls) 2172 * Context for ticket iteration
2173 */
2174struct TicketIterationProcResult
1339{ 2175{
1340 struct IssueHandle *handle = cls; 2176 /**
1341 cleanup_issue_handle (handle); 2177 * The ticket iteration handle
1342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error looking for existing token\n"); 2178 */
1343 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 2179 struct TicketIteration *ti;
1344}
1345 2180
2181 /**
2182 * Iteration result: iteration done?
2183 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2184 * we got one for now and have sent it to the client
2185 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2186 * #IT_START: if we are still trying to find a result.
2187 */
2188 int res_iteration_finished;
2189
2190};
1346 2191
1347static void 2192static void
1348find_existing_token_finished (void *cls) 2193cleanup_ticket_iter_handle (struct TicketIteration *ti)
1349{ 2194{
1350 struct IssueHandle *handle = cls; 2195 GNUNET_free (ti);
1351 uint64_t rnd_key;
1352
1353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1354 ">>> No existing token found\n");
1355 rnd_key =
1356 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1357 UINT64_MAX);
1358 GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
1359 sizeof (uint64_t),
1360 &handle->label);
1361 handle->ns_it = NULL;
1362 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1363 &handle->iss_key,
1364 &attr_collect_error,
1365 handle,
1366 &attr_collect,
1367 handle,
1368 &attr_collect_finished,
1369 handle);
1370} 2196}
1371 2197
1372
1373/** 2198/**
2199 * Process ticket from database
1374 * 2200 *
1375 * Look for existing token 2201 * @param cls struct TicketIterationProcResult
1376 * 2202 * @param ticket the ticket
1377 * @param cls the identity entry 2203 * @param attrs the attributes
1378 * @param zone the identity
1379 * @param lbl the name of the record
1380 * @param rd_count number of records
1381 * @param rd record data
1382 *
1383 */ 2204 */
1384static void 2205static void
1385find_existing_token (void *cls, 2206ticket_iterate_proc (void *cls,
1386 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 2207 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1387 const char *lbl, 2208 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
1388 unsigned int rd_count, 2209{
1389 const struct GNUNET_GNSRECORD_Data *rd) 2210 struct TicketIterationProcResult *proc = cls;
1390{
1391 struct IssueHandle *handle = cls;
1392 const struct GNUNET_GNSRECORD_Data *token_metadata_record;
1393 struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
1394 struct GNUNET_HashCode key;
1395 int scope_count_token;
1396 char *scope;
1397 char *tmp_scopes;
1398 2211
1399 //There should be only a single record for a token under a label 2212 if (NULL == ticket)
1400 if (2 != rd_count)
1401 { 2213 {
1402 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2215 "Iteration done\n");
2216 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1403 return; 2217 return;
1404 } 2218 }
2219 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2220 send_ticket_result (proc->ti->client,
2221 proc->ti->r_id,
2222 ticket,
2223 attrs);
1405 2224
1406 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 2225}
1407 {
1408 token_metadata_record = &rd[0];
1409 }
1410 else
1411 {
1412 token_metadata_record = &rd[1];
1413 }
1414 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
1415 {
1416 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1417 return;
1418 }
1419 ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
1420 aud_key =
1421 (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
1422 tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1423 2226
1424 if (0 != memcmp (aud_key, &handle->aud_key, 2227/**
1425 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) 2228 * Perform ticket iteration step
1426 { 2229 *
1427 char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key, 2230 * @param ti ticket iterator to process
1428 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 2231 */
1429 //Audience does not match! 2232static void
1430 char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA, 2233run_ticket_iteration_round (struct TicketIteration *ti)
1431 token_metadata_record->data, 2234{
1432 token_metadata_record->data_size); 2235 struct TicketIterationProcResult proc;
1433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2236 struct GNUNET_MQ_Envelope *env;
1434 "Token does not match audience %s vs %s. Moving on\n", 2237 struct TicketResultMessage *trm;
1435 tmp2, 2238 int ret;
1436 tmp);
1437 GNUNET_free (tmp_scopes);
1438 GNUNET_free (tmp2);
1439 GNUNET_free (tmp);
1440 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1441 return;
1442 }
1443 2239
1444 scope = strtok (tmp_scopes, ","); 2240 memset (&proc, 0, sizeof (proc));
1445 scope_count_token = 0; 2241 proc.ti = ti;
1446 while (NULL != scope) 2242 proc.res_iteration_finished = IT_START;
2243 while (IT_START == proc.res_iteration_finished)
1447 { 2244 {
1448 GNUNET_CRYPTO_hash (scope, 2245 if (GNUNET_SYSERR ==
1449 strlen (scope), 2246 (ret = TKT_database->iterate_tickets (TKT_database->cls,
1450 &key); 2247 &ti->identity,
1451 2248 ti->is_audience,
1452 if ((NULL != handle->attr_map) && 2249 ti->offset,
1453 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key))) 2250 &ticket_iterate_proc,
2251 &proc)))
1454 { 2252 {
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2253 GNUNET_break (0);
1456 "Issued token does not include `%s'. Moving on\n", scope); 2254 break;
1457 GNUNET_free (tmp_scopes);
1458 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1459 return;
1460 } 2255 }
1461 scope_count_token++; 2256 if (GNUNET_NO == ret)
1462 scope = strtok (NULL, ","); 2257 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2258 ti->offset++;
1463 } 2259 }
1464 GNUNET_free (tmp_scopes); 2260 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1465 //All scopes in token are also in request. Now
1466 //Check length
1467 if ((NULL != handle->attr_map) &&
1468 (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == scope_count_token))
1469 { 2261 {
1470 //We have an existing token 2262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1471 handle->label = GNUNET_strdup (lbl); 2263 "More results available\n");
1472 handle->ns_it = NULL; 2264 return; /* more later */
1473 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1474 &handle->iss_key,
1475 &attr_collect_error,
1476 handle,
1477 &attr_collect,
1478 handle,
1479 &attr_collect_finished,
1480 handle);
1481
1482 return;
1483 } 2265 }
1484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2266 /* send empty response to indicate end of list */
1485 "Nuber of attributes in token do not match request\n"); 2267 env = GNUNET_MQ_msg (trm,
1486 //No luck 2268 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
1487 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2269 trm->id = htonl (ti->r_id);
2270 GNUNET_MQ_send (ti->client->mq,
2271 env);
2272 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2273 ti->client->ticket_iter_tail,
2274 ti);
2275 cleanup_ticket_iter_handle (ti);
1488} 2276}
1489 2277
1490/** 2278static void
1491 * Checks an issue message 2279handle_ticket_iteration_start (void *cls,
1492 * 2280 const struct TicketIterationStartMessage *tis_msg)
1493 * @param cls client sending the message
1494 * @param im message of type `struct IssueMessage`
1495 * @return #GNUNET_OK if @a im is well-formed
1496 */
1497static int
1498check_issue_message(void *cls,
1499 const struct IssueMessage *im)
1500{ 2281{
1501 uint16_t size; 2282 struct IdpClient *client = cls;
2283 struct TicketIteration *ti;
1502 2284
1503 size = ntohs (im->header.size); 2285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1504 if (size <= sizeof (struct IssueMessage)) 2286 "Received TICKET_ITERATION_START message\n");
1505 { 2287 ti = GNUNET_new (struct TicketIteration);
1506 GNUNET_break (0); 2288 ti->r_id = ntohl (tis_msg->id);
1507 return GNUNET_SYSERR; 2289 ti->offset = 0;
1508 } 2290 ti->client = client;
1509 scopes = (char *) &im[1]; 2291 ti->identity = tis_msg->identity;
1510 if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1]) 2292 ti->is_audience = ntohl (tis_msg->is_audience);
2293
2294 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2295 client->ticket_iter_tail,
2296 ti);
2297 run_ticket_iteration_round (ti);
2298 GNUNET_SERVICE_client_continue (client->client);
2299}
2300
2301
2302static void
2303handle_ticket_iteration_stop (void *cls,
2304 const struct TicketIterationStopMessage *tis_msg)
2305{
2306 struct IdpClient *client = cls;
2307 struct TicketIteration *ti;
2308 uint32_t rid;
2309
2310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2311 "Received `%s' message\n",
2312 "TICKET_ITERATION_STOP");
2313 rid = ntohl (tis_msg->id);
2314 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2315 if (ti->r_id == rid)
2316 break;
2317 if (NULL == ti)
1511 { 2318 {
1512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1513 "Malformed scopes received!\n");
1514 GNUNET_break (0); 2319 GNUNET_break (0);
1515 return GNUNET_SYSERR; 2320 GNUNET_SERVICE_client_drop (client->client);
2321 return;
1516 } 2322 }
1517 return GNUNET_OK; 2323 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2324 client->ticket_iter_tail,
2325 ti);
2326 cleanup_ticket_iter_handle (ti);
2327 GNUNET_SERVICE_client_continue (client->client);
1518} 2328}
1519 2329
1520/** 2330
1521 *
1522 * Handler for issue message
1523 *
1524 * @param cls unused
1525 * @param client who sent the message
1526 * @param message the message
1527 */
1528static void 2331static void
1529handle_issue_message (void *cls, 2332handle_ticket_iteration_next (void *cls,
1530 const struct IssueMessage *im) 2333 const struct TicketIterationNextMessage *tis_msg)
1531{ 2334{
1532 const char *scopes; 2335 struct IdpClient *client = cls;
1533 char *scopes_tmp; 2336 struct TicketIteration *ti;
1534 char *scope; 2337 uint32_t rid;
1535 struct GNUNET_HashCode key;
1536 struct IssueHandle *issue_handle;
1537 struct GNUNET_SERVICE_Client *client = cls;
1538
1539 scopes = (const char *) &im[1];
1540 issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
1541 issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
1542 GNUNET_NO);
1543 scopes_tmp = GNUNET_strdup (scopes);
1544 2338
1545 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) 2339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2340 "Received TICKET_ITERATION_NEXT message\n");
2341 rid = ntohl (tis_msg->id);
2342 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2343 if (ti->r_id == rid)
2344 break;
2345 if (NULL == ti)
1546 { 2346 {
1547 GNUNET_CRYPTO_hash (scope, 2347 GNUNET_break (0);
1548 strlen (scope), 2348 GNUNET_SERVICE_client_drop (client->client);
1549 &key); 2349 return;
1550 GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1551 &key,
1552 scope,
1553 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1554 } 2350 }
1555 GNUNET_free (scopes_tmp); 2351 run_ticket_iteration_round (ti);
1556 issue_handle->r_id = im->id; 2352 GNUNET_SERVICE_client_continue (client->client);
1557 issue_handle->aud_key = im->aud_key;
1558 issue_handle->iss_key = im->iss_key;
1559 GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
1560 &issue_handle->iss_pkey);
1561 issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
1562 issue_handle->nonce = ntohl (im->nonce);
1563 GNUNET_SERVICE_client_continue (client);
1564 issue_handle->client = client;
1565 issue_handle->scopes = GNUNET_strdup (scopes);
1566 issue_handle->token = token_create (&issue_handle->iss_pkey,
1567 &issue_handle->aud_key);
1568
1569 issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1570 &im->iss_key,
1571 &find_existing_token_error,
1572 issue_handle,
1573 &find_existing_token,
1574 issue_handle,
1575 &find_existing_token_finished,
1576 issue_handle);
1577} 2353}
1578 2354
1579 2355
2356
2357
1580/** 2358/**
1581 * Main function that will be run 2359 * Main function that will be run
1582 * 2360 *
1583 * @param cls closure 2361 * @param cls closure
1584 * @param args remaining command-line arguments 2362 * @param c the configuration used
1585 * @param cfgfile name of the configuration file used (for saving, can be NULL) 2363 * @param server the service handle
1586 * @param c configuration
1587 */ 2364 */
1588static void 2365static void
1589run (void *cls, 2366run (void *cls,
1590 const struct GNUNET_CONFIGURATION_Handle *c, 2367 const struct GNUNET_CONFIGURATION_Handle *c,
1591 struct GNUNET_SERVICE_Handle *server) 2368 struct GNUNET_SERVICE_Handle *server)
1592{ 2369{
2370 char *database;
1593 cfg = c; 2371 cfg = c;
1594 2372
1595 stats = GNUNET_STATISTICS_create ("identity-provider", cfg); 2373 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
@@ -1606,10 +2384,38 @@ run (void *cls,
1606 { 2384 {
1607 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); 2385 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1608 } 2386 }
1609 2387 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2388 if (NULL == credential_handle)
2389 {
2390 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2391 }
1610 identity_handle = GNUNET_IDENTITY_connect (cfg, 2392 identity_handle = GNUNET_IDENTITY_connect (cfg,
1611 &list_ego, 2393 NULL,
1612 NULL); 2394 NULL);
2395 stats_handle = GNUNET_STATISTICS_create ("identity-provider",
2396 cfg);
2397 /* Loading DB plugin */
2398 if (GNUNET_OK !=
2399 GNUNET_CONFIGURATION_get_value_string (cfg,
2400 "identity-provider",
2401 "database",
2402 &database))
2403 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2404 "No database backend configured\n");
2405 GNUNET_asprintf (&db_lib_name,
2406 "libgnunet_plugin_identity_provider_%s",
2407 database);
2408 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2409 (void *) cfg);
2410 GNUNET_free (database);
2411 if (NULL == TKT_database)
2412 {
2413 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2414 "Could not load database backend `%s'\n",
2415 db_lib_name);
2416 GNUNET_SCHEDULER_shutdown ();
2417 return;
2418 }
1613 2419
1614 if (GNUNET_OK == 2420 if (GNUNET_OK ==
1615 GNUNET_CONFIGURATION_get_value_time (cfg, 2421 GNUNET_CONFIGURATION_get_value_time (cfg,
@@ -1640,9 +2446,39 @@ client_disconnect_cb (void *cls,
1640 struct GNUNET_SERVICE_Client *client, 2446 struct GNUNET_SERVICE_Client *client,
1641 void *app_ctx) 2447 void *app_ctx)
1642{ 2448{
2449 struct IdpClient *idp = app_ctx;
2450 struct AttributeIterator *ai;
2451 struct TicketIteration *ti;
2452 struct TicketRevocationHandle *rh;
2453
2454 //TODO other operations
2455
1643 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1644 "Client %p disconnected\n", 2457 "Client %p disconnected\n",
1645 client); 2458 client);
2459
2460 while (NULL != (ai = idp->op_head))
2461 {
2462 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2463 idp->op_tail,
2464 ai);
2465 GNUNET_free (ai);
2466 }
2467 while (NULL != (rh = idp->revocation_list_head))
2468 {
2469 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2470 idp->revocation_list_tail,
2471 rh);
2472 cleanup_revoke_ticket_handle (rh);
2473 }
2474 while (NULL != (ti = idp->ticket_iter_head))
2475 {
2476 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2477 idp->ticket_iter_tail,
2478 ti);
2479 cleanup_ticket_iter_handle (ti);
2480 }
2481 GNUNET_free (idp);
1646} 2482}
1647 2483
1648 2484
@@ -1659,10 +2495,14 @@ client_connect_cb (void *cls,
1659 struct GNUNET_SERVICE_Client *client, 2495 struct GNUNET_SERVICE_Client *client,
1660 struct GNUNET_MQ_Handle *mq) 2496 struct GNUNET_MQ_Handle *mq)
1661{ 2497{
2498 struct IdpClient *idp;
1662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1663 "Client %p connected\n", 2500 "Client %p connected\n",
1664 client); 2501 client);
1665 return client; 2502 idp = GNUNET_new (struct IdpClient);
2503 idp->client = client;
2504 idp->mq = mq;
2505 return idp;
1666} 2506}
1667 2507
1668 2508
@@ -1677,13 +2517,45 @@ GNUNET_SERVICE_MAIN
1677 &client_connect_cb, 2517 &client_connect_cb,
1678 &client_disconnect_cb, 2518 &client_disconnect_cb,
1679 NULL, 2519 NULL,
1680 GNUNET_MQ_hd_var_size (issue_message, 2520 GNUNET_MQ_hd_var_size (attribute_store_message,
1681 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE, 2521 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
1682 struct IssueMessage, 2522 struct AttributeStoreMessage,
2523 NULL),
2524 GNUNET_MQ_hd_fixed_size (iteration_start,
2525 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2526 struct AttributeIterationStartMessage,
2527 NULL),
2528 GNUNET_MQ_hd_fixed_size (iteration_next,
2529 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2530 struct AttributeIterationNextMessage,
2531 NULL),
2532 GNUNET_MQ_hd_fixed_size (iteration_stop,
2533 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2534 struct AttributeIterationStopMessage,
2535 NULL),
2536 GNUNET_MQ_hd_var_size (issue_ticket_message,
2537 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2538 struct IssueTicketMessage,
2539 NULL),
2540 GNUNET_MQ_hd_var_size (consume_ticket_message,
2541 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2542 struct ConsumeTicketMessage,
1683 NULL), 2543 NULL),
1684 GNUNET_MQ_hd_var_size (exchange_message, 2544 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1685 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE, 2545 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
1686 struct ExchangeMessage, 2546 struct TicketIterationStartMessage,
2547 NULL),
2548 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2549 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2550 struct TicketIterationNextMessage,
2551 NULL),
2552 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2553 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2554 struct TicketIterationStopMessage,
2555 NULL),
2556 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2557 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2558 struct RevokeTicketMessage,
1687 NULL), 2559 NULL),
1688 GNUNET_MQ_handler_end()); 2560 GNUNET_MQ_handler_end());
1689/* end of gnunet-service-identity-provider.c */ 2561/* end of gnunet-service-identity-provider.c */
diff --git a/src/identity-provider/identity-provider.conf b/src/identity-provider/identity-provider.conf
index bac8e69ed..7ee5e50d8 100644
--- a/src/identity-provider/identity-provider.conf
+++ b/src/identity-provider/identity-provider.conf
@@ -10,3 +10,7 @@ UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-identity-provider.sock
10UNIX_MATCH_UID = NO 10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES 11UNIX_MATCH_GID = YES
12TOKEN_EXPIRATION_INTERVAL = 30 m 12TOKEN_EXPIRATION_INTERVAL = 30 m
13DATABASE = sqlite
14
15[identity-provider-sqlite]
16FILENAME = $GNUNET_DATA_HOME/identity-provider/sqlite.db
diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h
index 6fe6102c8..b1fe6e1fd 100644
--- a/src/identity-provider/identity_provider.h
+++ b/src/identity-provider/identity_provider.h
@@ -34,34 +34,157 @@
34GNUNET_NETWORK_STRUCT_BEGIN 34GNUNET_NETWORK_STRUCT_BEGIN
35 35
36/** 36/**
37 * The token 37 * Use to store an identity attribute
38 */ 38 */
39struct GNUNET_IDENTITY_PROVIDER_Token 39struct AttributeStoreMessage
40{ 40{
41 /** 41 /**
42 * The JWT representation of the identity token 42 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
43 */
44 struct GNUNET_MessageHeader header;
45
46 /**
47 * Unique identifier for this request (for key collisions).
43 */ 48 */
44 char *data; 49 uint32_t id GNUNET_PACKED;
50
51 /**
52 * The length of the attribute
53 */
54 uint32_t attr_len GNUNET_PACKED;
55
56 /**
57 * Identity
58 */
59 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
60
61 /* followed by the serialized attribute */
62
45}; 63};
46 64
47/** 65/**
48 * The ticket 66 * Attribute store response message
49 */ 67 */
50struct GNUNET_IDENTITY_PROVIDER_Ticket 68struct AttributeStoreResultMessage
51{ 69{
52 /** 70 /**
53 * The Base64 representation of the ticket 71 * Message header
72 */
73 struct GNUNET_MessageHeader header;
74
75 /**
76 * Unique identifier for this request (for key collisions).
77 */
78 uint32_t id GNUNET_PACKED;
79
80 /**
81 * #GNUNET_SYSERR on failure, #GNUNET_OK on success
82 */
83 int32_t op_result GNUNET_PACKED;
84
85};
86
87/**
88 * Attribute is returned from the idp.
89 */
90struct AttributeResultMessage
91{
92 /**
93 * Message header
94 */
95 struct GNUNET_MessageHeader header;
96
97 /**
98 * Unique identifier for this request (for key collisions).
99 */
100 uint32_t id GNUNET_PACKED;
101
102 /**
103 * Length of serialized attribute data
104 */
105 uint16_t attr_len GNUNET_PACKED;
106
107 /**
108 * always zero (for alignment)
109 */
110 uint16_t reserved GNUNET_PACKED;
111
112 /**
113 * The public key of the identity.
114 */
115 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
116
117 /* followed by:
118 * serialized attribute data
119 */
120};
121
122
123/**
124 * Start a attribute iteration for the given identity
125 */
126struct AttributeIterationStartMessage
127{
128 /**
129 * Message
130 */
131 struct GNUNET_MessageHeader header;
132
133 /**
134 * Unique identifier for this request (for key collisions).
135 */
136 uint32_t id GNUNET_PACKED;
137
138 /**
139 * Identity.
140 */
141 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
142
143};
144
145
146/**
147 * Ask for next result of attribute iteration for the given operation
148 */
149struct AttributeIterationNextMessage
150{
151 /**
152 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT
153 */
154 struct GNUNET_MessageHeader header;
155
156 /**
157 * Unique identifier for this request (for key collisions).
158 */
159 uint32_t id GNUNET_PACKED;
160
161};
162
163
164/**
165 * Stop attribute iteration for the given operation
166 */
167struct AttributeIterationStopMessage
168{
169 /**
170 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP
171 */
172 struct GNUNET_MessageHeader header;
173
174 /**
175 * Unique identifier for this request (for key collisions).
54 */ 176 */
55 char *data; 177 uint32_t id GNUNET_PACKED;
178
56}; 179};
57 180
58/** 181/**
59 * Answer from service to client after issue operation 182 * Start a ticket iteration for the given identity
60 */ 183 */
61struct IssueResultMessage 184struct TicketIterationStartMessage
62{ 185{
63 /** 186 /**
64 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE 187 * Message
65 */ 188 */
66 struct GNUNET_MessageHeader header; 189 struct GNUNET_MessageHeader header;
67 190
@@ -70,18 +193,25 @@ struct IssueResultMessage
70 */ 193 */
71 uint32_t id GNUNET_PACKED; 194 uint32_t id GNUNET_PACKED;
72 195
73 /* followed by 0-terminated label,ticket,token */ 196 /**
197 * Identity.
198 */
199 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
74 200
201 /**
202 * Identity is audience or issuer
203 */
204 uint32_t is_audience GNUNET_PACKED;
75}; 205};
76 206
77 207
78/** 208/**
79 * Ticket exchange message. 209 * Ask for next result of ticket iteration for the given operation
80 */ 210 */
81struct ExchangeResultMessage 211struct TicketIterationNextMessage
82{ 212{
83 /** 213 /**
84 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE 214 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT
85 */ 215 */
86 struct GNUNET_MessageHeader header; 216 struct GNUNET_MessageHeader header;
87 217
@@ -90,25 +220,35 @@ struct ExchangeResultMessage
90 */ 220 */
91 uint32_t id GNUNET_PACKED; 221 uint32_t id GNUNET_PACKED;
92 222
223};
224
225
226/**
227 * Stop ticket iteration for the given operation
228 */
229struct TicketIterationStopMessage
230{
93 /** 231 /**
94 * Nonce found in ticket. NBO 232 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP
95 * 0 on error.
96 */ 233 */
97 uint64_t ticket_nonce GNUNET_PACKED; 234 struct GNUNET_MessageHeader header;
98 235
99 /* followed by 0-terminated token */ 236 /**
237 * Unique identifier for this request (for key collisions).
238 */
239 uint32_t id GNUNET_PACKED;
100 240
101}; 241};
102 242
103 243
104 244
105/** 245/**
106 * Client requests IdP to issue token. 246 * Ticket issue message
107 */ 247 */
108struct IssueMessage 248struct IssueTicketMessage
109{ 249{
110 /** 250 /**
111 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT 251 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET
112 */ 252 */
113 struct GNUNET_MessageHeader header; 253 struct GNUNET_MessageHeader header;
114 254
@@ -117,40 +257,98 @@ struct IssueMessage
117 */ 257 */
118 uint32_t id GNUNET_PACKED; 258 uint32_t id GNUNET_PACKED;
119 259
260 /**
261 * Identity.
262 */
263 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
120 264
121 /** 265 /**
122 * Issuer identity private key 266 * Requesting party.
123 */ 267 */
124 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key; 268 struct GNUNET_CRYPTO_EcdsaPublicKey rp;
125 269
126 /** 270 /**
127 * Audience public key 271 * length of serialized attribute list
128 */ 272 */
129 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 273 uint32_t attr_len GNUNET_PACKED;
130 274
275 //Followed by a serialized attribute list
276};
277
278/**
279 * Ticket revoke message
280 */
281struct RevokeTicketMessage
282{
131 /** 283 /**
132 * Nonce 284 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET
133 */ 285 */
134 uint64_t nonce; 286 struct GNUNET_MessageHeader header;
135 287
136 /** 288 /**
137 * Expiration of token in NBO. 289 * Unique identifier for this request (for key collisions).
138 */ 290 */
139 struct GNUNET_TIME_AbsoluteNBO expiration; 291 uint32_t id GNUNET_PACKED;
140 292
293 /**
294 * Identity.
295 */
296 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
141 297
142 /* followed by 0-terminated comma-separated scope list */ 298 /**
299 * length of serialized attribute list
300 */
301 uint32_t attrs_len GNUNET_PACKED;
143 302
303 //Followed by a ticket and serialized attribute list
304};
305
306/**
307 * Ticket revoke message
308 */
309struct RevokeTicketResultMessage
310{
311 /**
312 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
313 */
314 struct GNUNET_MessageHeader header;
315
316 /**
317 * Unique identifier for this request (for key collisions).
318 */
319 uint32_t id GNUNET_PACKED;
320
321 /**
322 * Revocation result
323 */
324 uint32_t success GNUNET_PACKED;
144}; 325};
145 326
146 327
147/** 328/**
148 * Use to exchange a ticket for a token 329 * Ticket result message
149 */ 330 */
150struct ExchangeMessage 331struct TicketResultMessage
151{ 332{
152 /** 333 /**
153 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT 334 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
335 */
336 struct GNUNET_MessageHeader header;
337
338 /**
339 * Unique identifier for this request (for key collisions).
340 */
341 uint32_t id GNUNET_PACKED;
342
343};
344
345/**
346 * Ticket consume message
347 */
348struct ConsumeTicketMessage
349{
350 /**
351 * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET
154 */ 352 */
155 struct GNUNET_MessageHeader header; 353 struct GNUNET_MessageHeader header;
156 354
@@ -160,15 +358,50 @@ struct ExchangeMessage
160 uint32_t id GNUNET_PACKED; 358 uint32_t id GNUNET_PACKED;
161 359
162 /** 360 /**
163 * Audience identity private key 361 * Identity.
362 */
363 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
364
365 //Followed by a serialized ticket
366};
367
368/**
369 * Attribute list is returned from the idp.
370 */
371struct ConsumeTicketResultMessage
372{
373 /**
374 * Message header
375 */
376 struct GNUNET_MessageHeader header;
377
378 /**
379 * Unique identifier for this request (for key collisions).
380 */
381 uint32_t id GNUNET_PACKED;
382
383 /**
384 * Length of serialized attribute data
164 */ 385 */
165 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey; 386 uint16_t attrs_len GNUNET_PACKED;
166 387
167 /* followed by 0-terminated ticket string */ 388 /**
389 * always zero (for alignment)
390 */
391 uint16_t reserved GNUNET_PACKED;
168 392
393 /**
394 * The public key of the identity.
395 */
396 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
397
398 /* followed by:
399 * serialized attributes data
400 */
169}; 401};
170 402
171 403
404
172GNUNET_NETWORK_STRUCT_END 405GNUNET_NETWORK_STRUCT_END
173 406
174#endif 407#endif
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c
index 845d1f753..d0ece80fe 100644
--- a/src/identity-provider/identity_provider_api.c
+++ b/src/identity-provider/identity_provider_api.c
@@ -29,12 +29,12 @@
29#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "gnunet_mq_lib.h" 30#include "gnunet_mq_lib.h"
31#include "gnunet_identity_provider_service.h" 31#include "gnunet_identity_provider_service.h"
32#include "gnunet_identity_attribute_lib.h"
32#include "identity_provider.h" 33#include "identity_provider.h"
33 34
34#define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) 35#define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__)
35 36
36 37
37
38/** 38/**
39 * Handle for an operation with the service. 39 * Handle for an operation with the service.
40 */ 40 */
@@ -63,16 +63,24 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
63 const struct GNUNET_MessageHeader *msg; 63 const struct GNUNET_MessageHeader *msg;
64 64
65 /** 65 /**
66 * Continuation to invoke with the result of the transmission; @e cb 66 * Continuation to invoke after attribute store call
67 * will be NULL in this case. 67 */
68 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb;
69
70 /**
71 * Attribute result callback
72 */
73 GNUNET_IDENTITY_PROVIDER_AttributeResult ar_cb;
74
75 /**
76 * Revocation result callback
68 */ 77 */
69 GNUNET_IDENTITY_PROVIDER_ExchangeCallback ex_cb; 78 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus rvk_cb;
70 79
71 /** 80 /**
72 * Continuation to invoke with the result of the transmission for 81 * Ticket result callback
73 * 'issue' operations (@e cont will be NULL in this case).
74 */ 82 */
75 GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb; 83 GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
76 84
77 /** 85 /**
78 * Envelope with the message for this queue entry. 86 * Envelope with the message for this queue entry.
@@ -91,6 +99,140 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
91 99
92}; 100};
93 101
102/**
103 * Handle for a ticket iterator operation
104 */
105struct GNUNET_IDENTITY_PROVIDER_TicketIterator
106{
107
108 /**
109 * Kept in a DLL.
110 */
111 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *next;
112
113 /**
114 * Kept in a DLL.
115 */
116 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *prev;
117
118 /**
119 * Main handle to access the idp.
120 */
121 struct GNUNET_IDENTITY_PROVIDER_Handle *h;
122
123 /**
124 * Function to call on completion.
125 */
126 GNUNET_SCHEDULER_TaskCallback finish_cb;
127
128 /**
129 * Closure for @e error_cb.
130 */
131 void *finish_cb_cls;
132
133 /**
134 * The continuation to call with the results
135 */
136 GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
137
138 /**
139 * Closure for @e tr_cb.
140 */
141 void *cls;
142
143 /**
144 * Function to call on errors.
145 */
146 GNUNET_SCHEDULER_TaskCallback error_cb;
147
148 /**
149 * Closure for @e error_cb.
150 */
151 void *error_cb_cls;
152
153 /**
154 * Envelope of the message to send to the service, if not yet
155 * sent.
156 */
157 struct GNUNET_MQ_Envelope *env;
158
159 /**
160 * The operation id this zone iteration operation has
161 */
162 uint32_t r_id;
163
164};
165
166
167/**
168 * Handle for a attribute iterator operation
169 */
170struct GNUNET_IDENTITY_PROVIDER_AttributeIterator
171{
172
173 /**
174 * Kept in a DLL.
175 */
176 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next;
177
178 /**
179 * Kept in a DLL.
180 */
181 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev;
182
183 /**
184 * Main handle to access the idp.
185 */
186 struct GNUNET_IDENTITY_PROVIDER_Handle *h;
187
188 /**
189 * Function to call on completion.
190 */
191 GNUNET_SCHEDULER_TaskCallback finish_cb;
192
193 /**
194 * Closure for @e error_cb.
195 */
196 void *finish_cb_cls;
197
198 /**
199 * The continuation to call with the results
200 */
201 GNUNET_IDENTITY_PROVIDER_AttributeResult proc;
202
203 /**
204 * Closure for @e proc.
205 */
206 void *proc_cls;
207
208 /**
209 * Function to call on errors.
210 */
211 GNUNET_SCHEDULER_TaskCallback error_cb;
212
213 /**
214 * Closure for @e error_cb.
215 */
216 void *error_cb_cls;
217
218 /**
219 * Envelope of the message to send to the service, if not yet
220 * sent.
221 */
222 struct GNUNET_MQ_Envelope *env;
223
224 /**
225 * Private key of the zone.
226 */
227 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
228
229 /**
230 * The operation id this zone iteration operation has
231 */
232 uint32_t r_id;
233
234};
235
94 236
95/** 237/**
96 * Handle for the service. 238 * Handle for the service.
@@ -123,6 +265,27 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
123 struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail; 265 struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail;
124 266
125 /** 267 /**
268 * Head of active iterations
269 */
270 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head;
271
272 /**
273 * Tail of active iterations
274 */
275 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail;
276
277 /**
278 * Head of active iterations
279 */
280 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_head;
281
282 /**
283 * Tail of active iterations
284 */
285 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_tail;
286
287
288 /**
126 * Currently pending transmission request, or NULL for none. 289 * Currently pending transmission request, or NULL for none.
127 */ 290 */
128 struct GNUNET_CLIENT_TransmitHandle *th; 291 struct GNUNET_CLIENT_TransmitHandle *th;
@@ -154,14 +317,13 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
154 317
155}; 318};
156 319
157
158/** 320/**
159 * Try again to connect to the service. 321 * Try again to connect to the service.
160 * 322 *
161 * @param cls handle to the service. 323 * @param h handle to the identity provider service.
162 */ 324 */
163static void 325static void
164reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle); 326reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
165 327
166/** 328/**
167 * Reconnect 329 * Reconnect
@@ -181,7 +343,7 @@ reconnect_task (void *cls)
181/** 343/**
182 * Disconnect from service and then reconnect. 344 * Disconnect from service and then reconnect.
183 * 345 *
184 * @param handle our handle 346 * @param handle our service
185 */ 347 */
186static void 348static void
187force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle) 349force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
@@ -197,6 +359,26 @@ force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
197} 359}
198 360
199/** 361/**
362 * Free @a it.
363 *
364 * @param it entry to free
365 */
366static void
367free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
368{
369 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
370
371 GNUNET_CONTAINER_DLL_remove (h->it_head,
372 h->it_tail,
373 it);
374 if (NULL != it->env)
375 GNUNET_MQ_discard (it->env);
376 GNUNET_free (it);
377}
378
379
380
381/**
200 * Generic error handler, called with the appropriate error code and 382 * Generic error handler, called with the appropriate error code and
201 * the same closure specified at the creation of the message queue. 383 * the same closure specified at the creation of the message queue.
202 * Not every message queue implementation supports an error handler. 384 * Not every message queue implementation supports an error handler.
@@ -213,22 +395,68 @@ mq_error_handler (void *cls,
213} 395}
214 396
215/** 397/**
216 * Check validity of message received from the service 398 * Handle an incoming message of type
399 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
400 *
401 * @param cls
402 * @param msg the message we received
403 */
404static void
405handle_attribute_store_response (void *cls,
406 const struct AttributeStoreResultMessage *msg)
407{
408 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
409 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
410 uint32_t r_id = ntohl (msg->id);
411 int res;
412 const char *emsg;
413
414 for (op = h->op_head; NULL != op; op = op->next)
415 if (op->r_id == r_id)
416 break;
417 if (NULL == op)
418 return;
419
420 res = ntohl (msg->op_result);
421 LOG (GNUNET_ERROR_TYPE_DEBUG,
422 "Received ATTRIBUTE_STORE_RESPONSE with result %d\n",
423 res);
424
425 /* TODO: add actual error message to response... */
426 if (GNUNET_SYSERR == res)
427 emsg = _("failed to store record\n");
428 else
429 emsg = NULL;
430 if (NULL != op->as_cb)
431 op->as_cb (op->cls,
432 res,
433 emsg);
434 GNUNET_CONTAINER_DLL_remove (h->op_head,
435 h->op_tail,
436 op);
437 GNUNET_free (op);
438
439}
440
441
442/**
443 * Handle an incoming message of type
444 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
217 * 445 *
218 * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` 446 * @param cls
219 * @param result_msg the incoming message 447 * @param msg the message we received
448 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
220 */ 449 */
221static int 450static int
222check_exchange_result (void *cls, 451check_consume_ticket_result (void *cls,
223 const struct ExchangeResultMessage *erm) 452 const struct ConsumeTicketResultMessage *msg)
224{ 453{
225 char *str; 454 size_t msg_len;
226 size_t size = ntohs (erm->header.size) - sizeof (*erm); 455 size_t attrs_len;
227
228 456
229 str = (char *) &erm[1]; 457 msg_len = ntohs (msg->header.size);
230 if ( (size > sizeof (struct ExchangeResultMessage)) && 458 attrs_len = ntohs (msg->attrs_len);
231 ('\0' != str[size - sizeof (struct ExchangeResultMessage) - 1]) ) 459 if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len)
232 { 460 {
233 GNUNET_break (0); 461 GNUNET_break (0);
234 return GNUNET_SYSERR; 462 return GNUNET_SYSERR;
@@ -238,20 +466,85 @@ check_exchange_result (void *cls,
238 466
239 467
240/** 468/**
241 * Check validity of message received from the service 469 * Handle an incoming message of type
470 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
471 *
472 * @param cls
473 * @param msg the message we received
474 */
475static void
476handle_consume_ticket_result (void *cls,
477 const struct ConsumeTicketResultMessage *msg)
478{
479 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
480 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
481 size_t attrs_len;
482 uint32_t r_id = ntohl (msg->id);
483
484 attrs_len = ntohs (msg->attrs_len);
485 LOG (GNUNET_ERROR_TYPE_DEBUG,
486 "Processing attribute result.\n");
487
488
489 for (op = h->op_head; NULL != op; op = op->next)
490 if (op->r_id == r_id)
491 break;
492 if (NULL == op)
493 return;
494
495 {
496 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
497 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
498 attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1],
499 attrs_len);
500 if (NULL != op->ar_cb)
501 {
502 if (NULL == attrs)
503 {
504 op->ar_cb (op->cls,
505 &msg->identity,
506 NULL);
507 }
508 else
509 {
510 for (le = attrs->list_head; NULL != le; le = le->next)
511 op->ar_cb (op->cls,
512 &msg->identity,
513 le->claim);
514 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
515 }
516 }
517 op->ar_cb (op->cls,
518 NULL,
519 NULL);
520 GNUNET_CONTAINER_DLL_remove (h->op_head,
521 h->op_tail,
522 op);
523 GNUNET_free (op);
524 return;
525 }
526 GNUNET_assert (0);
527}
528
529
530/**
531 * Handle an incoming message of type
532 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
242 * 533 *
243 * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` 534 * @param cls
244 * @param result_msg the incoming message 535 * @param msg the message we received
536 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
245 */ 537 */
246static int 538static int
247check_result (void *cls, 539check_attribute_result (void *cls,
248 const struct IssueResultMessage *irm) 540 const struct AttributeResultMessage *msg)
249{ 541{
250 char *str; 542 size_t msg_len;
251 size_t size = ntohs (irm->header.size) - sizeof (*irm); 543 size_t attr_len;
252 str = (char*) &irm[1]; 544
253 if ( (size > sizeof (struct IssueResultMessage)) && 545 msg_len = ntohs (msg->header.size);
254 ('\0' != str[size - sizeof (struct IssueResultMessage) - 1]) ) 546 attr_len = ntohs (msg->attr_len);
547 if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
255 { 548 {
256 GNUNET_break (0); 549 GNUNET_break (0);
257 return GNUNET_SYSERR; 550 return GNUNET_SYSERR;
@@ -259,119 +552,254 @@ check_result (void *cls,
259 return GNUNET_OK; 552 return GNUNET_OK;
260} 553}
261 554
555
262/** 556/**
263 * Handler for messages received from the GNS service 557 * Handle an incoming message of type
558 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
264 * 559 *
265 * @param cls the `struct GNUNET_GNS_Handle *` 560 * @param cls
266 * @param loookup_msg the incoming message 561 * @param msg the message we received
267 */ 562 */
268static void 563static void
269handle_exchange_result (void *cls, 564handle_attribute_result (void *cls,
270 const struct ExchangeResultMessage *erm) 565 const struct AttributeResultMessage *msg)
271{ 566{
272 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; 567 static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
568 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
569 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
273 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 570 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
274 struct GNUNET_IDENTITY_PROVIDER_Token token; 571 size_t attr_len;
275 uint64_t ticket_nonce; 572 uint32_t r_id = ntohl (msg->id);
276 uint32_t r_id = ntohl (erm->id); 573
277 char *str; 574 attr_len = ntohs (msg->attr_len);
278 575 LOG (GNUNET_ERROR_TYPE_DEBUG,
279 for (op = handle->op_head; NULL != op; op = op->next) 576 "Processing attribute result.\n");
577
578
579 for (it = h->it_head; NULL != it; it = it->next)
580 if (it->r_id == r_id)
581 break;
582 for (op = h->op_head; NULL != op; op = op->next)
280 if (op->r_id == r_id) 583 if (op->r_id == r_id)
281 break; 584 break;
282 if (NULL == op) 585 if ((NULL == it) && (NULL == op))
283 return; 586 return;
284 str = GNUNET_strdup ((char*)&erm[1]);
285 op = handle->op_head;
286 GNUNET_CONTAINER_DLL_remove (handle->op_head,
287 handle->op_tail,
288 op);
289 token.data = str;
290 ticket_nonce = ntohl (erm->ticket_nonce);
291 if (NULL != op->ex_cb)
292 op->ex_cb (op->cls, &token, ticket_nonce);
293 GNUNET_free (str);
294 GNUNET_free (op);
295 587
588 if ( (0 == (memcmp (&msg->identity,
589 &identity_dummy,
590 sizeof (identity_dummy)))) )
591 {
592 if ((NULL == it) && (NULL == op))
593 {
594 GNUNET_break (0);
595 force_reconnect (h);
596 return;
597 }
598 if (NULL != it)
599 {
600 if (NULL != it->finish_cb)
601 it->finish_cb (it->finish_cb_cls);
602 free_it (it);
603 }
604 if (NULL != op)
605 {
606 if (NULL != op->ar_cb)
607 op->ar_cb (op->cls,
608 NULL,
609 NULL);
610 GNUNET_CONTAINER_DLL_remove (h->op_head,
611 h->op_tail,
612 op);
613 GNUNET_free (op);
614
615 }
616 return;
617 }
618
619 {
620 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
621 attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1],
622 attr_len);
623 if (NULL != it)
624 {
625 if (NULL != it->proc)
626 it->proc (it->proc_cls,
627 &msg->identity,
628 attr);
629 } else if (NULL != op)
630 {
631 if (NULL != op->ar_cb)
632 op->ar_cb (op->cls,
633 &msg->identity,
634 attr);
635
636 }
637 GNUNET_free (attr);
638 return;
639 }
640 GNUNET_assert (0);
641}
642
643/**
644 * Handle an incoming message of type
645 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
646 *
647 * @param cls
648 * @param msg the message we received
649 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
650 */
651static int
652check_ticket_result (void *cls,
653 const struct TicketResultMessage *msg)
654{
655 size_t msg_len;
656
657 msg_len = ntohs (msg->header.size);
658 if (msg_len < sizeof (struct TicketResultMessage))
659 {
660 GNUNET_break (0);
661 return GNUNET_SYSERR;
662 }
663 return GNUNET_OK;
296} 664}
297 665
666
667
298/** 668/**
299 * Handler for messages received from the GNS service 669 * Handle an incoming message of type
670 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
300 * 671 *
301 * @param cls the `struct GNUNET_GNS_Handle *` 672 * @param cls
302 * @param loookup_msg the incoming message 673 * @param msg the message we received
303 */ 674 */
304static void 675static void
305handle_result (void *cls, 676handle_ticket_result (void *cls,
306 const struct IssueResultMessage *irm) 677 const struct TicketResultMessage *msg)
307{ 678{
308 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; 679 struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
309 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 680 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
310 struct GNUNET_IDENTITY_PROVIDER_Token token; 681 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
311 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; 682 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
312 uint32_t r_id = ntohl (irm->id); 683 uint32_t r_id = ntohl (msg->id);
313 char *str; 684 size_t msg_len;
314 char *label_str;
315 char *ticket_str;
316 char *token_str;
317 685
318 for (op = handle->op_head; NULL != op; op = op->next) 686 for (op = handle->op_head; NULL != op; op = op->next)
319 if (op->r_id == r_id) 687 if (op->r_id == r_id)
320 break; 688 break;
321 if (NULL == op) 689 for (it = handle->ticket_it_head; NULL != it; it = it->next)
690 if (it->r_id == r_id)
691 break;
692 if ((NULL == op) && (NULL == it))
322 return; 693 return;
323 str = GNUNET_strdup ((char*)&irm[1]); 694 msg_len = ntohs (msg->header.size);
324 label_str = strtok (str, ","); 695 if (NULL != op)
325
326 if (NULL == label_str)
327 { 696 {
328 GNUNET_free (str); 697 GNUNET_CONTAINER_DLL_remove (handle->op_head,
329 GNUNET_break (0); 698 handle->op_tail,
699 op);
700 if (msg_len == sizeof (struct TicketResultMessage))
701 {
702 if (NULL != op->tr_cb)
703 op->tr_cb (op->cls, NULL);
704 } else {
705 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
706 if (NULL != op->tr_cb)
707 op->tr_cb (op->cls, ticket);
708 }
709 GNUNET_free (op);
330 return; 710 return;
331 } 711 } else if (NULL != it) {
332 ticket_str = strtok (NULL, ","); 712 if (msg_len == sizeof (struct TicketResultMessage))
333 if (NULL == ticket_str) 713 {
334 { 714 if (NULL != it->tr_cb)
335 GNUNET_free (str); 715 GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
336 GNUNET_break (0); 716 handle->ticket_it_tail,
717 it);
718 it->finish_cb (it->finish_cb_cls);
719 GNUNET_free (it);
720 } else {
721 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
722 if (NULL != it->tr_cb)
723 it->tr_cb (it->cls, ticket);
724 }
337 return; 725 return;
338 } 726 }
339 token_str = strtok (NULL, ","); 727 GNUNET_break (0);
340 if (NULL == token_str) 728}
729
730/**
731 * Handle an incoming message of type
732 * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
733 *
734 * @param cls
735 * @param msg the message we received
736 */
737static void
738handle_revoke_ticket_result (void *cls,
739 const struct RevokeTicketResultMessage *msg)
740{
741 struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
742 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
743 uint32_t r_id = ntohl (msg->id);
744 int32_t success;
745
746 LOG (GNUNET_ERROR_TYPE_DEBUG,
747 "Processing revocation result.\n");
748
749
750 for (op = h->op_head; NULL != op; op = op->next)
751 if (op->r_id == r_id)
752 break;
753 if (NULL == op)
754 return;
755 success = ntohl (msg->success);
341 { 756 {
342 GNUNET_free (str); 757 if (NULL != op->rvk_cb)
343 GNUNET_break (0); 758 {
759 op->rvk_cb (op->cls,
760 success,
761 NULL);
762 }
763 GNUNET_CONTAINER_DLL_remove (h->op_head,
764 h->op_tail,
765 op);
766 GNUNET_free (op);
344 return; 767 return;
345 } 768 }
346 GNUNET_CONTAINER_DLL_remove (handle->op_head, 769 GNUNET_assert (0);
347 handle->op_tail,
348 op);
349 ticket.data = ticket_str;
350 token.data = token_str;
351 if (NULL != op->iss_cb)
352 op->iss_cb (op->cls, label_str, &ticket, &token);
353 GNUNET_free (str);
354 GNUNET_free (op);
355
356} 770}
357 771
772
773
358/** 774/**
359 * Try again to connect to the service. 775 * Try again to connect to the service.
360 * 776 *
361 * @param cls handle to the identity provider service. 777 * @param h handle to the identity provider service.
362 */ 778 */
363static void 779static void
364reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) 780reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
365{ 781{
366 struct GNUNET_MQ_MessageHandler handlers[] = { 782 struct GNUNET_MQ_MessageHandler handlers[] = {
367 GNUNET_MQ_hd_var_size (result, 783 GNUNET_MQ_hd_fixed_size (attribute_store_response,
368 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT, 784 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE,
369 struct IssueResultMessage, 785 struct AttributeStoreResultMessage,
786 h),
787 GNUNET_MQ_hd_var_size (attribute_result,
788 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT,
789 struct AttributeResultMessage,
370 h), 790 h),
371 GNUNET_MQ_hd_var_size (exchange_result, 791 GNUNET_MQ_hd_var_size (ticket_result,
372 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT, 792 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT,
373 struct ExchangeResultMessage, 793 struct TicketResultMessage,
374 h), 794 h),
795 GNUNET_MQ_hd_var_size (consume_ticket_result,
796 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT,
797 struct ConsumeTicketResultMessage,
798 h),
799 GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
800 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT,
801 struct RevokeTicketResultMessage,
802 h),
375 GNUNET_MQ_handler_end () 803 GNUNET_MQ_handler_end ()
376 }; 804 };
377 struct GNUNET_IDENTITY_PROVIDER_Operation *op; 805 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
@@ -417,111 +845,6 @@ GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
417 845
418 846
419/** 847/**
420 * Issue an identity token
421 *
422 * @param id identity service to query
423 * @param service_name for which service is an identity wanted
424 * @param cb function to call with the result (will only be called once)
425 * @param cb_cls closure for @a cb
426 * @return handle to abort the operation
427 */
428struct GNUNET_IDENTITY_PROVIDER_Operation *
429GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
430 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
431 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
432 const char* scopes,
433 struct GNUNET_TIME_Absolute expiration,
434 uint64_t nonce,
435 GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
436 void *cb_cls)
437{
438 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
439 struct IssueMessage *im;
440 size_t slen;
441
442 slen = strlen (scopes) + 1;
443 if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct IssueMessage))
444 {
445 GNUNET_break (0);
446 return NULL;
447 }
448 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
449 op->h = id;
450 op->iss_cb = cb;
451 op->cls = cb_cls;
452 op->r_id = id->r_id_gen++;
453 op->env = GNUNET_MQ_msg_extra (im,
454 slen,
455 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE);
456 im->id = op->r_id;
457 im->iss_key = *iss_key;
458 im->aud_key = *aud_key;
459 im->nonce = htonl (nonce);
460 im->expiration = GNUNET_TIME_absolute_hton (expiration);
461 GNUNET_memcpy (&im[1], scopes, slen);
462 GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
463 id->op_tail,
464 op);
465 if (NULL != id->mq)
466 GNUNET_MQ_send_copy (id->mq,
467 op->env);
468 return op;
469}
470
471
472/**
473 * Exchange a token ticket for a token
474 *
475 * @param id identity provider service
476 * @param ticket ticket to exchange
477 * @param cont function to call once the operation finished
478 * @param cont_cls closure for @a cont
479 * @return handle to abort the operation
480 */
481struct GNUNET_IDENTITY_PROVIDER_Operation *
482GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
483 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
484 const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey,
485 GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
486 void *cont_cls)
487{
488 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
489 struct ExchangeMessage *em;
490 size_t slen;
491 char *ticket_str;
492
493 ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
494
495 slen = strlen (ticket_str) + 1;
496 if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct ExchangeMessage))
497 {
498 GNUNET_free (ticket_str);
499 GNUNET_break (0);
500 return NULL;
501 }
502 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
503 op->h = id;
504 op->ex_cb = cont;
505 op->cls = cont_cls;
506 op->r_id = id->r_id_gen++;
507 op->env = GNUNET_MQ_msg_extra (em,
508 slen,
509 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE);
510 em->aud_privkey = *aud_privkey;
511 em->id = htonl (op->r_id);
512 GNUNET_memcpy (&em[1], ticket_str, slen);
513 GNUNET_free (ticket_str);
514 GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
515 id->op_tail,
516 op);
517 if (NULL != id->mq)
518 GNUNET_MQ_send_copy (id->mq,
519 op->env);
520 return op;
521}
522
523
524/**
525 * Cancel an operation. Note that the operation MAY still 848 * Cancel an operation. Note that the operation MAY still
526 * be executed; this merely cancels the continuation; if the request 849 * be executed; this merely cancels the continuation; if the request
527 * was already transmitted, the service may still choose to complete 850 * was already transmitted, the service may still choose to complete
@@ -566,80 +889,482 @@ GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
566} 889}
567 890
568/** 891/**
569 * Convenience API 892 * Store an attribute. If the attribute is already present,
893 * it is replaced with the new attribute.
894 *
895 * @param h handle to the identity provider
896 * @param pkey private key of the identity
897 * @param attr the attribute value
898 * @param cont continuation to call when done
899 * @param cont_cls closure for @a cont
900 * @return handle to abort the request
570 */ 901 */
902struct GNUNET_IDENTITY_PROVIDER_Operation *
903GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
904 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
905 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
906 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
907 void *cont_cls)
908{
909 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
910 struct AttributeStoreMessage *sam;
911 size_t attr_len;
912
913 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
914 op->h = h;
915 op->as_cb = cont;
916 op->cls = cont_cls;
917 op->r_id = h->r_id_gen++;
918 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
919 h->op_tail,
920 op);
921 attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr);
922 op->env = GNUNET_MQ_msg_extra (sam,
923 attr_len,
924 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE);
925 sam->identity = *pkey;
926 sam->id = htonl (op->r_id);
927
928 GNUNET_IDENTITY_ATTRIBUTE_serialize (attr,
929 (char*)&sam[1]);
930
931 sam->attr_len = htons (attr_len);
932 if (NULL != h->mq)
933 GNUNET_MQ_send_copy (h->mq,
934 op->env);
935 return op;
936
937}
938
939
940/**
941 * List all attributes for a local identity.
942 * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
943 * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
944 * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
945 * immediately, and then again after
946 * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
947 *
948 * On error (disconnect), @a error_cb will be invoked.
949 * On normal completion, @a finish_cb proc will be
950 * invoked.
951 *
952 * @param h handle to the idp
953 * @param identity identity to access
954 * @param error_cb function to call on error (i.e. disconnect),
955 * the handle is afterwards invalid
956 * @param error_cb_cls closure for @a error_cb
957 * @param proc function to call on each attribute; it
958 * will be called repeatedly with a value (if available)
959 * @param proc_cls closure for @a proc
960 * @param finish_cb function to call on completion
961 * the handle is afterwards invalid
962 * @param finish_cb_cls closure for @a finish_cb
963 * @return an iterator handle to use for iteration
964 */
965struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
966GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
967 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
968 GNUNET_SCHEDULER_TaskCallback error_cb,
969 void *error_cb_cls,
970 GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
971 void *proc_cls,
972 GNUNET_SCHEDULER_TaskCallback finish_cb,
973 void *finish_cb_cls)
974{
975 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
976 struct GNUNET_MQ_Envelope *env;
977 struct AttributeIterationStartMessage *msg;
978 uint32_t rid;
979
980 rid = h->r_id_gen++;
981 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator);
982 it->h = h;
983 it->error_cb = error_cb;
984 it->error_cb_cls = error_cb_cls;
985 it->finish_cb = finish_cb;
986 it->finish_cb_cls = finish_cb_cls;
987 it->proc = proc;
988 it->proc_cls = proc_cls;
989 it->r_id = rid;
990 it->identity = *identity;
991 GNUNET_CONTAINER_DLL_insert_tail (h->it_head,
992 h->it_tail,
993 it);
994 env = GNUNET_MQ_msg (msg,
995 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START);
996 msg->id = htonl (rid);
997 msg->identity = *identity;
998 if (NULL == h->mq)
999 it->env = env;
1000 else
1001 GNUNET_MQ_send (h->mq,
1002 env);
1003 return it;
1004}
571 1005
572 1006
573/** 1007/**
574 * Destroy token 1008 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
1009 * for the next record.
575 * 1010 *
576 * @param token the token 1011 * @param it the iterator
577 */ 1012 */
578void 1013void
579GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token) 1014GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
1015{
1016 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
1017 struct AttributeIterationNextMessage *msg;
1018 struct GNUNET_MQ_Envelope *env;
1019
1020 env = GNUNET_MQ_msg (msg,
1021 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT);
1022 msg->id = htonl (it->r_id);
1023 GNUNET_MQ_send (h->mq,
1024 env);
1025}
1026
1027
1028/**
1029 * Stops iteration and releases the idp handle for further calls. Must
1030 * be called on any iteration that has not yet completed prior to calling
1031 * #GNUNET_IDENTITY_PROVIDER_disconnect.
1032 *
1033 * @param it the iterator
1034 */
1035void
1036GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
1037{
1038 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
1039 struct GNUNET_MQ_Envelope *env;
1040 struct AttributeIterationStopMessage *msg;
1041
1042 if (NULL != h->mq)
1043 {
1044 env = GNUNET_MQ_msg (msg,
1045 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP);
1046 msg->id = htonl (it->r_id);
1047 GNUNET_MQ_send (h->mq,
1048 env);
1049 }
1050 free_it (it);
1051}
1052
1053
1054/** TODO
1055 * Issues a ticket to another identity. The identity may use
1056 * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
1057 * and retrieve the attributes specified in the AttributeList.
1058 *
1059 * @param h the identity provider to use
1060 * @param iss the issuing identity
1061 * @param rp the subject of the ticket (the relying party)
1062 * @param attrs the attributes that the relying party is given access to
1063 * @param cb the callback
1064 * @param cb_cls the callback closure
1065 * @return handle to abort the operation
1066 */
1067struct GNUNET_IDENTITY_PROVIDER_Operation *
1068GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1069 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
1070 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
1071 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
1072 GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
1073 void *cb_cls)
1074{
1075 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
1076 struct IssueTicketMessage *tim;
1077 size_t attr_len;
1078
1079 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1080 op->h = h;
1081 op->tr_cb = cb;
1082 op->cls = cb_cls;
1083 op->r_id = h->r_id_gen++;
1084 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1085 h->op_tail,
1086 op);
1087 attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
1088 op->env = GNUNET_MQ_msg_extra (tim,
1089 attr_len,
1090 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET);
1091 tim->identity = *iss;
1092 tim->rp = *rp;
1093 tim->id = htonl (op->r_id);
1094
1095 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
1096 (char*)&tim[1]);
1097
1098 tim->attr_len = htons (attr_len);
1099 if (NULL != h->mq)
1100 GNUNET_MQ_send_copy (h->mq,
1101 op->env);
1102 return op;
1103}
1104
1105/**
1106 * Consumes an issued ticket. The ticket is persisted
1107 * and used to retrieve identity information from the issuer
1108 *
1109 * @param h the identity provider to use
1110 * @param identity the identity that is the subject of the issued ticket (the relying party)
1111 * @param ticket the issued ticket to consume
1112 * @param cb the callback to call
1113 * @param cb_cls the callback closure
1114 * @return handle to abort the operation
1115 */
1116struct GNUNET_IDENTITY_PROVIDER_Operation *
1117GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1118 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1119 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1120 GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
1121 void *cb_cls)
580{ 1122{
581 GNUNET_assert (NULL != token); 1123 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
582 if (NULL != token->data) 1124 struct ConsumeTicketMessage *ctm;
583 GNUNET_free (token->data); 1125
584 GNUNET_free (token); 1126 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1127 op->h = h;
1128 op->ar_cb = cb;
1129 op->cls = cb_cls;
1130 op->r_id = h->r_id_gen++;
1131 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1132 h->op_tail,
1133 op);
1134 op->env = GNUNET_MQ_msg_extra (ctm,
1135 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket),
1136 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET);
1137 ctm->identity = *identity;
1138 ctm->id = htonl (op->r_id);
1139
1140 GNUNET_memcpy ((char*)&ctm[1],
1141 ticket,
1142 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket));
1143
1144 if (NULL != h->mq)
1145 GNUNET_MQ_send_copy (h->mq,
1146 op->env);
1147 return op;
1148
585} 1149}
586 1150
1151
587/** 1152/**
588 * Returns string representation of token. A JSON-Web-Token. 1153 * Lists all tickets that have been issued to remote
1154 * identites (relying parties)
589 * 1155 *
590 * @param token the token 1156 * @param h the identity provider to use
591 * @return The JWT (must be freed) 1157 * @param identity the issuing identity
1158 * @param error_cb function to call on error (i.e. disconnect),
1159 * the handle is afterwards invalid
1160 * @param error_cb_cls closure for @a error_cb
1161 * @param proc function to call on each ticket; it
1162 * will be called repeatedly with a value (if available)
1163 * @param proc_cls closure for @a proc
1164 * @param finish_cb function to call on completion
1165 * the handle is afterwards invalid
1166 * @param finish_cb_cls closure for @a finish_cb
1167 * @return an iterator handle to use for iteration
592 */ 1168 */
593char * 1169struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
594GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token) 1170GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1171 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1172 GNUNET_SCHEDULER_TaskCallback error_cb,
1173 void *error_cb_cls,
1174 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
1175 void *proc_cls,
1176 GNUNET_SCHEDULER_TaskCallback finish_cb,
1177 void *finish_cb_cls)
595{ 1178{
596 return GNUNET_strdup (token->data); 1179 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
1180 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
1181 struct GNUNET_MQ_Envelope *env;
1182 struct TicketIterationStartMessage *msg;
1183 uint32_t rid;
1184
1185 GNUNET_CRYPTO_ecdsa_key_get_public (identity,
1186 &identity_pub);
1187 rid = h->r_id_gen++;
1188 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
1189 it->h = h;
1190 it->error_cb = error_cb;
1191 it->error_cb_cls = error_cb_cls;
1192 it->finish_cb = finish_cb;
1193 it->finish_cb_cls = finish_cb_cls;
1194 it->tr_cb = proc;
1195 it->cls = proc_cls;
1196 it->r_id = rid;
1197 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
1198 h->ticket_it_tail,
1199 it);
1200 env = GNUNET_MQ_msg (msg,
1201 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
1202 msg->id = htonl (rid);
1203 msg->identity = identity_pub;
1204 msg->is_audience = htonl (GNUNET_NO);
1205 if (NULL == h->mq)
1206 it->env = env;
1207 else
1208 GNUNET_MQ_send (h->mq,
1209 env);
1210 return it;
1211
597} 1212}
598 1213
1214
599/** 1215/**
600 * Returns string representation of ticket. Base64-Encoded 1216 * Lists all tickets that have been issued to remote
1217 * identites (relying parties)
601 * 1218 *
602 * @param ticket the ticket 1219 * @param h the identity provider to use
603 * @return the Base64-Encoded ticket 1220 * @param identity the issuing identity
1221 * @param error_cb function to call on error (i.e. disconnect),
1222 * the handle is afterwards invalid
1223 * @param error_cb_cls closure for @a error_cb
1224 * @param proc function to call on each ticket; it
1225 * will be called repeatedly with a value (if available)
1226 * @param proc_cls closure for @a proc
1227 * @param finish_cb function to call on completion
1228 * the handle is afterwards invalid
1229 * @param finish_cb_cls closure for @a finish_cb
1230 * @return an iterator handle to use for iteration
604 */ 1231 */
605char * 1232struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
606GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) 1233GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1234 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1235 GNUNET_SCHEDULER_TaskCallback error_cb,
1236 void *error_cb_cls,
1237 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
1238 void *proc_cls,
1239 GNUNET_SCHEDULER_TaskCallback finish_cb,
1240 void *finish_cb_cls)
607{ 1241{
608 return GNUNET_strdup (ticket->data); 1242 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
1243 struct GNUNET_MQ_Envelope *env;
1244 struct TicketIterationStartMessage *msg;
1245 uint32_t rid;
1246
1247 rid = h->r_id_gen++;
1248 it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
1249 it->h = h;
1250 it->error_cb = error_cb;
1251 it->error_cb_cls = error_cb_cls;
1252 it->finish_cb = finish_cb;
1253 it->finish_cb_cls = finish_cb_cls;
1254 it->tr_cb = proc;
1255 it->cls = proc_cls;
1256 it->r_id = rid;
1257 GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
1258 h->ticket_it_tail,
1259 it);
1260 env = GNUNET_MQ_msg (msg,
1261 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
1262 msg->id = htonl (rid);
1263 msg->identity = *identity;
1264 msg->is_audience = htonl (GNUNET_YES);
1265 if (NULL == h->mq)
1266 it->env = env;
1267 else
1268 GNUNET_MQ_send (h->mq,
1269 env);
1270 return it;
1271
1272
609} 1273}
610 1274
611/** 1275/**
612 * Created a ticket from a string (Base64 encoded ticket) 1276 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
1277 * for the next record.
613 * 1278 *
614 * @param input Base64 encoded ticket 1279 * @param it the iterator
615 * @param ticket pointer where the ticket is stored
616 * @return GNUNET_OK
617 */ 1280 */
618int 1281void
619GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, 1282GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
620 struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket)
621{ 1283{
622 *ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); 1284 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
623 (*ticket)->data = GNUNET_strdup (input); 1285 struct TicketIterationNextMessage *msg;
624 return GNUNET_OK; 1286 struct GNUNET_MQ_Envelope *env;
1287
1288 env = GNUNET_MQ_msg (msg,
1289 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT);
1290 msg->id = htonl (it->r_id);
1291 GNUNET_MQ_send (h->mq,
1292 env);
625} 1293}
626 1294
627 1295
628/** 1296/**
629 * Destroys a ticket 1297 * Stops iteration and releases the idp handle for further calls. Must
1298 * be called on any iteration that has not yet completed prior to calling
1299 * #GNUNET_IDENTITY_PROVIDER_disconnect.
630 * 1300 *
631 * @param ticket the ticket to destroy 1301 * @param it the iterator
632 */ 1302 */
633void 1303void
634GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) 1304GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
635{ 1305{
636 GNUNET_assert (NULL != ticket); 1306 struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
637 if (NULL != ticket->data) 1307 struct GNUNET_MQ_Envelope *env;
638 GNUNET_free (ticket->data); 1308 struct TicketIterationStopMessage *msg;
639 GNUNET_free (ticket); 1309
1310 if (NULL != h->mq)
1311 {
1312 env = GNUNET_MQ_msg (msg,
1313 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP);
1314 msg->id = htonl (it->r_id);
1315 GNUNET_MQ_send (h->mq,
1316 env);
1317 }
1318 GNUNET_free (it);
640} 1319}
641 1320
1321/**
1322 * Revoked an issued ticket. The relying party will be unable to retrieve
1323 * updated attributes.
1324 *
1325 * @param h the identity provider to use
1326 * @param identity the issuing identity
1327 * @param ticket the ticket to revoke
1328 * @param cb the callback
1329 * @param cb_cls the callback closure
1330 * @return handle to abort the operation
1331 */
1332struct GNUNET_IDENTITY_PROVIDER_Operation *
1333GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
1334 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1335 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1336 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
1337 void *cb_cls)
1338{
1339 struct GNUNET_IDENTITY_PROVIDER_Operation *op;
1340 struct GNUNET_MQ_Envelope *env;
1341 struct RevokeTicketMessage *msg;
1342 uint32_t rid;
642 1343
1344 rid = h->r_id_gen++;
1345 op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
1346 op->h = h;
1347 op->rvk_cb = cb;
1348 op->cls = cb_cls;
1349 op->r_id = rid;
1350 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1351 h->op_tail,
1352 op);
1353 env = GNUNET_MQ_msg_extra (msg,
1354 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
1355 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET);
1356 msg->id = htonl (rid);
1357 msg->identity = *identity;
1358 memcpy (&msg[1],
1359 ticket,
1360 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
1361 if (NULL == h->mq)
1362 op->env = env;
1363 else
1364 GNUNET_MQ_send (h->mq,
1365 env);
1366 return op;
1367}
643 1368
644 1369
645 1370
diff --git a/src/identity-provider/identity_token.c b/src/identity-provider/identity_token.c
deleted file mode 100644
index 31249840b..000000000
--- a/src/identity-provider/identity_token.c
+++ /dev/null
@@ -1,964 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21/**
22 * @file identity-provider/identity_token.c
23 * @brief helper library to manage identity tokens
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_signatures.h"
29#include "identity_token.h"
30#include <jansson.h>
31#include <inttypes.h>
32
33#define JWT_ALG "alg"
34
35#define JWT_ALG_VALUE "ED512"
36
37#define JWT_TYP "typ"
38
39#define JWT_TYP_VALUE "jwt"
40
41/**
42 * Crypto helper functions
43 */
44
45static int
46create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
47 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
48 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
49{
50 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
51
52 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
53 &new_key_hash_str);
54 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
55 static const char ctx_key[] = "gnuid-aes-ctx-key";
56 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
57 new_key_hash, sizeof (struct GNUNET_HashCode),
58 ctx_key, strlen (ctx_key),
59 NULL, 0);
60 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
61 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
62 new_key_hash, sizeof (struct GNUNET_HashCode),
63 ctx_iv, strlen (ctx_iv),
64 NULL, 0);
65 return GNUNET_OK;
66}
67
68
69
70/**
71 * Decrypts data part from a token code
72 */
73static int
74decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
75 const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key,
76 const char *cyphertext,
77 size_t cyphertext_len,
78 char **result_str)
79{
80 struct GNUNET_HashCode new_key_hash;
81 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
82 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
83
84 char *str_buf = GNUNET_malloc (cyphertext_len);
85 size_t str_size;
86
87 //Calculate symmetric key from ecdh parameters
88 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (priv_key,
89 ecdh_key,
90 &new_key_hash));
91
92 create_sym_key_from_ecdh (&new_key_hash,
93 &enc_key,
94 &enc_iv);
95
96 str_size = GNUNET_CRYPTO_symmetric_decrypt (cyphertext,
97 cyphertext_len,
98 &enc_key,
99 &enc_iv,
100 str_buf);
101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
102 "Decrypted bytes: %zd Expected bytes: %zd\n",
103 str_size,
104 cyphertext_len);
105 if (-1 == str_size)
106 {
107 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
108 GNUNET_free (str_buf);
109 return GNUNET_SYSERR;
110 }
111 *result_str = GNUNET_malloc (str_size+1);
112 GNUNET_memcpy (*result_str, str_buf, str_size);
113 (*result_str)[str_size] = '\0';
114 GNUNET_free (str_buf);
115 return GNUNET_OK;
116
117}
118
119/**
120 * Decrypt string using pubkey and ECDHE
121*/
122static int
123decrypt_str_ecdhe2 (const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey,
124 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
125 const char *ciphertext,
126 size_t ciphertext_len,
127 char **plaintext)
128{
129 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
130 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
131 struct GNUNET_HashCode new_key_hash;
132
133 //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
134 *plaintext = GNUNET_malloc (ciphertext_len);
135
136 // Derived key K = H(eB)
137 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (ecdh_privkey,
138 aud_key,
139 &new_key_hash));
140 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
141 GNUNET_CRYPTO_symmetric_decrypt (ciphertext,
142 ciphertext_len,
143 &skey, &iv,
144 *plaintext);
145 return GNUNET_OK;
146}
147
148
149/**
150 * Encrypt string using pubkey and ECDHE
151 * Returns ECDHE pubkey to be used for decryption
152 */
153static int
154encrypt_str_ecdhe (const char *plaintext,
155 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
156 char **cyphertext,
157 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
158 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey)
159{
160 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
161 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
162 struct GNUNET_HashCode new_key_hash;
163 ssize_t enc_size;
164
165 // ECDH keypair E = eG
166 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
167 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
168 ecdh_pubkey);
169
170 //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
171 *cyphertext = GNUNET_malloc (strlen (plaintext));
172
173 // Derived key K = H(eB)
174 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
175 pub_key,
176 &new_key_hash));
177 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting string %s\n (len=%zd)",
179 plaintext,
180 strlen (plaintext));
181 enc_size = GNUNET_CRYPTO_symmetric_encrypt (plaintext,
182 strlen (plaintext),
183 &skey, &iv,
184 *cyphertext);
185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted (len=%zd)", enc_size);
186 return GNUNET_OK;
187}
188
189
190/**
191 * Identity Token API
192 */
193
194
195/**
196 * Create an Identity Token
197 *
198 * @param type the JSON API resource type
199 * @param id the JSON API resource id
200 * @return a new JSON API resource or NULL on error.
201 */
202struct IdentityToken*
203token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey* iss,
204 const struct GNUNET_CRYPTO_EcdsaPublicKey* aud)
205{
206 struct IdentityToken *token;
207 char* audience;
208 char* issuer;
209
210 issuer = GNUNET_STRINGS_data_to_string_alloc (iss,
211 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
212 audience = GNUNET_STRINGS_data_to_string_alloc (aud,
213 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
214
215 token = GNUNET_malloc (sizeof (struct IdentityToken));
216 token_add_attr (token, "iss", issuer);
217 token_add_attr (token, "aud", audience);
218 token_add_attr (token, "sub", issuer);
219 token->aud_key = *aud;
220 GNUNET_free (issuer);
221 GNUNET_free (audience);
222 return token;
223}
224
225void
226token_destroy (struct IdentityToken *token)
227{
228 struct TokenAttr *attr;
229 struct TokenAttr *tmp_attr;
230 struct TokenAttrValue *val;
231 struct TokenAttrValue *tmp_val;
232
233 for (attr = token->attr_head; NULL != attr;)
234 {
235 tmp_attr = attr->next;
236 GNUNET_CONTAINER_DLL_remove (token->attr_head,
237 token->attr_tail,
238 attr);
239 for (val = attr->val_head; NULL != val;)
240 {
241 tmp_val = val->next;
242 GNUNET_CONTAINER_DLL_remove (attr->val_head,
243 attr->val_tail,
244 val);
245 if (NULL != val->value)
246 GNUNET_free (val->value);
247 GNUNET_free (val);
248 val = tmp_val;
249 }
250 GNUNET_free (attr->name);
251 GNUNET_free (attr);
252 attr = tmp_attr;
253 }
254
255
256 GNUNET_free (token);
257}
258
259void
260token_add_attr (struct IdentityToken *token,
261 const char* key,
262 const char* value)
263{
264 struct TokenAttr *attr;
265 struct TokenAttrValue *new_val;
266 GNUNET_assert (NULL != token);
267
268 new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
269 new_val->value = GNUNET_strdup (value);
270 for (attr = token->attr_head; NULL != attr; attr = attr->next)
271 {
272 if (0 == strcmp (key, attr->name))
273 break;
274 }
275
276 if (NULL == attr)
277 {
278 attr = GNUNET_malloc (sizeof (struct TokenAttr));
279 attr->name = GNUNET_strdup (key);
280 GNUNET_CONTAINER_DLL_insert (token->attr_head,
281 token->attr_tail,
282 attr);
283 }
284
285 GNUNET_CONTAINER_DLL_insert (attr->val_head,
286 attr->val_tail,
287 new_val);
288}
289
290void
291token_add_attr_int (struct IdentityToken *token,
292 const char* key,
293 uint64_t value)
294{
295 struct TokenAttr *attr;
296 struct TokenAttrValue *new_val;
297 GNUNET_assert (NULL != token);
298
299 new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
300 new_val->int_value = value;
301 for (attr = token->attr_head; NULL != attr; attr = attr->next)
302 {
303 if (0 == strcmp (key, attr->name))
304 break;
305 }
306
307 if (NULL == attr)
308 {
309 attr = GNUNET_malloc (sizeof (struct TokenAttr));
310 attr->name = GNUNET_strdup (key);
311 GNUNET_CONTAINER_DLL_insert (token->attr_head,
312 token->attr_tail,
313 attr);
314 }
315
316 GNUNET_CONTAINER_DLL_insert (attr->val_head,
317 attr->val_tail,
318 new_val);
319}
320
321static void
322parse_json_payload(const char* payload_base64,
323 struct IdentityToken *token)
324{
325 const char *key;
326 const json_t *value;
327 const json_t *arr_value;
328 char *payload;
329 int idx;
330 json_t *payload_json;
331 json_error_t err_json;
332
333 GNUNET_STRINGS_base64_decode (payload_base64,
334 strlen (payload_base64),
335 &payload);
336 //TODO signature and aud key
337 payload_json = json_loads (payload, JSON_DECODE_ANY, &err_json);
338
339 json_object_foreach (payload_json, key, value)
340 {
341 if (json_is_array (value))
342 {
343 json_array_foreach (value, idx, arr_value)
344 {
345 if (json_is_integer (arr_value))
346 token_add_attr_int (token, key,
347 json_integer_value (arr_value));
348 else
349 token_add_attr (token,
350 key,
351 json_string_value (arr_value));
352 }
353 } else {
354 if (json_is_integer (value))
355 token_add_attr_int (token, key,
356 json_integer_value (value));
357 else
358 token_add_attr (token, key, json_string_value (value));
359 }
360 }
361
362 json_decref (payload_json);
363 GNUNET_free (payload);
364}
365
366int
367token_parse2 (const char* raw_data,
368 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
369 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
370 struct IdentityToken **result)
371{
372 char *enc_token_str;
373 char *tmp_buf;
374 char *token_str;
375 char *enc_token;
376 char *payload_base64;
377 size_t enc_token_len;
378
379 GNUNET_asprintf (&tmp_buf, "%s", raw_data);
380 strtok (tmp_buf, ",");
381 enc_token_str = strtok (NULL, ",");
382
383 enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
384 strlen (enc_token_str),
385 &enc_token);
386 if (GNUNET_OK != decrypt_str_ecdhe2 (priv_key,
387 aud_key,
388 enc_token,
389 enc_token_len,
390 &token_str))
391 {
392 GNUNET_free (tmp_buf);
393 GNUNET_free (enc_token);
394 return GNUNET_SYSERR;
395 }
396
397 GNUNET_assert (NULL != strtok (token_str, "."));
398 payload_base64 = strtok (NULL, ".");
399
400 *result = GNUNET_malloc (sizeof (struct IdentityToken));
401 parse_json_payload (payload_base64, *result);
402
403 (*result)->aud_key = *aud_key;
404 GNUNET_free (enc_token);
405 GNUNET_free (token_str);
406 GNUNET_free (tmp_buf);
407 return GNUNET_OK;
408}
409
410int
411token_parse (const char* raw_data,
412 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
413 struct IdentityToken **result)
414{
415 char *ecdh_pubkey_str;
416 char *enc_token_str;
417 char *tmp_buf;
418 char *token_str;
419 char *enc_token;
420 char *payload_base64;
421 size_t enc_token_len;
422 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
423
424 GNUNET_asprintf (&tmp_buf, "%s", raw_data);
425 ecdh_pubkey_str = strtok (tmp_buf, ",");
426 enc_token_str = strtok (NULL, ",");
427
428 GNUNET_assert (NULL != ecdh_pubkey_str);
429 GNUNET_assert (NULL != enc_token_str);
430
431 GNUNET_STRINGS_string_to_data (ecdh_pubkey_str,
432 strlen (ecdh_pubkey_str),
433 &ecdh_pubkey,
434 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
435 enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
436 strlen (enc_token_str),
437 &enc_token);
438 if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
439 &ecdh_pubkey,
440 enc_token,
441 enc_token_len,
442 &token_str))
443 {
444 GNUNET_free (tmp_buf);
445 GNUNET_free (enc_token);
446 return GNUNET_SYSERR;
447 }
448
449 GNUNET_assert (NULL != strtok (token_str, "."));
450 payload_base64 = strtok (NULL, ".");
451
452 *result = GNUNET_malloc (sizeof (struct IdentityToken));
453 parse_json_payload (payload_base64, *result);
454
455 GNUNET_free (enc_token);
456 GNUNET_free (token_str);
457 GNUNET_free (tmp_buf);
458 return GNUNET_OK;
459}
460
461static char*
462create_json_payload (const struct IdentityToken *token)
463{
464 struct TokenAttr *attr;
465 struct TokenAttrValue *val;
466 json_t *root;
467 char *json_str;
468
469 root = json_object();
470 for (attr = token->attr_head; NULL != attr; attr = attr->next)
471 {
472 for (val = attr->val_head; NULL != val; val = val->next)
473 {
474 if (NULL != val->value)
475 {
476 json_object_set_new (root,
477 attr->name,
478 json_string (val->value));
479 } else {
480 json_object_set_new (root,
481 attr->name,
482 json_integer (val->int_value));
483 }
484 }
485 }
486 json_str = json_dumps (root, JSON_INDENT(1));
487 json_decref (root);
488 return json_str;
489}
490
491static char*
492create_json_header(void)
493{
494 json_t *root;
495 char *json_str;
496
497 root = json_object ();
498 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
499 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
500
501 json_str = json_dumps (root, JSON_INDENT(1));
502 json_decref (root);
503 return json_str;
504}
505
506int
507token_to_string (const struct IdentityToken *token,
508 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
509 char **result)
510{
511 char *payload_str;
512 char *header_str;
513 char *payload_base64;
514 char *header_base64;
515 char *padding;
516 char *signature_target;
517 char *signature_str;
518 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
519 header_str = create_json_header();
520 GNUNET_STRINGS_base64_encode (header_str,
521 strlen (header_str),
522 &header_base64);
523 //Remove GNUNET padding of base64
524 padding = strtok(header_base64, "=");
525 while (NULL != padding)
526 padding = strtok(NULL, "=");
527
528 payload_str = create_json_payload (token);
529 GNUNET_STRINGS_base64_encode (payload_str,
530 strlen (payload_str),
531 &payload_base64);
532
533 //Remove GNUNET padding of base64
534 padding = strtok(payload_base64, "=");
535 while (NULL != padding)
536 padding = strtok(NULL, "=");
537
538 GNUNET_asprintf (&signature_target, "%s,%s", header_base64, payload_base64);
539 purpose =
540 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
541 strlen (signature_target));
542 purpose->size =
543 htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
544 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
545 GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
546 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
547 purpose,
548 (struct GNUNET_CRYPTO_EcdsaSignature *)&token->signature))
549 {
550 GNUNET_free (signature_target);
551 GNUNET_free (payload_str);
552 GNUNET_free (payload_base64);
553 GNUNET_free (header_base64);
554 GNUNET_free (purpose);
555 return GNUNET_SYSERR;
556 }
557
558 GNUNET_STRINGS_base64_encode ((const char*)&token->signature,
559 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
560 &signature_str);
561 GNUNET_asprintf (result, "%s.%s.%s",
562 header_base64, payload_base64, signature_str);
563 GNUNET_free (signature_target);
564 GNUNET_free (payload_str);
565 GNUNET_free (header_str);
566 GNUNET_free (signature_str);
567 GNUNET_free (payload_base64);
568 GNUNET_free (header_base64);
569 GNUNET_free (purpose);
570 return GNUNET_OK;
571}
572
573int
574token_serialize (const struct IdentityToken *token,
575 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
576 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
577 char **result)
578{
579 char *token_str;
580 char *enc_token;
581 char *dh_key_str;
582 char *enc_token_base64;
583 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
584
585 GNUNET_assert (GNUNET_OK == token_to_string (token,
586 priv_key,
587 &token_str));
588
589 GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (token_str,
590 &token->aud_key,
591 &enc_token,
592 ecdh_privkey,
593 &ecdh_pubkey));
594 GNUNET_STRINGS_base64_encode (enc_token,
595 strlen (token_str),
596 &enc_token_base64);
597 dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ecdh_pubkey,
598 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
599 GNUNET_asprintf (result, "%s,%s", dh_key_str, enc_token_base64);
600 GNUNET_free (dh_key_str);
601 GNUNET_free (enc_token_base64);
602 GNUNET_free (enc_token);
603 GNUNET_free (token_str);
604 return GNUNET_OK;
605}
606
607struct TokenTicketPayload*
608ticket_payload_create (uint64_t nonce,
609 const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
610 const char* lbl_str)
611{
612 struct TokenTicketPayload* payload;
613
614 payload = GNUNET_malloc (sizeof (struct TokenTicketPayload));
615 payload->nonce = nonce;
616 payload->identity_key = *identity_pkey;
617 GNUNET_asprintf (&payload->label, lbl_str, strlen (lbl_str));
618 return payload;
619}
620
621void
622ticket_payload_destroy (struct TokenTicketPayload* payload)
623{
624 if (NULL != payload->label)
625 GNUNET_free (payload->label);
626 GNUNET_free (payload);
627}
628
629void
630ticket_payload_serialize (struct TokenTicketPayload *payload,
631 char **result)
632{
633 char* identity_key_str;
634
635 identity_key_str = GNUNET_STRINGS_data_to_string_alloc (&payload->identity_key,
636 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
637
638 GNUNET_asprintf (result,
639 "{\"nonce\": \"%"SCNu64"\",\"identity\": \"%s\",\"label\": \"%s\"}",
640 payload->nonce, identity_key_str, payload->label);
641 GNUNET_free (identity_key_str);
642
643}
644
645
646/**
647 * Create the token code
648 * The data is encrypted with a share ECDH derived secret using B (aud_key)
649 * and e (ecdh_privkey)
650 * The ticket also contains E (ecdh_pubkey) and a signature over the
651 * data and E
652 */
653struct TokenTicket*
654ticket_create (uint64_t nonce,
655 const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
656 const char* lbl_str,
657 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key)
658{
659 struct TokenTicket *ticket;
660 struct TokenTicketPayload *code_payload;
661
662 ticket = GNUNET_malloc (sizeof (struct TokenTicket));
663 code_payload = ticket_payload_create (nonce,
664 identity_pkey,
665 lbl_str);
666 ticket->aud_key = *aud_key;
667 ticket->payload = code_payload;
668
669
670 return ticket;
671}
672
673void
674ticket_destroy (struct TokenTicket *ticket)
675{
676 ticket_payload_destroy (ticket->payload);
677 GNUNET_free (ticket);
678}
679
680int
681ticket_serialize (struct TokenTicket *ticket,
682 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
683 char **result)
684{
685 char *code_payload_str;
686 char *enc_ticket_payload;
687 char *ticket_payload_str;
688 char *ticket_sig_str;
689 char *ticket_str;
690 char *dh_key_str;
691 char *write_ptr;
692 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
693
694 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
695
696 ticket_payload_serialize (ticket->payload,
697 &code_payload_str);
698
699 GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (code_payload_str,
700 &ticket->aud_key,
701 &enc_ticket_payload,
702 &ecdhe_privkey,
703 &ticket->ecdh_pubkey));
704
705 GNUNET_free (ecdhe_privkey);
706
707 purpose =
708 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
709 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
710 strlen (code_payload_str)); // E_K (code_str)
711 purpose->size =
712 htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
713 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
714 strlen (code_payload_str));
715 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
716 write_ptr = (char*) &purpose[1];
717 GNUNET_memcpy (write_ptr,
718 &ticket->ecdh_pubkey,
719 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
720 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
721 GNUNET_memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
722 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
723 purpose,
724 &ticket->signature));
725 GNUNET_STRINGS_base64_encode (enc_ticket_payload,
726 strlen (code_payload_str),
727 &ticket_payload_str);
728 ticket_sig_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->signature,
729 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
730
731 dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->ecdh_pubkey,
732 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
733 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
734 GNUNET_asprintf (&ticket_str, "{\"data\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
735 ticket_payload_str, dh_key_str, ticket_sig_str);
736 GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
737 GNUNET_free (dh_key_str);
738 GNUNET_free (purpose);
739 GNUNET_free (ticket_str);
740 GNUNET_free (ticket_sig_str);
741 GNUNET_free (code_payload_str);
742 GNUNET_free (enc_ticket_payload);
743 GNUNET_free (ticket_payload_str);
744 return GNUNET_OK;
745}
746
747int
748ticket_payload_parse(const char *raw_data,
749 ssize_t data_len,
750 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
751 const struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe_pkey,
752 struct TokenTicketPayload **result)
753{
754 const char* label_str;
755 const char* nonce_str;
756 const char* identity_key_str;
757
758 json_t *root;
759 json_t *label_json;
760 json_t *identity_json;
761 json_t *nonce_json;
762 json_error_t err_json;
763 char* data_str;
764 uint64_t nonce;
765 struct GNUNET_CRYPTO_EcdsaPublicKey id_pkey;
766
767 if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
768 ecdhe_pkey,
769 raw_data,
770 data_len,
771 &data_str))
772 {
773 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Data decryption failed\n");
774 return GNUNET_SYSERR;
775 }
776
777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data: %s\n", data_str);
778 root = json_loads (data_str, JSON_DECODE_ANY, &err_json);
779 if (!root)
780 {
781 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
782 "Error parsing data: %s\n", err_json.text);
783 GNUNET_free (data_str);
784 return GNUNET_SYSERR;
785 }
786
787 identity_json = json_object_get (root, "identity");
788 if (!json_is_string (identity_json))
789 {
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
791 "Error parsing data: %s\n", err_json.text);
792 json_decref (root);
793 GNUNET_free (data_str);
794 return GNUNET_SYSERR;
795 }
796 identity_key_str = json_string_value (identity_json);
797 GNUNET_STRINGS_string_to_data (identity_key_str,
798 strlen (identity_key_str),
799 &id_pkey,
800 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
801
802
803 label_json = json_object_get (root, "label");
804 if (!json_is_string (label_json))
805 {
806 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
807 "Error parsing data: %s\n", err_json.text);
808 json_decref (root);
809 GNUNET_free (data_str);
810 return GNUNET_SYSERR;
811 }
812
813 label_str = json_string_value (label_json);
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found label: %s\n", label_str);
815
816 nonce_json = json_object_get (root, "nonce");
817 if (!json_is_string (label_json))
818 {
819 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
820 "Error parsing data: %s\n", err_json.text);
821 json_decref (root);
822 GNUNET_free (data_str);
823 return GNUNET_SYSERR;
824 }
825
826 nonce_str = json_string_value (nonce_json);
827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found nonce: %s\n", nonce_str);
828
829 GNUNET_assert (0 != sscanf (nonce_str, "%"SCNu64, &nonce));
830
831 *result = ticket_payload_create (nonce,
832 (const struct GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
833 label_str);
834 GNUNET_free (data_str);
835 json_decref (root);
836 return GNUNET_OK;
837
838}
839
840int
841ticket_parse (const char *raw_data,
842 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
843 struct TokenTicket **result)
844{
845 const char* enc_data_str;
846 const char* ecdh_enc_str;
847 const char* signature_enc_str;
848
849 json_t *root;
850 json_t *signature_json;
851 json_t *ecdh_json;
852 json_t *enc_data_json;
853 json_error_t err_json;
854 char* enc_data;
855 char* ticket_decoded;
856 char* write_ptr;
857 size_t enc_data_len;
858 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
859 struct TokenTicket *ticket;
860 struct TokenTicketPayload *ticket_payload;
861
862 ticket_decoded = NULL;
863 GNUNET_STRINGS_base64_decode (raw_data, strlen (raw_data), &ticket_decoded);
864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket: %s\n", ticket_decoded);
865 root = json_loads (ticket_decoded, JSON_DECODE_ANY, &err_json);
866 if (!root)
867 {
868 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
869 "%s\n", err_json.text);
870 return GNUNET_SYSERR;
871 }
872
873 signature_json = json_object_get (root, "signature");
874 ecdh_json = json_object_get (root, "ecdh");
875 enc_data_json = json_object_get (root, "data");
876
877 signature_enc_str = json_string_value (signature_json);
878 ecdh_enc_str = json_string_value (ecdh_json);
879 enc_data_str = json_string_value (enc_data_json);
880
881 ticket = GNUNET_malloc (sizeof (struct TokenTicket));
882
883 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ecdh_enc_str,
884 strlen (ecdh_enc_str),
885 &ticket->ecdh_pubkey,
886 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)))
887 {
888 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in data\n", ecdh_enc_str);
889 json_decref (root);
890 GNUNET_free (ticket);
891 return GNUNET_SYSERR;
892 }
893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s for data decryption\n", ecdh_enc_str);
894 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
895 strlen (signature_enc_str),
896 &ticket->signature,
897 sizeof (struct GNUNET_CRYPTO_EcdsaSignature)))
898 {
899 json_decref (root);
900 GNUNET_free (ticket_decoded);
901 GNUNET_free (ticket);
902 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in data\n");
903 return GNUNET_SYSERR;
904 }
905
906 enc_data_len = GNUNET_STRINGS_base64_decode (enc_data_str,
907 strlen (enc_data_str),
908 &enc_data);
909
910
911 if (GNUNET_OK != ticket_payload_parse (enc_data,
912 enc_data_len,
913 priv_key,
914 (const struct GNUNET_CRYPTO_EcdhePublicKey*)&ticket->ecdh_pubkey,
915 &ticket_payload))
916 {
917 json_decref (root);
918 GNUNET_free (enc_data);
919 GNUNET_free (ticket_decoded);
920 GNUNET_free (ticket);
921 return GNUNET_SYSERR;
922 }
923
924 ticket->payload = ticket_payload;
925 purpose =
926 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
927 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
928 enc_data_len); // E_K (code_str)
929 purpose->size =
930 htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
931 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
932 enc_data_len);
933 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
934 write_ptr = (char*) &purpose[1];
935 GNUNET_memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
936 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
937 GNUNET_memcpy (write_ptr, enc_data, enc_data_len);
938
939 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET,
940 purpose,
941 &ticket->signature,
942 &ticket_payload->identity_key))
943 {
944 ticket_destroy (ticket);
945 GNUNET_free (ticket_decoded);
946 json_decref (root);
947 GNUNET_free (purpose);
948 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
949 "Error verifying signature for ticket\n");
950 return GNUNET_SYSERR;
951 }
952 *result = ticket;
953 GNUNET_free (purpose);
954
955 GNUNET_free (enc_data);
956 GNUNET_free (ticket_decoded);
957 json_decref (root);
958 return GNUNET_OK;
959
960}
961
962
963
964/* end of identity_token.c */
diff --git a/src/identity-provider/identity_token.h b/src/identity-provider/identity_token.h
deleted file mode 100644
index 7ded6662e..000000000
--- a/src/identity-provider/identity_token.h
+++ /dev/null
@@ -1,346 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file identity-provider/identity_token.h
23 * @brief GNUnet Identity Provider library
24 *
25 */
26#ifndef IDENTITY_TOKEN_H
27#define IDENTITY_TOKEN_H
28
29#include "gnunet_crypto_lib.h"
30#include <jansson.h>
31
32struct IdentityToken
33{
34 /**
35 * DLL
36 */
37 struct TokenAttr *attr_head;
38
39 /**
40 * DLL
41 */
42 struct TokenAttr *attr_tail;
43
44 /**
45 * Token Signature
46 */
47 struct GNUNET_CRYPTO_EcdsaSignature signature;
48
49 /**
50 * Audience Pubkey
51 */
52 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
53};
54
55struct TokenAttr
56{
57 /**
58 * DLL
59 */
60 struct TokenAttr *next;
61
62 /**
63 * DLL
64 */
65 struct TokenAttr *prev;
66
67 /**
68 * Attribute name
69 */
70 char *name;
71
72 /**
73 * Attribute value DLL
74 */
75 struct TokenAttrValue *val_head;
76
77 /**
78 * Attribute value DLL
79 */
80 struct TokenAttrValue *val_tail;
81
82};
83
84struct TokenAttrValue
85{
86 /**
87 * DLL
88 */
89 struct TokenAttrValue *next;
90
91 /**
92 * DLL
93 */
94 struct TokenAttrValue *prev;
95
96 /**
97 * Attribute value
98 */
99 char *value;
100
101 /**
102 * Attribute int value
103 * used if NULL == value
104 */
105 uint64_t int_value;
106};
107
108struct TokenTicketPayload
109{
110 /**
111 * Nonce
112 */
113 uint64_t nonce;
114
115 /**
116 * Label
117 */
118 char *label;
119
120 /**
121 * Issuing Identity
122 */
123 struct GNUNET_CRYPTO_EcdsaPublicKey identity_key;
124};
125
126
127struct TokenTicket
128{
129 /**
130 * Meta info
131 */
132 struct TokenTicketPayload *payload;
133
134 /**
135 * ECDH Pubkey
136 */
137 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
138
139 /**
140 * Signature
141 */
142 struct GNUNET_CRYPTO_EcdsaSignature signature;
143
144 /**
145 * Target identity
146 */
147 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
148};
149
150
151
152/**
153 * Create an identity token
154 *
155 * @param iss the issuer string for the token
156 * @param aud the audience of the token
157 *
158 * @return a new token
159 */
160struct IdentityToken*
161token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *iss,
162 const struct GNUNET_CRYPTO_EcdsaPublicKey* aud);
163
164/**
165 * Destroy an identity token
166 *
167 * @param token the token to destroy
168 */
169void
170token_destroy (struct IdentityToken*token);
171
172/**
173 * Add a new key value pair to the token
174 *
175 * @param token the token to modify
176 * @param key the key
177 * @param value the value
178 */
179void
180token_add_attr (struct IdentityToken *token,
181 const char* key,
182 const char* value);
183
184/**
185 * Add a new key value pair to the token
186 *
187 * @param token the token to modify
188 * @param key the key
189 * @param value the value
190 */
191void
192token_add_attr_int (struct IdentityToken *token,
193 const char* key,
194 uint64_t value);
195
196
197
198/**
199 * Add a value to a TokenAttribute
200 *
201 * @param attr the token attribute
202 * @param value value to add
203 */
204 void
205 token_attr_add_value (const struct TokenAttr *attr,
206 const char *value);
207
208/**
209 * Add a new key value pair to the token with the value as json
210 *
211 * @param the token to modify
212 * @param key the key
213 * @param value the value
214 *
215 */
216 void
217 token_add_json (const struct IdentityToken *token,
218 const char* key,
219 json_t* value);
220
221/**
222 * Serialize a token. The token will be signed and base64 according to the
223 * JWT format. The signature is base32-encoded ECDSA.
224 * The resulting JWT is encrypted using
225 * ECDHE for the audience and Base64
226 * encoded in result. The audience requires the ECDHE public key P
227 * to decrypt the token T. The key P is included in the result and prepended
228 * before the token
229 *
230 * @param token the token to serialize
231 * @param priv_key the private key used to sign the token
232 * @param ecdhe_privkey the ECDHE private key used to encrypt the token
233 * @param result P,Base64(E(T))
234 *
235 * @return GNUNET_OK on success
236 */
237 int
238 token_serialize (const struct IdentityToken*token,
239 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
240 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
241 char **result);
242
243/**
244 * Parses the serialized token and returns a token
245 *
246 * @param data the serialized token
247 * @param priv_key the private key of the audience
248 * @param result the token
249 *
250 * @return GNUNET_OK on success
251 */
252 int
253 token_parse (const char* data,
254 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
255 struct IdentityToken **result);
256
257/**
258 * Parses the serialized token and returns a token
259 * This variant is intended for the party that issued the token and also
260 * wants to decrypt the serialized token.
261 *
262 * @param data the serialized token
263 * @param priv_key the private (!) ECDHE key
264 * @param aud_key the identity of the audience
265 * @param result the token
266 *
267 * @return GNUNET_OK on success
268 */
269int
270token_parse2 (const char* data,
271 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
272 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
273 struct IdentityToken **result);
274
275
276/**
277 *
278 * Returns a JWT-string representation of the token
279 *
280 * @param token the token
281 * @param priv_key the private key used to sign the JWT
282 * @param result the JWT
283 *
284 * @return GNUNET_OK on success
285 */
286 int
287 token_to_string (const struct IdentityToken *token,
288 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
289 char **result);
290
291/**
292 *
293 * Creates a ticket that can be exchanged by the audience for
294 * the token. The token must be placed under the label
295 *
296 * @param nonce nonce provided by the audience that requested the ticket
297 * @param iss_pkey the issuer pubkey used to sign the ticket
298 * @param label the label encoded in the ticket
299 * @param aud_ley the audience pubkey used to encrypt the ticket payload
300 *
301 * @return the ticket
302 */
303struct TokenTicket*
304ticket_create (uint64_t nonce,
305 const struct GNUNET_CRYPTO_EcdsaPublicKey* iss_pkey,
306 const char* lbl_str,
307 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key);
308
309/**
310 * Serialize a ticket. Returns the Base64 representation of the ticket.
311 * Format: Base64( { payload: E(Payload), ecdhe: K, signature: signature } )
312 *
313 * @param ticket the ticket to serialize
314 * @param priv_key the issuer private key to sign the ticket payload
315 * @param result the serialized ticket
316 *
317 * @return GNUNET_OK on success
318 */
319 int
320 ticket_serialize (struct TokenTicket *ticket,
321 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
322 char **result);
323
324/**
325 * Destroys a ticket
326 *
327 * @param the ticket to destroy
328 */
329void
330ticket_destroy (struct TokenTicket *ticket);
331
332/**
333 * Parses a serialized ticket
334 *
335 * @param data the serialized ticket
336 * @param priv_key the audience private key
337 * @param ticket the ticket
338 *
339 * @return GNUNET_OK on success
340 */
341int
342ticket_parse (const char* raw_data,
343 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
344 struct TokenTicket **ticket);
345
346#endif
diff --git a/src/identity-provider/jwt.c b/src/identity-provider/jwt.c
new file mode 100644
index 000000000..2f1e3240b
--- /dev/null
+++ b/src/identity-provider/jwt.c
@@ -0,0 +1,180 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21/**
22 * @file identity-provider/jwt.c
23 * @brief helper library for JSON-Web-Tokens
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_signatures.h"
29#include "gnunet_identity_attribute_lib.h"
30#include <jansson.h>
31
32
33#define JWT_ALG "alg"
34
35/*TODO is this the correct way to define new algs? */
36#define JWT_ALG_VALUE "ED512"
37
38#define JWT_TYP "typ"
39
40#define JWT_TYP_VALUE "jwt"
41
42static char*
43create_jwt_header(void)
44{
45 json_t *root;
46 char *json_str;
47
48 root = json_object ();
49 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
50 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
51
52 json_str = json_dumps (root, JSON_INDENT(1));
53 json_decref (root);
54 return json_str;
55}
56
57/**
58 * Create a JWT from attributes
59 *
60 * @param sub_key the public of the subject
61 * @param attrs the attribute list
62 * @param priv_key the key used to sign the JWT
63 * @return a new base64-encoded JWT string.
64 */
65char*
66jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
67 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
68 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key)
69{
70 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
71 struct GNUNET_CRYPTO_EcdsaPublicKey iss_key;
72 struct GNUNET_CRYPTO_EcdsaSignature signature;
73 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
74 char* audience;
75 char* issuer;
76 char* header;
77 char* padding;
78 char* body_str;
79 char* result;
80 char* header_base64;
81 char* body_base64;
82 char* signature_target;
83 char* signature_base64;
84 char* attr_val_str;
85 json_t* body;
86
87 GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &iss_key);
88 /* TODO maybe we should use a local identity here */
89 issuer = GNUNET_STRINGS_data_to_string_alloc (&iss_key,
90 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
91 audience = GNUNET_STRINGS_data_to_string_alloc (sub_key,
92 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
93 header = create_jwt_header ();
94 body = json_object ();
95 /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */
96 json_object_set_new (body,
97 "iss", json_string (issuer));
98 json_object_set_new (body,
99 "sub", json_string (issuer));
100 /* TODO what should be in here exactly? */
101 json_object_set_new (body,
102 "aud", json_string (audience));
103 for (le = attrs->list_head; NULL != le; le = le->next)
104 {
105 /**
106 * TODO here we should have a function that
107 * calls the Attribute plugins to create a
108 * json representation for its value
109 */
110 attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type,
111 le->claim->data,
112 le->claim->data_size);
113 json_object_set_new (body,
114 le->claim->name,
115 json_string (attr_val_str));
116 GNUNET_free (attr_val_str);
117 }
118 body_str = json_dumps (body, JSON_INDENT(0));
119 json_decref (body);
120
121 GNUNET_STRINGS_base64_encode (header,
122 strlen (header),
123 &header_base64);
124 //Remove GNUNET padding of base64
125 padding = strtok(header_base64, "=");
126 while (NULL != padding)
127 padding = strtok(NULL, "=");
128
129 GNUNET_STRINGS_base64_encode (body_str,
130 strlen (body_str),
131 &body_base64);
132
133 //Remove GNUNET padding of base64
134 padding = strtok(body_base64, "=");
135 while (NULL != padding)
136 padding = strtok(NULL, "=");
137
138 GNUNET_free (issuer);
139 GNUNET_free (audience);
140
141 /**
142 * TODO
143 * Creating the JWT signature. This might not be
144 * standards compliant, check.
145 */
146 GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64);
147
148 purpose =
149 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
150 strlen (signature_target));
151 purpose->size =
152 htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
153 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
154 GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
155 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
156 purpose,
157 (struct GNUNET_CRYPTO_EcdsaSignature *)&signature))
158 {
159 GNUNET_free (signature_target);
160 GNUNET_free (body_str);
161 GNUNET_free (body_base64);
162 GNUNET_free (header_base64);
163 GNUNET_free (purpose);
164 return NULL;
165 }
166 GNUNET_STRINGS_base64_encode ((const char*)&signature,
167 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
168 &signature_base64);
169 GNUNET_asprintf (&result, "%s.%s.%s",
170 header_base64, body_base64, signature_base64);
171
172 GNUNET_free (signature_target);
173 GNUNET_free (header);
174 GNUNET_free (body_str);
175 GNUNET_free (signature_base64);
176 GNUNET_free (body_base64);
177 GNUNET_free (header_base64);
178 GNUNET_free (purpose);
179 return result;
180}
diff --git a/src/identity/plugin_gnsrecord_identity.c b/src/identity-provider/plugin_gnsrecord_identity_provider.c
index c26c04074..6ed0b0852 100644
--- a/src/identity/plugin_gnsrecord_identity.c
+++ b/src/identity-provider/plugin_gnsrecord_identity_provider.c
@@ -19,9 +19,9 @@
19*/ 19*/
20 20
21/** 21/**
22 * @file identity/plugin_gnsrecord_identity.c 22 * @file identity-provider/plugin_gnsrecord_identity_provider.c
23 * @brief gnsrecord plugin to provide the API for identity records 23 * @brief gnsrecord plugin to provide the API for identity records
24 * @author Christian Grothoff 24 * @author Martin Schanzenbach
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
@@ -54,9 +54,13 @@ value_to_string (void *cls,
54 switch (type) 54 switch (type)
55 { 55 {
56 case GNUNET_GNSRECORD_TYPE_ID_ATTR: 56 case GNUNET_GNSRECORD_TYPE_ID_ATTR:
57 case GNUNET_GNSRECORD_TYPE_ID_TOKEN: 57 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
58 case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED
58 return GNUNET_strndup (data, data_size); 59 return GNUNET_strndup (data, data_size);
59 case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: 60 case GNUNET_GNSRECORD_TYPE_ABE_KEY:
61 case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
62 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
63 case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED
60 ecdhe_privkey = data; 64 ecdhe_privkey = data;
61 audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); 65 audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
62 scopes = (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 66 scopes = (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
@@ -106,12 +110,22 @@ string_to_value (void *cls,
106 switch (type) 110 switch (type)
107 { 111 {
108 case GNUNET_GNSRECORD_TYPE_ID_ATTR: 112 case GNUNET_GNSRECORD_TYPE_ID_ATTR:
113 return GNUNET_STRINGS_string_to_data (s,
114 strlen (s),
115 *data,
116 *data_size);
109 case GNUNET_GNSRECORD_TYPE_ID_TOKEN: 117 case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
110 *data = GNUNET_strdup (s); 118 *data = GNUNET_strdup (s);
111 *data_size = strlen (s); 119 *data_size = strlen (s);
112 return GNUNET_OK; 120 return GNUNET_OK;
121 case GNUNET_GNSRECORD_TYPE_ABE_KEY:
122 case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
123 return GNUNET_STRINGS_string_to_data (s,
124 strlen (s),
125 *data,
126 *data_size);
113 case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: 127 case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
114 tmp_tok = GNUNET_strdup (s); 128 tmp_tok = GNUNET_strdup (s);
115 ecdhe_str = strtok (tmp_tok, ";"); 129 ecdhe_str = strtok (tmp_tok, ";");
116 if (NULL == ecdhe_str) 130 if (NULL == ecdhe_str)
117 { 131 {
@@ -160,15 +174,17 @@ string_to_value (void *cls,
160 * Mapping of record type numbers to human-readable 174 * Mapping of record type numbers to human-readable
161 * record type names. 175 * record type names.
162 */ 176 */
163 static struct { 177static struct {
164 const char *name; 178 const char *name;
165 uint32_t number; 179 uint32_t number;
166 } name_map[] = { 180} name_map[] = {
167 { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR }, 181 { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
168 { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN }, 182 { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
169 { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA }, 183 { "ABE_KEY", GNUNET_GNSRECORD_TYPE_ABE_KEY },
170 { NULL, UINT32_MAX } 184 { "ABE_MASTER", GNUNET_GNSRECORD_TYPE_ABE_MASTER },
171 }; 185 { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
186 { NULL, UINT32_MAX }
187};
172 188
173 189
174/** 190/**
@@ -220,7 +236,7 @@ number_to_typename (void *cls,
220 * @return the exported block API 236 * @return the exported block API
221 */ 237 */
222void * 238void *
223libgnunet_plugin_gnsrecord_identity_init (void *cls) 239libgnunet_plugin_gnsrecord_identity_provider_init (void *cls)
224{ 240{
225 struct GNUNET_GNSRECORD_PluginFunctions *api; 241 struct GNUNET_GNSRECORD_PluginFunctions *api;
226 242
@@ -240,7 +256,7 @@ libgnunet_plugin_gnsrecord_identity_init (void *cls)
240 * @return NULL 256 * @return NULL
241 */ 257 */
242void * 258void *
243libgnunet_plugin_gnsrecord_identity_done (void *cls) 259libgnunet_plugin_gnsrecord_identity_provider_done (void *cls)
244{ 260{
245 struct GNUNET_GNSRECORD_PluginFunctions *api = cls; 261 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
246 262
diff --git a/src/identity-provider/plugin_identity_provider_sqlite.c b/src/identity-provider/plugin_identity_provider_sqlite.c
new file mode 100644
index 000000000..0071528b9
--- /dev/null
+++ b/src/identity-provider/plugin_identity_provider_sqlite.c
@@ -0,0 +1,736 @@
1 /*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2017 GNUnet e.V.
4 *
5 * GNUnet is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 3, or (at your
8 * option) any later version.
9 *
10 * GNUnet is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GNUnet; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21/**
22 * @file identity-provider/plugin_identity_provider_sqlite.c
23 * @brief sqlite-based idp backend
24 * @author Martin Schanzenbach
25 */
26
27#include "platform.h"
28#include "gnunet_identity_provider_service.h"
29#include "gnunet_identity_provider_plugin.h"
30#include "gnunet_identity_attribute_lib.h"
31#include "gnunet_sq_lib.h"
32#include <sqlite3.h>
33
34/**
35 * After how many ms "busy" should a DB operation fail for good? A
36 * low value makes sure that we are more responsive to requests
37 * (especially PUTs). A high value guarantees a higher success rate
38 * (SELECTs in iterate can take several seconds despite LIMIT=1).
39 *
40 * The default value of 1s should ensure that users do not experience
41 * huge latencies while at the same time allowing operations to
42 * succeed with reasonable probability.
43 */
44#define BUSY_TIMEOUT_MS 1000
45
46
47/**
48 * Log an error message at log-level 'level' that indicates
49 * a failure of the command 'cmd' on file 'filename'
50 * with the message given by strerror(errno).
51 */
52#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "identity-provider", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
53
54#define LOG(kind,...) GNUNET_log_from (kind, "identity-provider-sqlite", __VA_ARGS__)
55
56
57/**
58 * Context for all functions in this plugin.
59 */
60struct Plugin
61{
62
63 const struct GNUNET_CONFIGURATION_Handle *cfg;
64
65 /**
66 * Database filename.
67 */
68 char *fn;
69
70 /**
71 * Native SQLite database handle.
72 */
73 sqlite3 *dbh;
74
75 /**
76 * Precompiled SQL to store ticket.
77 */
78 sqlite3_stmt *store_ticket;
79
80 /**
81 * Precompiled SQL to delete existing ticket.
82 */
83 sqlite3_stmt *delete_ticket;
84
85 /**
86 * Precompiled SQL to iterate tickets.
87 */
88 sqlite3_stmt *iterate_tickets;
89
90 /**
91 * Precompiled SQL to get ticket attributes.
92 */
93 sqlite3_stmt *get_ticket_attrs;
94
95 /**
96 * Precompiled SQL to iterate tickets by audience.
97 */
98 sqlite3_stmt *iterate_tickets_by_audience;
99};
100
101
102/**
103 * @brief Prepare a SQL statement
104 *
105 * @param dbh handle to the database
106 * @param zSql SQL statement, UTF-8 encoded
107 * @param ppStmt set to the prepared statement
108 * @return 0 on success
109 */
110static int
111sq_prepare (sqlite3 *dbh,
112 const char *zSql,
113 sqlite3_stmt **ppStmt)
114{
115 char *dummy;
116 int result;
117
118 result =
119 sqlite3_prepare_v2 (dbh,
120 zSql,
121 strlen (zSql),
122 ppStmt,
123 (const char **) &dummy);
124 LOG (GNUNET_ERROR_TYPE_DEBUG,
125 "Prepared `%s' / %p: %d\n",
126 zSql,
127 *ppStmt,
128 result);
129 return result;
130}
131
132/**
133 * Create our database indices.
134 *
135 * @param dbh handle to the database
136 */
137static void
138create_indices (sqlite3 * dbh)
139{
140 /* create indices */
141 if ( (SQLITE_OK !=
142 sqlite3_exec (dbh,
143 "CREATE INDEX IF NOT EXISTS identity_reverse ON identity001tickets (identity,audience)",
144 NULL, NULL, NULL)) ||
145 (SQLITE_OK !=
146 sqlite3_exec (dbh,
147 "CREATE INDEX IF NOT EXISTS it_iter ON identity001tickets (rnd)",
148 NULL, NULL, NULL)) )
149 LOG (GNUNET_ERROR_TYPE_ERROR,
150 "Failed to create indices: %s\n",
151 sqlite3_errmsg (dbh));
152}
153
154
155
156#if 0
157#define CHECK(a) GNUNET_break(a)
158#define ENULL NULL
159#else
160#define ENULL &e
161#define ENULL_DEFINED 1
162#define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
163#endif
164
165
166/**
167 * Initialize the database connections and associated
168 * data structures (create tables and indices
169 * as needed as well).
170 *
171 * @param plugin the plugin context (state for this module)
172 * @return #GNUNET_OK on success
173 */
174static int
175database_setup (struct Plugin *plugin)
176{
177 sqlite3_stmt *stmt;
178 char *afsdir;
179#if ENULL_DEFINED
180 char *e;
181#endif
182
183 if (GNUNET_OK !=
184 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
185 "identity-provider-sqlite",
186 "FILENAME",
187 &afsdir))
188 {
189 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
190 "identity-provider-sqlite",
191 "FILENAME");
192 return GNUNET_SYSERR;
193 }
194 if (GNUNET_OK !=
195 GNUNET_DISK_file_test (afsdir))
196 {
197 if (GNUNET_OK !=
198 GNUNET_DISK_directory_create_for_file (afsdir))
199 {
200 GNUNET_break (0);
201 GNUNET_free (afsdir);
202 return GNUNET_SYSERR;
203 }
204 }
205 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
206 plugin->fn = afsdir;
207
208 /* Open database and precompile statements */
209 if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
210 {
211 LOG (GNUNET_ERROR_TYPE_ERROR,
212 _("Unable to initialize SQLite: %s.\n"),
213 sqlite3_errmsg (plugin->dbh));
214 return GNUNET_SYSERR;
215 }
216 CHECK (SQLITE_OK ==
217 sqlite3_exec (plugin->dbh,
218 "PRAGMA temp_store=MEMORY", NULL, NULL,
219 ENULL));
220 CHECK (SQLITE_OK ==
221 sqlite3_exec (plugin->dbh,
222 "PRAGMA synchronous=NORMAL", NULL, NULL,
223 ENULL));
224 CHECK (SQLITE_OK ==
225 sqlite3_exec (plugin->dbh,
226 "PRAGMA legacy_file_format=OFF", NULL, NULL,
227 ENULL));
228 CHECK (SQLITE_OK ==
229 sqlite3_exec (plugin->dbh,
230 "PRAGMA auto_vacuum=INCREMENTAL", NULL,
231 NULL, ENULL));
232 CHECK (SQLITE_OK ==
233 sqlite3_exec (plugin->dbh,
234 "PRAGMA encoding=\"UTF-8\"", NULL,
235 NULL, ENULL));
236 CHECK (SQLITE_OK ==
237 sqlite3_exec (plugin->dbh,
238 "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
239 ENULL));
240 CHECK (SQLITE_OK ==
241 sqlite3_exec (plugin->dbh,
242 "PRAGMA page_size=4092", NULL, NULL,
243 ENULL));
244
245 CHECK (SQLITE_OK ==
246 sqlite3_busy_timeout (plugin->dbh,
247 BUSY_TIMEOUT_MS));
248
249
250 /* Create table */
251 CHECK (SQLITE_OK ==
252 sq_prepare (plugin->dbh,
253 "SELECT 1 FROM sqlite_master WHERE tbl_name = 'identity001tickets'",
254 &stmt));
255 if ((sqlite3_step (stmt) == SQLITE_DONE) &&
256 (sqlite3_exec
257 (plugin->dbh,
258 "CREATE TABLE identity001tickets ("
259 " identity BLOB NOT NULL DEFAULT '',"
260 " audience BLOB NOT NULL DEFAULT '',"
261 " rnd INT8 NOT NULL DEFAULT '',"
262 " attributes BLOB NOT NULL DEFAULT ''"
263 ")",
264 NULL, NULL, NULL) != SQLITE_OK))
265 {
266 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR,
267 "sqlite3_exec");
268 sqlite3_finalize (stmt);
269 return GNUNET_SYSERR;
270 }
271 sqlite3_finalize (stmt);
272
273 create_indices (plugin->dbh);
274
275 if ( (SQLITE_OK !=
276 sq_prepare (plugin->dbh,
277 "INSERT INTO identity001tickets (identity, audience, rnd, attributes)"
278 " VALUES (?, ?, ?, ?)",
279 &plugin->store_ticket)) ||
280 (SQLITE_OK !=
281 sq_prepare (plugin->dbh,
282 "DELETE FROM identity001tickets WHERE identity=? AND rnd=?",
283 &plugin->delete_ticket)) ||
284 (SQLITE_OK !=
285 sq_prepare (plugin->dbh,
286 "SELECT identity,audience,rnd,attributes"
287 " FROM identity001tickets WHERE identity=? AND rnd=?",
288 &plugin->get_ticket_attrs)) ||
289 (SQLITE_OK !=
290 sq_prepare (plugin->dbh,
291 "SELECT identity,audience,rnd,attributes"
292 " FROM identity001tickets WHERE identity=?"
293 " ORDER BY rnd LIMIT 1 OFFSET ?",
294 &plugin->iterate_tickets)) ||
295 (SQLITE_OK !=
296 sq_prepare (plugin->dbh,
297 "SELECT identity,audience,rnd,attributes"
298 " FROM identity001tickets WHERE audience=?"
299 " ORDER BY rnd LIMIT 1 OFFSET ?",
300 &plugin->iterate_tickets_by_audience)) )
301 {
302 LOG_SQLITE (plugin,
303 GNUNET_ERROR_TYPE_ERROR,
304 "precompiling");
305 return GNUNET_SYSERR;
306 }
307 return GNUNET_OK;
308}
309
310
311/**
312 * Shutdown database connection and associate data
313 * structures.
314 * @param plugin the plugin context (state for this module)
315 */
316static void
317database_shutdown (struct Plugin *plugin)
318{
319 int result;
320 sqlite3_stmt *stmt;
321
322 if (NULL != plugin->store_ticket)
323 sqlite3_finalize (plugin->store_ticket);
324 if (NULL != plugin->delete_ticket)
325 sqlite3_finalize (plugin->delete_ticket);
326 if (NULL != plugin->iterate_tickets)
327 sqlite3_finalize (plugin->iterate_tickets);
328 if (NULL != plugin->iterate_tickets_by_audience)
329 sqlite3_finalize (plugin->iterate_tickets_by_audience);
330 if (NULL != plugin->get_ticket_attrs)
331 sqlite3_finalize (plugin->get_ticket_attrs);
332 result = sqlite3_close (plugin->dbh);
333 if (result == SQLITE_BUSY)
334 {
335 LOG (GNUNET_ERROR_TYPE_WARNING,
336 _("Tried to close sqlite without finalizing all prepared statements.\n"));
337 stmt = sqlite3_next_stmt (plugin->dbh,
338 NULL);
339 while (NULL != stmt)
340 {
341 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
342 "sqlite",
343 "Closing statement %p\n",
344 stmt);
345 result = sqlite3_finalize (stmt);
346 if (result != SQLITE_OK)
347 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
348 "sqlite",
349 "Failed to close statement %p: %d\n",
350 stmt,
351 result);
352 stmt = sqlite3_next_stmt (plugin->dbh,
353 NULL);
354 }
355 result = sqlite3_close (plugin->dbh);
356 }
357 if (SQLITE_OK != result)
358 LOG_SQLITE (plugin,
359 GNUNET_ERROR_TYPE_ERROR,
360 "sqlite3_close");
361
362 GNUNET_free_non_null (plugin->fn);
363}
364
365
366/**
367 * Store a ticket in the database.
368 *
369 * @param cls closure (internal context for the plugin)
370 * @param ticket the ticket to persist
371 * @param attrs the attributes associated with the ticket
372 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
373 */
374static int
375identity_provider_sqlite_store_ticket (void *cls,
376 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
377 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
378{
379 struct Plugin *plugin = cls;
380 size_t attrs_len;
381 char *attrs_ser;
382 int n;
383
384 {
385 /* First delete duplicates */
386 struct GNUNET_SQ_QueryParam dparams[] = {
387 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
388 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
389 GNUNET_SQ_query_param_end
390 };
391 if (GNUNET_OK !=
392 GNUNET_SQ_bind (plugin->delete_ticket,
393 dparams))
394 {
395 LOG_SQLITE (plugin,
396 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
397 "sqlite3_bind_XXXX");
398 GNUNET_SQ_reset (plugin->dbh,
399 plugin->delete_ticket);
400 return GNUNET_SYSERR;
401 }
402 n = sqlite3_step (plugin->delete_ticket);
403 GNUNET_SQ_reset (plugin->dbh,
404 plugin->delete_ticket);
405
406 attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
407 attrs_ser = GNUNET_malloc (attrs_len);
408 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
409 attrs_ser);
410 struct GNUNET_SQ_QueryParam sparams[] = {
411 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
412 GNUNET_SQ_query_param_auto_from_type (&ticket->audience),
413 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
414 GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len),
415 GNUNET_SQ_query_param_end
416 };
417
418 if (GNUNET_OK !=
419 GNUNET_SQ_bind (plugin->store_ticket,
420 sparams))
421 {
422 LOG_SQLITE (plugin,
423 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
424 "sqlite3_bind_XXXX");
425 GNUNET_SQ_reset (plugin->dbh,
426 plugin->store_ticket);
427 return GNUNET_SYSERR;
428 }
429 n = sqlite3_step (plugin->store_ticket);
430 GNUNET_SQ_reset (plugin->dbh,
431 plugin->store_ticket);
432 GNUNET_free (attrs_ser);
433 }
434 switch (n)
435 {
436 case SQLITE_DONE:
437 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
438 "sqlite",
439 "Ticket stored\n");
440 return GNUNET_OK;
441 case SQLITE_BUSY:
442 LOG_SQLITE (plugin,
443 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
444 "sqlite3_step");
445 return GNUNET_NO;
446 default:
447 LOG_SQLITE (plugin,
448 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
449 "sqlite3_step");
450 return GNUNET_SYSERR;
451 }
452}
453
454
455/**
456 * Store a ticket in the database.
457 *
458 * @param cls closure (internal context for the plugin)
459 * @param ticket the ticket to delete
460 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
461 */
462static int
463identity_provider_sqlite_delete_ticket (void *cls,
464 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
465{
466 struct Plugin *plugin = cls;
467 int n;
468
469 {
470 struct GNUNET_SQ_QueryParam sparams[] = {
471 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
472 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
473 GNUNET_SQ_query_param_end
474 };
475
476 if (GNUNET_OK !=
477 GNUNET_SQ_bind (plugin->delete_ticket,
478 sparams))
479 {
480 LOG_SQLITE (plugin,
481 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
482 "sqlite3_bind_XXXX");
483 GNUNET_SQ_reset (plugin->dbh,
484 plugin->store_ticket);
485 return GNUNET_SYSERR;
486 }
487 n = sqlite3_step (plugin->delete_ticket);
488 GNUNET_SQ_reset (plugin->dbh,
489 plugin->delete_ticket);
490 }
491 switch (n)
492 {
493 case SQLITE_DONE:
494 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
495 "sqlite",
496 "Ticket deleted\n");
497 return GNUNET_OK;
498 case SQLITE_BUSY:
499 LOG_SQLITE (plugin,
500 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
501 "sqlite3_step");
502 return GNUNET_NO;
503 default:
504 LOG_SQLITE (plugin,
505 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
506 "sqlite3_step");
507 return GNUNET_SYSERR;
508 }
509}
510
511
512/**
513 * The given 'sqlite' statement has been prepared to be run.
514 * It will return a record which should be given to the iterator.
515 * Runs the statement and parses the returned record.
516 *
517 * @param plugin plugin context
518 * @param stmt to run (and then clean up)
519 * @param iter iterator to call with the result
520 * @param iter_cls closure for @a iter
521 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
522 */
523static int
524get_ticket_and_call_iterator (struct Plugin *plugin,
525 sqlite3_stmt *stmt,
526 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
527 void *iter_cls)
528{
529 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
530 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
531 int ret;
532 int sret;
533 size_t attrs_len;
534 char *attrs_ser;
535
536 ret = GNUNET_NO;
537 if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
538 {
539 struct GNUNET_SQ_ResultSpec rs[] = {
540 GNUNET_SQ_result_spec_auto_from_type (&ticket.identity),
541 GNUNET_SQ_result_spec_auto_from_type (&ticket.audience),
542 GNUNET_SQ_result_spec_uint64 (&ticket.rnd),
543 GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser,
544 &attrs_len),
545 GNUNET_SQ_result_spec_end
546
547 };
548 ret = GNUNET_SQ_extract_result (stmt,
549 rs);
550 if (GNUNET_OK != ret)
551 {
552 GNUNET_break (0);
553 ret = GNUNET_SYSERR;
554 }
555 else
556 {
557 attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (attrs_ser,
558 attrs_len);
559 if (NULL != iter)
560 iter (iter_cls,
561 &ticket,
562 attrs);
563 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
564 ret = GNUNET_YES;
565 }
566 GNUNET_SQ_cleanup_result (rs);
567 }
568 else
569 {
570 if (SQLITE_DONE != sret)
571 LOG_SQLITE (plugin,
572 GNUNET_ERROR_TYPE_ERROR,
573 "sqlite_step");
574 }
575 GNUNET_SQ_reset (plugin->dbh,
576 stmt);
577 return ret;
578}
579
580
581/**
582 * Lookup tickets in the datastore.
583 *
584 * @param cls closure (internal context for the plugin)
585 * @param ticket the ticket to retrieve attributes for
586 * @param iter function to call with the result
587 * @param iter_cls closure for @a iter
588 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
589 */
590static int
591identity_provider_sqlite_ticket_get_attrs (void *cls,
592 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
593 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
594 void *iter_cls)
595{
596 struct Plugin *plugin = cls;
597 struct GNUNET_SQ_QueryParam params[] = {
598 GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
599 GNUNET_SQ_query_param_uint64 (&ticket->rnd),
600 GNUNET_SQ_query_param_end
601 };
602
603 if (GNUNET_OK !=
604 GNUNET_SQ_bind (plugin->get_ticket_attrs,
605 params))
606 {
607 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
608 "sqlite3_bind_XXXX");
609 GNUNET_SQ_reset (plugin->dbh,
610 plugin->get_ticket_attrs);
611 return GNUNET_SYSERR;
612 }
613 return get_ticket_and_call_iterator (plugin,
614 plugin->get_ticket_attrs,
615 iter,
616 iter_cls);
617}
618
619
620/**
621 * Iterate over the results for a particular key and zone in the
622 * datastore. Will return at most one result to the iterator.
623 *
624 * @param cls closure (internal context for the plugin)
625 * @param identity the issuing identity or audience (depending on audience switch)
626 * @param audience GNUNET_YES if identity is audience
627 * @param offset offset in the list of all matching records
628 * @param iter function to call with the result
629 * @param iter_cls closure for @a iter
630 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
631 */
632static int
633identity_provider_sqlite_iterate_tickets (void *cls,
634 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
635 int audience,
636 uint64_t offset,
637 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
638 void *iter_cls)
639{
640 struct Plugin *plugin = cls;
641 sqlite3_stmt *stmt;
642 int err;
643
644 if (NULL == identity)
645 {
646 GNUNET_break (0);
647 return GNUNET_SYSERR;
648 }
649 struct GNUNET_SQ_QueryParam params[] = {
650 GNUNET_SQ_query_param_auto_from_type (identity),
651 GNUNET_SQ_query_param_uint64 (&offset),
652 GNUNET_SQ_query_param_end
653 };
654 if (GNUNET_YES == audience)
655 {
656 stmt = plugin->iterate_tickets_by_audience;
657 err = GNUNET_SQ_bind (stmt,
658 params);
659 }
660 else
661 {
662 stmt = plugin->iterate_tickets;
663 err = GNUNET_SQ_bind (stmt,
664 params);
665 }
666 if (GNUNET_OK != err)
667 {
668 LOG_SQLITE (plugin,
669 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
670 "sqlite3_bind_XXXX");
671 GNUNET_SQ_reset (plugin->dbh,
672 stmt);
673 return GNUNET_SYSERR;
674 }
675 return get_ticket_and_call_iterator (plugin,
676 stmt,
677 iter,
678 iter_cls);
679}
680
681
682/**
683 * Entry point for the plugin.
684 *
685 * @param cls the "struct GNUNET_IDENTITY_PROVIDER_PluginEnvironment*"
686 * @return NULL on error, otherwise the plugin context
687 */
688void *
689libgnunet_plugin_identity_provider_sqlite_init (void *cls)
690{
691 static struct Plugin plugin;
692 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
693 struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api;
694
695 if (NULL != plugin.cfg)
696 return NULL; /* can only initialize once! */
697 memset (&plugin, 0, sizeof (struct Plugin));
698 plugin.cfg = cfg;
699 if (GNUNET_OK != database_setup (&plugin))
700 {
701 database_shutdown (&plugin);
702 return NULL;
703 }
704 api = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_PluginFunctions);
705 api->cls = &plugin;
706 api->store_ticket = &identity_provider_sqlite_store_ticket;
707 api->delete_ticket = &identity_provider_sqlite_delete_ticket;
708 api->iterate_tickets = &identity_provider_sqlite_iterate_tickets;
709 api->get_ticket_attributes = &identity_provider_sqlite_ticket_get_attrs;
710 LOG (GNUNET_ERROR_TYPE_INFO,
711 _("Sqlite database running\n"));
712 return api;
713}
714
715
716/**
717 * Exit point from the plugin.
718 *
719 * @param cls the plugin context (as returned by "init")
720 * @return always NULL
721 */
722void *
723libgnunet_plugin_identity_provider_sqlite_done (void *cls)
724{
725 struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api = cls;
726 struct Plugin *plugin = api->cls;
727
728 database_shutdown (plugin);
729 plugin->cfg = NULL;
730 GNUNET_free (api);
731 LOG (GNUNET_ERROR_TYPE_DEBUG,
732 "sqlite plugin is finished\n");
733 return NULL;
734}
735
736/* end of plugin_identity_provider_sqlite.c */
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c
index 907b28ba9..6eb856435 100644
--- a/src/identity-provider/plugin_rest_identity_provider.c
+++ b/src/identity-provider/plugin_rest_identity_provider.c
@@ -37,6 +37,7 @@
37#include <jansson.h> 37#include <jansson.h>
38#include <inttypes.h> 38#include <inttypes.h>
39#include "gnunet_signatures.h" 39#include "gnunet_signatures.h"
40#include "gnunet_identity_attribute_lib.h"
40#include "gnunet_identity_provider_service.h" 41#include "gnunet_identity_provider_service.h"
41 42
42/** 43/**
@@ -45,39 +46,40 @@
45#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp" 46#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp"
46 47
47/** 48/**
48 * Issue namespace 49 * Attribute namespace
49 */ 50 */
50#define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/idp/issue" 51#define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes"
51 52
52/** 53/**
53 * Check namespace TODO 54 * Ticket namespace
54 */ 55 */
55#define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/idp/check" 56#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets"
56 57
57/** 58/**
58 * Token namespace 59 * Revoke namespace
59 */ 60 */
60#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token" 61#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke"
61 62
62/** 63/**
63 * The parameter name in which the ticket must be provided 64 * Revoke namespace
64 */ 65 */
65#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket" 66#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume"
66 67
67/** 68/**
68 * The parameter name in which the expected nonce must be provided 69 * Attribute key
69 */ 70 */
70#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce" 71#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute"
71 72
72/** 73/**
73 * The parameter name in which the ticket must be provided 74 * Ticket key
74 */ 75 */
75#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token" 76#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
77
76 78
77/** 79/**
78 * The URL parameter name in which the nonce must be provided 80 * Value key
79 */ 81 */
80#define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce" 82#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value"
81 83
82/** 84/**
83 * State while collecting all egos 85 * State while collecting all egos
@@ -89,41 +91,6 @@
89 */ 91 */
90#define ID_REST_STATE_POST_INIT 1 92#define ID_REST_STATE_POST_INIT 1
91 93
92/**
93 * Resource type
94 */
95#define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
96
97/**
98 * URL parameter to create a GNUid token for a specific audience
99 */
100#define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
101
102/**
103 * URL parameter to create a GNUid token for a specific issuer (EGO)
104 */
105#define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
106
107/**
108 * Attributes passed to issue request
109 */
110#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
111
112/**
113 * Token expiration string
114 */
115#define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
116
117/**
118 * Error messages
119 */
120#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
121#define GNUNET_REST_ERROR_NO_DATA "No data"
122
123/**
124 * GNUid token lifetime
125 */
126#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
127 94
128/** 95/**
129 * The configuration handle 96 * The configuration handle
@@ -198,11 +165,6 @@ struct RequestHandle
198 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 165 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
199 166
200 /** 167 /**
201 * Handle to the rest connection
202 */
203 struct GNUNET_REST_RequestHandle *conndata_handle;
204
205 /**
206 * The processing state 168 * The processing state
207 */ 169 */
208 int state; 170 int state;
@@ -213,6 +175,12 @@ struct RequestHandle
213 struct GNUNET_IDENTITY_Handle *identity_handle; 175 struct GNUNET_IDENTITY_Handle *identity_handle;
214 176
215 /** 177 /**
178 * Rest connection
179 */
180 struct GNUNET_REST_RequestHandle *rest_handle;
181
182
183 /**
216 * IDENTITY Operation 184 * IDENTITY Operation
217 */ 185 */
218 struct GNUNET_IDENTITY_Operation *op; 186 struct GNUNET_IDENTITY_Operation *op;
@@ -228,19 +196,14 @@ struct RequestHandle
228 struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; 196 struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
229 197
230 /** 198 /**
231 * Handle to NS service 199 * Attribute iterator
232 */
233 struct GNUNET_NAMESTORE_Handle *ns_handle;
234
235 /**
236 * NS iterator
237 */ 200 */
238 struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 201 struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
239 202
240 /** 203 /**
241 * NS Handle 204 * Ticket iterator
242 */ 205 */
243 struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 206 struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
244 207
245 /** 208 /**
246 * Desired timeout for the lookup (default is no timeout). 209 * Desired timeout for the lookup (default is no timeout).
@@ -285,6 +248,7 @@ struct RequestHandle
285}; 248};
286 249
287 250
251
288/** 252/**
289 * Cleanup lookup handle 253 * Cleanup lookup handle
290 * @param handle Handle to clean up 254 * @param handle Handle to clean up
@@ -302,14 +266,12 @@ cleanup_handle (struct RequestHandle *handle)
302 GNUNET_SCHEDULER_cancel (handle->timeout_task); 266 GNUNET_SCHEDULER_cancel (handle->timeout_task);
303 if (NULL != handle->identity_handle) 267 if (NULL != handle->identity_handle)
304 GNUNET_IDENTITY_disconnect (handle->identity_handle); 268 GNUNET_IDENTITY_disconnect (handle->identity_handle);
269 if (NULL != handle->attr_it)
270 GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it);
271 if (NULL != handle->ticket_it)
272 GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it);
305 if (NULL != handle->idp) 273 if (NULL != handle->idp)
306 GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp); 274 GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
307 if (NULL != handle->ns_it)
308 GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
309 if (NULL != handle->ns_qe)
310 GNUNET_NAMESTORE_cancel (handle->ns_qe);
311 if (NULL != handle->ns_handle)
312 GNUNET_NAMESTORE_disconnect (handle->ns_handle);
313 if (NULL != handle->url) 275 if (NULL != handle->url)
314 GNUNET_free (handle->url); 276 GNUNET_free (handle->url);
315 if (NULL != handle->emsg) 277 if (NULL != handle->emsg)
@@ -326,6 +288,12 @@ cleanup_handle (struct RequestHandle *handle)
326 GNUNET_free (handle); 288 GNUNET_free (handle);
327} 289}
328 290
291static void
292cleanup_handle_delayed (void *cls)
293{
294 cleanup_handle (cls);
295}
296
329 297
330/** 298/**
331 * Task run on error, sends error message. Cleans up everything. 299 * Task run on error, sends error message. Cleans up everything.
@@ -363,622 +331,663 @@ do_timeout (void *cls)
363} 331}
364 332
365 333
366/**
367 * Task run on shutdown. Cleans up everything.
368 *
369 * @param cls unused
370 */
371static void 334static void
372do_cleanup_handle_delayed (void *cls) 335collect_error_cb (void *cls)
373{ 336{
374 struct RequestHandle *handle = cls; 337 struct RequestHandle *handle = cls;
375 338
376 cleanup_handle (handle); 339 do_error (handle);
377} 340}
378 341
379
380/**
381 * Get a ticket for identity
382 * @param cls the handle
383 * @param ticket the ticket returned from the idp
384 */
385static void 342static void
386token_creat_cont (void *cls, 343finished_cont (void *cls,
387 const char *label, 344 int32_t success,
388 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, 345 const char *emsg)
389 const struct GNUNET_IDENTITY_PROVIDER_Token *token)
390{ 346{
391 struct GNUNET_JSONAPI_Resource *json_resource;
392 struct RequestHandle *handle = cls; 347 struct RequestHandle *handle = cls;
393 struct MHD_Response *resp; 348 struct MHD_Response *resp;
394 json_t *ticket_json;
395 json_t *token_json;
396 char *ticket_str;
397 char *token_str;
398 char *result_str;
399 349
400 if (NULL == ticket) 350 resp = GNUNET_REST_create_response (emsg);
351 if (GNUNET_OK != success)
401 { 352 {
402 handle->emsg = GNUNET_strdup ("Error in token issue");
403 GNUNET_SCHEDULER_add_now (&do_error, handle); 353 GNUNET_SCHEDULER_add_now (&do_error, handle);
404 return; 354 return;
405 } 355 }
356 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
357 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
358}
406 359
407 handle->resp_object = GNUNET_JSONAPI_document_new (); 360
408 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 361/**
409 label); 362 * Return attributes for identity
410 ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket); 363 *
411 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token); 364 * @param cls the request handle
412 ticket_json = json_string (ticket_str); 365 */
413 token_json = json_string (token_str); 366static void
414 GNUNET_JSONAPI_resource_add_attr (json_resource, 367return_response (void *cls)
415 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 368{
416 ticket_json); 369 char* result_str;
417 GNUNET_JSONAPI_resource_add_attr (json_resource, 370 struct RequestHandle *handle = cls;
418 GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN, 371 struct MHD_Response *resp;
419 token_json);
420 GNUNET_free (ticket_str);
421 GNUNET_free (token_str);
422 json_decref (ticket_json);
423 json_decref (token_json);
424 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
425 372
426 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str); 373 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
428 resp = GNUNET_REST_create_response (result_str); 375 resp = GNUNET_REST_create_response (result_str);
429 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 376 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
430 GNUNET_free (result_str); 377 GNUNET_free (result_str);
431 GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle); 378 cleanup_handle (handle);
379}
380
381
382static void
383collect_finished_cb (void *cls)
384{
385 struct RequestHandle *handle = cls;
386 //Done
387 handle->attr_it = NULL;
388 handle->ticket_it = NULL;
389 GNUNET_SCHEDULER_add_now (&return_response, handle);
432} 390}
433 391
434 392
435/** 393/**
436 * Continueationf for token issue request 394 * Collect all attributes for an ego
437 * 395 *
438 * @param con the Rest handle
439 * @param url the requested url
440 * @param cls the request handle
441 */ 396 */
442static void 397static void
443issue_token_cont (struct GNUNET_REST_RequestHandle *con, 398ticket_collect (void *cls,
444 const char *url, 399 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
445 void *cls)
446{ 400{
447 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 401 struct GNUNET_JSONAPI_Resource *json_resource;
448 const char *egoname; 402 struct RequestHandle *handle = cls;
403 json_t *value;
404 char* tmp;
405
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
407 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
408 sizeof (uint64_t));
409 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET,
410 tmp);
411 GNUNET_free (tmp);
412 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
413
414 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
415 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
416 value = json_string (tmp);
417 GNUNET_JSONAPI_resource_add_attr (json_resource,
418 "issuer",
419 value);
420 GNUNET_free (tmp);
421 json_decref (value);
422 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
423 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
424 value = json_string (tmp);
425 GNUNET_JSONAPI_resource_add_attr (json_resource,
426 "audience",
427 value);
428 GNUNET_free (tmp);
429 json_decref (value);
430 tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
431 sizeof (uint64_t));
432 value = json_string (tmp);
433 GNUNET_JSONAPI_resource_add_attr (json_resource,
434 "rnd",
435 value);
436 GNUNET_free (tmp);
437 json_decref (value);
438 GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (handle->ticket_it);
439}
440
449 441
442
443/**
444 * List tickets for identity request
445 *
446 * @param con_handle the connection handle
447 * @param url the url
448 * @param cls the RequestHandle
449 */
450static void
451list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
452 const char* url,
453 void *cls)
454{
455 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
450 struct RequestHandle *handle = cls; 456 struct RequestHandle *handle = cls;
451 struct EgoEntry *ego_entry; 457 struct EgoEntry *ego_entry;
452 struct GNUNET_HashCode key; 458 char *identity;
453 struct MHD_Response *resp; 459
454 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
455 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 461 handle->url);
456 struct GNUNET_TIME_Relative etime_rel; 462 if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
457 struct GNUNET_TIME_Absolute exp_time; 463 strlen (handle->url))
458 char *ego_val;
459 char *audience;
460 char *exp_str;
461 char *nonce_str;
462 char *scopes;
463 uint64_t time;
464 uint64_t nonce;
465
466 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
467 GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
468 {
469 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
470 resp = GNUNET_REST_create_response (NULL);
471 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
472 cleanup_handle (handle);
473 return;
474 }
475 egoname = NULL;
476 ego_entry = NULL;
477 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
478 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
479 &key);
480 if ( GNUNET_YES !=
481 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
482 &key) )
483 {
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
485 "Issuer not found\n");
486 GNUNET_SCHEDULER_add_now (&do_error, handle);
487 return;
488 }
489 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
490 &key);
491 if (NULL == ego_val)
492 { 464 {
465 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
493 GNUNET_SCHEDULER_add_now (&do_error, handle); 466 GNUNET_SCHEDULER_add_now (&do_error, handle);
494 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
495 "Ego invalid: %s\n",
496 ego_val);
497 return; 467 return;
498 } 468 }
469 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
470
499 for (ego_entry = handle->ego_head; 471 for (ego_entry = handle->ego_head;
500 NULL != ego_entry; 472 NULL != ego_entry;
501 ego_entry = ego_entry->next) 473 ego_entry = ego_entry->next)
474 if (0 == strcmp (identity, ego_entry->identifier))
475 break;
476 handle->resp_object = GNUNET_JSONAPI_document_new ();
477
478 if (NULL == ego_entry)
502 { 479 {
503 if (0 != strcmp (ego_val, ego_entry->identifier)) 480 //Done
504 continue; 481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
505 egoname = ego_entry->identifier; 482 identity);
506 break; 483 GNUNET_SCHEDULER_add_now (&return_response, handle);
507 }
508 if ( (NULL == egoname) ||
509 (NULL == ego_entry) )
510 {
511 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
512 "Ego not found: %s\n",
513 ego_val);
514 GNUNET_SCHEDULER_add_now (&do_error, handle);
515 return; 484 return;
516 } 485 }
517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 486 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
518 "Ego to issue token for: %s\n", 487 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
519 egoname); 488 handle->ticket_it = GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (handle->idp,
489 priv_key,
490 &collect_error_cb,
491 handle,
492 &ticket_collect,
493 handle,
494 &collect_finished_cb,
495 handle);
496}
520 497
521 498
522 //Meta info 499static void
523 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST, 500add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
524 strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST), 501 const char* url,
525 &key); 502 void *cls)
503{
504 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
505 const char* identity;
506 const char* name_str;
507 const char* value_str;
526 508
527 scopes = NULL; 509 struct RequestHandle *handle = cls;
528 if ( GNUNET_YES != 510 struct EgoEntry *ego_entry;
529 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 511 struct MHD_Response *resp;
530 &key) ) 512 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attribute;
513 struct GNUNET_JSONAPI_Document *json_obj;
514 struct GNUNET_JSONAPI_Resource *json_res;
515 char term_data[handle->rest_handle->data_size+1];
516 json_t *value_json;
517 json_t *data_json;
518 json_error_t err;
519 struct GNUNET_JSON_Specification docspec[] = {
520 GNUNET_JSON_spec_jsonapi_document (&json_obj),
521 GNUNET_JSON_spec_end()
522 };
523
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
525 handle->url);
526 if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
527 strlen (handle->url))
531 { 528 {
532 handle->emsg = GNUNET_strdup ("Scopes missing!\n"); 529 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
533 GNUNET_SCHEDULER_add_now (&do_error, handle); 530 GNUNET_SCHEDULER_add_now (&do_error, handle);
534 return; 531 return;
535 } 532 }
536 scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 533 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
537 &key); 534
538 535 for (ego_entry = handle->ego_head;
539 536 NULL != ego_entry;
540 //Token audience 537 ego_entry = ego_entry->next)
541 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST, 538 if (0 == strcmp (identity, ego_entry->identifier))
542 strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST), 539 break;
543 &key); 540
544 audience = NULL; 541 if (NULL == ego_entry)
545 if ( GNUNET_YES !=
546 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
547 &key) )
548 { 542 {
549 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 543 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
550 "Audience missing!\n"); 544 "Identity unknown (%s)\n", identity);
551 GNUNET_SCHEDULER_add_now (&do_error, handle); 545 GNUNET_JSONAPI_document_delete (json_obj);
552 return; 546 return;
553 } 547 }
554 audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 548 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
555 &key);
556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
557 "Audience to issue token for: %s\n",
558 audience);
559
560 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
561 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
562 &pub_key);
563 GNUNET_STRINGS_string_to_data (audience,
564 strlen (audience),
565 &aud_key,
566 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
567 549
568 //Remote nonce 550 if (0 >= handle->rest_handle->data_size)
569 nonce_str = NULL;
570 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
571 strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
572 &key);
573 if ( GNUNET_YES !=
574 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
575 &key) )
576 { 551 {
577 handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
578 GNUNET_SCHEDULER_add_now (&do_error, handle); 552 GNUNET_SCHEDULER_add_now (&do_error, handle);
579 return; 553 return;
580 } 554 }
581 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 555
582 &key); 556 term_data[handle->rest_handle->data_size] = '\0';
583 GNUNET_assert (NULL != nonce_str); 557 GNUNET_memcpy (term_data,
584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 558 handle->rest_handle->data,
585 "Request nonce: %s\n", 559 handle->rest_handle->data_size);
586 nonce_str); 560 data_json = json_loads (term_data,
587 GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce)); 561 JSON_DECODE_ANY,
588 562 &err);
589 //Get expiration for token from URL parameter 563 GNUNET_assert (GNUNET_OK ==
590 GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING, 564 GNUNET_JSON_parse (data_json, docspec,
591 strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING), 565 NULL, NULL));
592 &key); 566 json_decref (data_json);
593 567 if (NULL == json_obj)
594 exp_str = NULL;
595 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
596 &key))
597 { 568 {
598 exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 569 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
599 &key); 570 "Unable to parse JSONAPI Object from %s\n",
600 } 571 term_data);
601 if (NULL == exp_str) {
602 handle->emsg = GNUNET_strdup ("No expiration given!\n");
603 GNUNET_SCHEDULER_add_now (&do_error, handle); 572 GNUNET_SCHEDULER_add_now (&do_error, handle);
604 return; 573 return;
605 } 574 }
606 575 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
607 if (GNUNET_OK !=
608 GNUNET_STRINGS_fancy_time_to_relative (exp_str,
609 &etime_rel))
610 { 576 {
611 handle->emsg = GNUNET_strdup ("Expiration invalid!\n"); 577 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
578 "Cannot create more than 1 resource! (Got %d)\n",
579 GNUNET_JSONAPI_document_resource_count (json_obj));
580 GNUNET_JSONAPI_document_delete (json_obj);
612 GNUNET_SCHEDULER_add_now (&do_error, handle); 581 GNUNET_SCHEDULER_add_now (&do_error, handle);
613 return; 582 return;
614 } 583 }
615 time = GNUNET_TIME_absolute_get().abs_value_us; 584 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
616 exp_time.abs_value_us = time + etime_rel.rel_value_us; 585 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
617 586 GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE))
587 {
588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
589 "Unsupported JSON data type\n");
590 GNUNET_JSONAPI_document_delete (json_obj);
591 resp = GNUNET_REST_create_response (NULL);
592 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
593 cleanup_handle (handle);
594 return;
595 }
596 name_str = GNUNET_JSONAPI_resource_get_id (json_res);
597 value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
598 "value");
599 value_str = json_string_value (value_json);
600 attribute = GNUNET_IDENTITY_ATTRIBUTE_claim_new (name_str,
601 GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
602 value_str,
603 strlen (value_str) + 1);
618 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); 604 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
619 handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp, 605 handle->idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (handle->idp,
620 priv_key, 606 identity_priv,
621 &aud_key, 607 attribute,
622 scopes, 608 &finished_cont,
623 exp_time, 609 handle);
624 nonce, 610 GNUNET_free (attribute);
625 &token_creat_cont, 611 GNUNET_JSONAPI_document_delete (json_obj);
626 handle);
627
628}
629
630
631/**
632 * Build a GNUid token for identity
633 *
634 * @param cls the request handle
635 */
636static void
637return_token_list (void *cls)
638{
639 char* result_str;
640 struct RequestHandle *handle = cls;
641 struct MHD_Response *resp;
642
643 GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
645 resp = GNUNET_REST_create_response (result_str);
646 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
647 GNUNET_free (result_str);
648 cleanup_handle (handle);
649} 612}
650 613
651 614
652static void
653token_collect_error_cb (void *cls)
654{
655 struct RequestHandle *handle = cls;
656
657 do_error (handle);
658}
659
660 615
661/** 616/**
662 * Collect all tokens for an ego 617 * Collect all attributes for an ego
663 *
664 * TODO move this into the identity-provider service
665 * 618 *
666 */ 619 */
667static void 620static void
668token_collect (void *cls, 621attr_collect (void *cls,
669 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 622 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
670 const char *label, 623 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
671 unsigned int rd_count,
672 const struct GNUNET_GNSRECORD_Data *rd);
673
674
675static void
676token_collect_finished_cb (void *cls)
677{ 624{
625 struct GNUNET_JSONAPI_Resource *json_resource;
678 struct RequestHandle *handle = cls; 626 struct RequestHandle *handle = cls;
679 struct EgoEntry *ego_tmp; 627 json_t *value;
680 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 628
681 629 if ((NULL == attr->name) || (NULL == attr->data))
682 ego_tmp = handle->ego_head;
683 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
684 handle->ego_tail,
685 ego_tmp);
686 GNUNET_free (ego_tmp->identifier);
687 GNUNET_free (ego_tmp->keystring);
688 GNUNET_free (ego_tmp);
689
690 if (NULL == handle->ego_head)
691 { 630 {
692 //Done 631 GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
694 handle->ns_it = NULL;
695 GNUNET_SCHEDULER_add_now (&return_token_list, handle);
696 return; 632 return;
697 } 633 }
698 634
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
700 "Next ego: %s\n", 636 attr->name);
701 handle->ego_head->identifier); 637 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
702 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); 638 attr->name);
703 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, 639 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
704 priv_key,
705 &token_collect_error_cb,
706 handle,
707 &token_collect,
708 handle,
709 &token_collect_finished_cb,
710 handle);
711}
712
713
714/**
715 * Collect all tokens for an ego
716 *
717 * TODO move this into the identity-provider service
718 *
719 */
720static void
721token_collect (void *cls,
722 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
723 const char *label,
724 unsigned int rd_count,
725 const struct GNUNET_GNSRECORD_Data *rd)
726{
727 struct RequestHandle *handle = cls;
728 int i;
729 char* data;
730 struct GNUNET_JSONAPI_Resource *json_resource;
731 json_t *issuer;
732 json_t *token;
733
734 for (i = 0; i < rd_count; i++)
735 {
736 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
737 {
738 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
739 rd[i].data,
740 rd[i].data_size);
741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
742 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
743 label);
744 issuer = json_string (handle->ego_head->identifier);
745 GNUNET_JSONAPI_resource_add_attr (json_resource,
746 GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
747 issuer);
748 json_decref (issuer);
749 token = json_string (data);
750 GNUNET_JSONAPI_resource_add_attr (json_resource,
751 GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
752 token);
753 json_decref (token);
754
755 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
756 GNUNET_free (data);
757 }
758 }
759 640
760 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 641 value = json_string (attr->data);
642 GNUNET_JSONAPI_resource_add_attr (json_resource,
643 "value",
644 value);
645 json_decref (value);
646 GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
761} 647}
762 648
763 649
764 650
765/** 651/**
766 * Respond to OPTIONS request 652 * List attributes for identity request
767 * 653 *
768 * @param con_handle the connection handle 654 * @param con_handle the connection handle
769 * @param url the url 655 * @param url the url
770 * @param cls the RequestHandle 656 * @param cls the RequestHandle
771 */ 657 */
772static void 658static void
773list_token_cont (struct GNUNET_REST_RequestHandle *con_handle, 659list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
774 const char* url, 660 const char* url,
775 void *cls) 661 void *cls)
776{ 662{
777 char* ego_val;
778 struct GNUNET_HashCode key;
779 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 663 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
780 struct RequestHandle *handle = cls; 664 struct RequestHandle *handle = cls;
781 struct EgoEntry *ego_entry; 665 struct EgoEntry *ego_entry;
782 struct EgoEntry *ego_tmp; 666 char *identity;
783 667
784 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST, 668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
785 strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST), 669 handle->url);
786 &key); 670 if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
787 671 strlen (handle->url))
788 if ( GNUNET_YES !=
789 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
790 &key) )
791 { 672 {
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No issuer given.\n"); 673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
793 GNUNET_SCHEDULER_add_now (&do_error, handle); 674 GNUNET_SCHEDULER_add_now (&do_error, handle);
794 return; 675 return;
795 } 676 }
796 ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 677 identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
797 &key); 678
798 GNUNET_assert (NULL != ego_val);
799 //Remove non-matching egos
800 for (ego_entry = handle->ego_head; 679 for (ego_entry = handle->ego_head;
801 NULL != ego_entry;) 680 NULL != ego_entry;
802 { 681 ego_entry = ego_entry->next)
803 ego_tmp = ego_entry; 682 if (0 == strcmp (identity, ego_entry->identifier))
804 ego_entry = ego_entry->next; 683 break;
805 if (0 != strcmp (ego_val, ego_tmp->identifier))
806 {
807 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
808 handle->ego_tail,
809 ego_tmp);
810 GNUNET_free (ego_tmp->identifier);
811 GNUNET_free (ego_tmp->keystring);
812 GNUNET_free (ego_tmp);
813 }
814 }
815 handle->resp_object = GNUNET_JSONAPI_document_new (); 684 handle->resp_object = GNUNET_JSONAPI_document_new ();
816 if (NULL == handle->ego_head) 685
686
687 if (NULL == ego_entry)
817 { 688 {
818 //Done 689 //Done
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n"); 690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
820 GNUNET_SCHEDULER_add_now (&return_token_list, handle); 691 identity);
692 GNUNET_SCHEDULER_add_now (&return_response, handle);
821 return; 693 return;
822 } 694 }
823 priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); 695 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
824 handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); 696 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
825 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, 697 handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (handle->idp,
826 priv_key, 698 priv_key,
827 &token_collect_error_cb, 699 &collect_error_cb,
828 handle, 700 handle,
829 &token_collect, 701 &attr_collect,
830 handle, 702 handle,
831 &token_collect_finished_cb, 703 &collect_finished_cb,
832 handle); 704 handle);
833
834} 705}
835 706
836/** 707
837 * Return token to requestor
838 *
839 * @param cls request handle
840 * @param token the token
841 */
842static void 708static void
843exchange_cont (void *cls, 709revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
844 const struct GNUNET_IDENTITY_PROVIDER_Token *token, 710 const char* url,
845 uint64_t ticket_nonce) 711 void *cls)
846{ 712{
847 json_t *root; 713 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
714 const char* identity_str;
715 const char* audience_str;
716 const char* rnd_str;
717
848 struct RequestHandle *handle = cls; 718 struct RequestHandle *handle = cls;
719 struct EgoEntry *ego_entry;
849 struct MHD_Response *resp; 720 struct MHD_Response *resp;
850 struct GNUNET_HashCode key; 721 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
851 char* result; 722 struct GNUNET_JSONAPI_Document *json_obj;
852 char* token_str; 723 struct GNUNET_JSONAPI_Resource *json_res;
853 char* nonce_str; 724 struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
854 uint64_t expected_nonce; 725 char term_data[handle->rest_handle->data_size+1];
855 726 json_t *rnd_json;
856 //Get nonce 727 json_t *identity_json;
857 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE, 728 json_t *audience_json;
858 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE), 729 json_t *data_json;
859 &key); 730 json_error_t err;
860 731 struct GNUNET_JSON_Specification docspec[] = {
861 if ( GNUNET_NO == 732 GNUNET_JSON_spec_jsonapi_document (&json_obj),
862 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 733 GNUNET_JSON_spec_end()
863 &key) ) 734 };
735
736 if (0 >= handle->rest_handle->data_size)
864 { 737 {
865 handle->emsg = GNUNET_strdup ("No nonce given.");
866 GNUNET_SCHEDULER_add_now (&do_error, handle); 738 GNUNET_SCHEDULER_add_now (&do_error, handle);
867 return; 739 return;
868 } 740 }
869 nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
870 &key);
871 GNUNET_assert (NULL != nonce_str);
872 GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
873 741
874 if (ticket_nonce != expected_nonce) 742 term_data[handle->rest_handle->data_size] = '\0';
743 GNUNET_memcpy (term_data,
744 handle->rest_handle->data,
745 handle->rest_handle->data_size);
746 data_json = json_loads (term_data,
747 JSON_DECODE_ANY,
748 &err);
749 GNUNET_assert (GNUNET_OK ==
750 GNUNET_JSON_parse (data_json, docspec,
751 NULL, NULL));
752 json_decref (data_json);
753 if (NULL == json_obj)
754 {
755 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
756 "Unable to parse JSONAPI Object from %s\n",
757 term_data);
758 GNUNET_SCHEDULER_add_now (&do_error, handle);
759 return;
760 }
761 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
875 { 762 {
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
877 "Ticket nonce %"SCNu64" does not match expected nonce %"SCNu64"\n", 764 "Cannot create more than 1 resource! (Got %d)\n",
878 ticket_nonce, expected_nonce); 765 GNUNET_JSONAPI_document_resource_count (json_obj));
879 handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n"); 766 GNUNET_JSONAPI_document_delete (json_obj);
880 GNUNET_SCHEDULER_add_now (&do_error, handle); 767 GNUNET_SCHEDULER_add_now (&do_error, handle);
881 return; 768 return;
882 } 769 }
770 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
771 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
772 GNUNET_REST_JSONAPI_IDENTITY_TICKET))
773 {
774 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
775 "Unsupported JSON data type\n");
776 GNUNET_JSONAPI_document_delete (json_obj);
777 resp = GNUNET_REST_create_response (NULL);
778 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
779 cleanup_handle (handle);
780 return;
781 }
782 rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
783 "rnd");
784 identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
785 "identity");
786 audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
787 "audience");
788 rnd_str = json_string_value (rnd_json);
789 identity_str = json_string_value (identity_json);
790 audience_str = json_string_value (audience_json);
791
792 GNUNET_STRINGS_string_to_data (rnd_str,
793 strlen (rnd_str),
794 &ticket.rnd,
795 sizeof (uint64_t));
796 GNUNET_STRINGS_string_to_data (identity_str,
797 strlen (identity_str),
798 &ticket.identity,
799 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
800 GNUNET_STRINGS_string_to_data (audience_str,
801 strlen (audience_str),
802 &ticket.audience,
803 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
883 804
884 root = json_object (); 805 for (ego_entry = handle->ego_head;
885 token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token); 806 NULL != ego_entry;
886 json_object_set_new (root, "token", json_string (token_str)); 807 ego_entry = ego_entry->next)
887 json_object_set_new (root, "token_type", json_string ("jwt")); 808 {
888 GNUNET_free (token_str); 809 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
810 &tmp_pk);
811 if (0 == memcmp (&ticket.identity,
812 &tmp_pk,
813 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
814 break;
815 }
816 if (NULL == ego_entry)
817 {
818 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
819 "Identity unknown (%s)\n", identity_str);
820 GNUNET_JSONAPI_document_delete (json_obj);
821 return;
822 }
823 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
889 824
890 result = json_dumps (root, JSON_INDENT(1)); 825 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
891 resp = GNUNET_REST_create_response (result); 826 handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp,
892 GNUNET_free (result); 827 identity_priv,
893 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 828 &ticket,
894 cleanup_handle (handle); 829 &finished_cont,
895 json_decref (root); 830 handle);
831 GNUNET_JSONAPI_document_delete (json_obj);
896} 832}
897 833
898
899/**
900 *
901 * Callback called when identity for token exchange has been found
902 *
903 * @param cls request handle
904 * @param ego the identity to use as issuer
905 * @param ctx user context
906 * @param name identity name
907 *
908 */
909static void 834static void
910exchange_token_ticket_cb (void *cls, 835consume_cont (void *cls,
911 struct GNUNET_IDENTITY_Ego *ego, 836 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
912 void **ctx, 837 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
913 const char *name)
914{ 838{
915 struct RequestHandle *handle = cls; 839 struct RequestHandle *handle = cls;
916 struct GNUNET_HashCode key; 840 struct GNUNET_JSONAPI_Resource *json_resource;
917 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; 841 json_t *value;
918 char* ticket_str;
919 842
920 handle->op = NULL; 843 if (NULL == identity)
844 {
845 GNUNET_SCHEDULER_add_now (&return_response, handle);
846 return;
847 }
848
849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
850 attr->name);
851 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
852 attr->name);
853 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
854
855 value = json_string (attr->data);
856 GNUNET_JSONAPI_resource_add_attr (json_resource,
857 "value",
858 value);
859 json_decref (value);
860}
921 861
922 if (NULL == ego) 862static void
863consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
864 const char* url,
865 void *cls)
866{
867 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
868 const char* identity_str;
869 const char* audience_str;
870 const char* rnd_str;
871
872 struct RequestHandle *handle = cls;
873 struct EgoEntry *ego_entry;
874 struct MHD_Response *resp;
875 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
876 struct GNUNET_JSONAPI_Document *json_obj;
877 struct GNUNET_JSONAPI_Resource *json_res;
878 struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
879 char term_data[handle->rest_handle->data_size+1];
880 json_t *rnd_json;
881 json_t *identity_json;
882 json_t *audience_json;
883 json_t *data_json;
884 json_error_t err;
885 struct GNUNET_JSON_Specification docspec[] = {
886 GNUNET_JSON_spec_jsonapi_document (&json_obj),
887 GNUNET_JSON_spec_end()
888 };
889
890 if (0 >= handle->rest_handle->data_size)
923 { 891 {
924 handle->emsg = GNUNET_strdup ("No identity found.");
925 GNUNET_SCHEDULER_add_now (&do_error, handle); 892 GNUNET_SCHEDULER_add_now (&do_error, handle);
926 return; 893 return;
927 } 894 }
928 895
929 //Get ticket 896 term_data[handle->rest_handle->data_size] = '\0';
930 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET, 897 GNUNET_memcpy (term_data,
931 strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET), 898 handle->rest_handle->data,
932 &key); 899 handle->rest_handle->data_size);
933 900 data_json = json_loads (term_data,
934 if ( GNUNET_NO == 901 JSON_DECODE_ANY,
935 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 902 &err);
936 &key) ) 903 GNUNET_assert (GNUNET_OK ==
904 GNUNET_JSON_parse (data_json, docspec,
905 NULL, NULL));
906 json_decref (data_json);
907 if (NULL == json_obj)
908 {
909 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
910 "Unable to parse JSONAPI Object from %s\n",
911 term_data);
912 GNUNET_SCHEDULER_add_now (&do_error, handle);
913 return;
914 }
915 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
937 { 916 {
938 handle->emsg = GNUNET_strdup ("No ticket given."); 917 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
918 "Cannot create more than 1 resource! (Got %d)\n",
919 GNUNET_JSONAPI_document_resource_count (json_obj));
920 GNUNET_JSONAPI_document_delete (json_obj);
939 GNUNET_SCHEDULER_add_now (&do_error, handle); 921 GNUNET_SCHEDULER_add_now (&do_error, handle);
940 return; 922 return;
941 } 923 }
942 ticket_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 924 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
943 &key); 925 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
944 handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego); 926 GNUNET_REST_JSONAPI_IDENTITY_TICKET))
945 GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str, 927 {
946 &ticket); 928 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
929 "Unsupported JSON data type\n");
930 GNUNET_JSONAPI_document_delete (json_obj);
931 resp = GNUNET_REST_create_response (NULL);
932 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
933 cleanup_handle (handle);
934 return;
935 }
936 rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
937 "rnd");
938 identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
939 "identity");
940 audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
941 "audience");
942 rnd_str = json_string_value (rnd_json);
943 identity_str = json_string_value (identity_json);
944 audience_str = json_string_value (audience_json);
945
946 GNUNET_STRINGS_string_to_data (rnd_str,
947 strlen (rnd_str),
948 &ticket.rnd,
949 sizeof (uint64_t));
950 GNUNET_STRINGS_string_to_data (identity_str,
951 strlen (identity_str),
952 &ticket.identity,
953 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
954 GNUNET_STRINGS_string_to_data (audience_str,
955 strlen (audience_str),
956 &ticket.audience,
957 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
947 958
959 for (ego_entry = handle->ego_head;
960 NULL != ego_entry;
961 ego_entry = ego_entry->next)
962 {
963 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
964 &tmp_pk);
965 if (0 == memcmp (&ticket.audience,
966 &tmp_pk,
967 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
968 break;
969 }
970 if (NULL == ego_entry)
971 {
972 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
973 "Identity unknown (%s)\n", identity_str);
974 GNUNET_JSONAPI_document_delete (json_obj);
975 return;
976 }
977 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
978 handle->resp_object = GNUNET_JSONAPI_document_new ();
948 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); 979 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
949 handle->idp_op = GNUNET_IDENTITY_PROVIDER_exchange_ticket (handle->idp, 980 handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (handle->idp,
950 ticket, 981 identity_priv,
951 handle->priv_key, 982 &ticket,
952 &exchange_cont, 983 &consume_cont,
953 handle); 984 handle);
954 GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket); 985 GNUNET_JSONAPI_document_delete (json_obj);
955
956} 986}
957 987
958 988
959 989
960/** 990/**
961 * Respond to issue request
962 *
963 * @param con_handle the connection handle
964 * @param url the url
965 * @param cls the RequestHandle
966 */
967static void
968exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
969 const char* url,
970 void *cls)
971{
972 struct RequestHandle *handle = cls;
973
974 //Get token from GNS
975 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
976 "gns-master",
977 &exchange_token_ticket_cb,
978 handle);
979}
980
981/**
982 * Respond to OPTIONS request 991 * Respond to OPTIONS request
983 * 992 *
984 * @param con_handle the connection handle 993 * @param con_handle the connection handle
@@ -1013,15 +1022,17 @@ init_cont (struct RequestHandle *handle)
1013{ 1022{
1014 struct GNUNET_REST_RequestHandlerError err; 1023 struct GNUNET_REST_RequestHandlerError err;
1015 static const struct GNUNET_REST_RequestHandler handlers[] = { 1024 static const struct GNUNET_REST_RequestHandler handlers[] = {
1016 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont}, 1025 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont},
1017 //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont}, 1026 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont},
1018 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont}, 1027 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
1019 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &options_cont}, 1028 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
1020 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont}, 1029 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
1030 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER,
1031 &options_cont},
1021 GNUNET_REST_HANDLER_END 1032 GNUNET_REST_HANDLER_END
1022 }; 1033 };
1023 1034
1024 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, 1035 if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
1025 handlers, 1036 handlers,
1026 &err, 1037 &err,
1027 handle)) 1038 handle))
@@ -1092,19 +1103,8 @@ list_ego (void *cls,
1092 1103
1093} 1104}
1094 1105
1095/**
1096 * Function processing the REST call
1097 *
1098 * @param method HTTP method
1099 * @param url URL of the HTTP request
1100 * @param data body of the HTTP request (optional)
1101 * @param data_size length of the body
1102 * @param proc callback function for the result
1103 * @param proc_cls closure for callback function
1104 * @return GNUNET_OK if request accepted
1105 */
1106static void 1106static void
1107rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, 1107rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
1108 GNUNET_REST_ResultProcessor proc, 1108 GNUNET_REST_ResultProcessor proc,
1109 void *proc_cls) 1109 void *proc_cls)
1110{ 1110{
@@ -1114,10 +1114,9 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
1114 handle->proc_cls = proc_cls; 1114 handle->proc_cls = proc_cls;
1115 handle->proc = proc; 1115 handle->proc = proc;
1116 handle->state = ID_REST_STATE_INIT; 1116 handle->state = ID_REST_STATE_INIT;
1117 handle->conndata_handle = conndata_handle; 1117 handle->rest_handle = rest_handle;
1118 1118
1119 1119 handle->url = GNUNET_strdup (rest_handle->url);
1120 handle->url = GNUNET_strdup (conndata_handle->url);
1121 if (handle->url[strlen (handle->url)-1] == '/') 1120 if (handle->url[strlen (handle->url)-1] == '/')
1122 handle->url[strlen (handle->url)-1] = '\0'; 1121 handle->url[strlen (handle->url)-1] = '\0';
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1162,8 +1161,8 @@ libgnunet_plugin_rest_identity_provider_init (void *cls)
1162 MHD_HTTP_METHOD_DELETE, 1161 MHD_HTTP_METHOD_DELETE,
1163 MHD_HTTP_METHOD_OPTIONS); 1162 MHD_HTTP_METHOD_OPTIONS);
1164 1163
1165 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1166 _("Identity Token REST API initialized\n")); 1165 _("Identity Provider REST API initialized\n"));
1167 return api; 1166 return api;
1168} 1167}
1169 1168
@@ -1184,8 +1183,8 @@ libgnunet_plugin_rest_identity_provider_done (void *cls)
1184 GNUNET_free_non_null (allow_methods); 1183 GNUNET_free_non_null (allow_methods);
1185 GNUNET_free (api); 1184 GNUNET_free (api);
1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "Identity Token REST plugin is finished\n"); 1186 "Identity Provider REST plugin is finished\n");
1188 return NULL; 1187 return NULL;
1189} 1188}
1190 1189
1191/* end of plugin_rest_gns.c */ 1190/* end of plugin_rest_identity_provider.c */
diff --git a/src/identity-provider/test_idp.conf b/src/identity-provider/test_idp.conf
new file mode 100644
index 000000000..2b76c7bf2
--- /dev/null
+++ b/src/identity-provider/test_idp.conf
@@ -0,0 +1,28 @@
1@INLINE@ test_idp_defaults.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-idp-peer-1/
5
6[dht]
7AUTOSTART = YES
8
9[rest]
10AUTOSTART = YES
11#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
12
13[transport]
14PLUGINS =
15
16[identity-provider]
17AUTOSTART = YES
18#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=/tmp/idplog
19
20[gns]
21#PREFIX = valgrind --leak-check=full --track-origins=yes
22AUTOSTART = YES
23AUTO_IMPORT_PKEY = YES
24MAX_PARALLEL_BACKGROUND_QUERIES = 10
25DEFAULT_LOOKUP_TIMEOUT = 15 s
26RECORD_PUT_INTERVAL = 1 h
27ZONE_PUBLISH_TIME_WINDOW = 1 h
28DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
diff --git a/src/identity-provider/test_idp.sh b/src/identity-provider/test_idp.sh
new file mode 100755
index 000000000..598d1008c
--- /dev/null
+++ b/src/identity-provider/test_idp.sh
@@ -0,0 +1,31 @@
1#!/bin/bash
2#trap "gnunet-arm -e -c test_idp_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_idp.conf
27gnunet-identity -C testego -c test_idp.conf
28valgrind gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
29gnunet-idp -e testego -a name -V John -c test_idp.conf
30gnunet-idp -e testego -D -c test_idp.conf
31gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_attribute.sh b/src/identity-provider/test_idp_attribute.sh
new file mode 100755
index 000000000..7f0f06dac
--- /dev/null
+++ b/src/identity-provider/test_idp_attribute.sh
@@ -0,0 +1,40 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_idp.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_idp.conf
27#gnunet-arm -i rest -c test_idp.conf
28gnunet-identity -C testego -c test_idp.conf
29gnunet-identity -C rpego -c test_idp.conf
30TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
31gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
32gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
33if test $? != 0
34then
35 echo "Failed."
36 exit 1
37fi
38
39#curl localhost:7776/idp/attributes/testego
40gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_consume.sh b/src/identity-provider/test_idp_consume.sh
new file mode 100755
index 000000000..11f6865a4
--- /dev/null
+++ b/src/identity-provider/test_idp_consume.sh
@@ -0,0 +1,43 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_idp.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_idp.conf
27#gnunet-arm -i rest -c test_idp.conf
28gnunet-identity -C testego -c test_idp.conf
29gnunet-identity -C rpego -c test_idp.conf
30SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}')
31TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
32gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
33gnunet-idp -e testego -a name -V John -c test_idp.conf
34TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf | awk '{print $1}')
35gnunet-idp -e rpego -C $TICKET -c test_idp.conf > /dev/null 2>&1
36
37if test $? != 0
38then
39 "Failed."
40 exit 1
41fi
42#curl http://localhost:7776/idp/tickets/testego
43gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_defaults.conf b/src/identity-provider/test_idp_defaults.conf
new file mode 100644
index 000000000..10d89c2fb
--- /dev/null
+++ b/src/identity-provider/test_idp_defaults.conf
@@ -0,0 +1,24 @@
1@INLINE@ ../../contrib/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/test-gnunet-idp-testing/
5
6[namestore-sqlite]
7FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
8
9[namecache-sqlite]
10FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
11
12[identity]
13# Directory where we store information about our egos
14EGODIR = $GNUNET_TEST_HOME/identity/egos/
15
16[dhtcache]
17DATABASE = heap
18
19[transport]
20PLUGINS = tcp
21
22[transport-tcp]
23BINDTO = 127.0.0.1
24
diff --git a/src/identity-provider/test_idp_issue.sh b/src/identity-provider/test_idp_issue.sh
new file mode 100755
index 000000000..90487ee73
--- /dev/null
+++ b/src/identity-provider/test_idp_issue.sh
@@ -0,0 +1,42 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_idp.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_idp.conf
27#gnunet-arm -i rest -c test_idp.conf
28gnunet-identity -C testego -c test_idp.conf
29gnunet-identity -C rpego -c test_idp.conf
30SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}')
31TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
32gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf > /dev/null 2>&1
33gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
34#gnunet-idp -e testego -D -c test_idp.conf
35gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf > /dev/null 2>&1
36if test $? != 0
37then
38 echo "Failed."
39 exit 1
40fi
41#curl http://localhost:7776/idp/attributes/testego
42gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_revoke.sh b/src/identity-provider/test_idp_revoke.sh
new file mode 100755
index 000000000..d5c2c3f77
--- /dev/null
+++ b/src/identity-provider/test_idp_revoke.sh
@@ -0,0 +1,60 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_idp.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
17
18# (1) PKEY1.user -> PKEY2.resu.user
19# (2) PKEY2.resu -> PKEY3
20# (3) PKEY3.user -> PKEY4
21
22
23which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
24
25TEST_ATTR="test"
26gnunet-arm -s -c test_idp.conf
27gnunet-identity -C alice -c test_idp.conf
28gnunet-identity -C bob -c test_idp.conf
29gnunet-identity -C eve -c test_idp.conf
30ALICE_KEY=$(gnunet-identity -d -c test_idp.conf | grep alice | awk '{print $3}')
31BOB_KEY=$(gnunet-identity -d -c test_idp.conf | grep bob | awk '{print $3}')
32EVE_KEY=$(gnunet-identity -d -c test_idp.conf | grep eve | awk '{print $3}')
33
34gnunet-idp -e alice -a email -V john@doe.gnu -c test_idp.conf
35gnunet-idp -e alice -a name -V John -c test_idp.conf
36TICKET_BOB=$(gnunet-idp -e alice -i "email,name" -r $BOB_KEY -c test_idp.conf | awk '{print $1}')
37#gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf
38TICKET_EVE=$(gnunet-idp -e alice -i "email" -r $EVE_KEY -c test_idp.conf | awk '{print $1}')
39
40
41#echo "Consuming $TICKET"
42#gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf
43gnunet-idp -e alice -R $TICKET_EVE -c test_idp.conf
44
45gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf > /dev/null 2>&1
46if test $? == 0
47then
48 echo "Eve can still resolve attributes..."
49 gnunet-arm -e -c test_idp.conf
50 exit 1
51fi
52gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf > /dev/null 2>&1
53if test $? != 0
54then
55 echo "Bob cannot resolve attributes..."
56 gnunet-arm -e -c test_idp.conf
57 exit 1
58fi
59
60gnunet-arm -e -c test_idp.conf
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index 94e8c5e94..b8e70fffb 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -42,8 +42,7 @@ libexec_PROGRAMS = \
42if HAVE_MHD 42if HAVE_MHD
43if HAVE_JSON 43if HAVE_JSON
44plugin_LTLIBRARIES = \ 44plugin_LTLIBRARIES = \
45 libgnunet_plugin_rest_identity.la \ 45 libgnunet_plugin_rest_identity.la
46 libgnunet_plugin_gnsrecord_identity.la
47endif 46endif
48endif 47endif
49 48
@@ -55,14 +54,6 @@ gnunet_service_identity_LDADD = \
55 $(top_builddir)/src/util/libgnunetutil.la \ 54 $(top_builddir)/src/util/libgnunetutil.la \
56 $(GN_LIBINTL) 55 $(GN_LIBINTL)
57 56
58libgnunet_plugin_gnsrecord_identity_la_SOURCES = \
59 plugin_gnsrecord_identity.c
60libgnunet_plugin_gnsrecord_identity_la_LIBADD = \
61 $(top_builddir)/src/util/libgnunetutil.la \
62 $(LTLIBINTL)
63libgnunet_plugin_gnsrecord_identity_la_LDFLAGS = \
64 $(GN_PLUGIN_LDFLAGS)
65
66 57
67libgnunet_plugin_rest_identity_la_SOURCES = \ 58libgnunet_plugin_rest_identity_la_SOURCES = \
68 plugin_rest_identity.c 59 plugin_rest_identity.c
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
index e64b2685a..5f34d0f1b 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -427,9 +427,6 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con,
427 continue; 427 continue;
428 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, 428 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO,
429 ego_entry->keystring); 429 ego_entry->keystring);
430 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
431 "Egoname: %s\n",
432 ego_entry->identifier);
433 name_str = json_string (ego_entry->identifier); 430 name_str = json_string (ego_entry->identifier);
434 GNUNET_JSONAPI_resource_add_attr ( 431 GNUNET_JSONAPI_resource_add_attr (
435 json_resource, 432 json_resource,
diff --git a/src/include/gnunet_abe_lib.h b/src/include/gnunet_abe_lib.h
new file mode 100644
index 000000000..f73ea2431
--- /dev/null
+++ b/src/include/gnunet_abe_lib.h
@@ -0,0 +1,193 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2018 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file include/gnunet_abe_lib.h
23 * @brief Attribute-Based Encryption primitives for GNUnet
24 *
25 * @author Martin Schanzenbach
26 *
27 * @defgroup abe ABE Crypto library: Attribute-Based Encryption operations
28 *
29 */
30#ifndef GNUNET_ABE_LIB_H
31#define GNUNET_ABE_LIB_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "gnunet_common.h"
42#include <gcrypt.h>
43
44/**
45 * @brief type for ABE master keys
46 */
47struct GNUNET_CRYPTO_AbeMasterKey;
48
49/**
50 * @brief type for ABE keys
51 */
52struct GNUNET_CRYPTO_AbeKey;
53
54
55
56/**
57 * @ingroup abe
58 * Create a new CP-ABE master key. Caller must free return value.
59 *
60 * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
61 */
62struct GNUNET_ABE_AbeMasterKey *
63GNUNET_ABE_cpabe_create_master_key (void);
64
65/**
66 * @ingroup abe
67 * Delete a CP-ABE master key.
68 *
69 * @param key the master key
70 * @return fresh private key; free using #GNUNET_free
71 */
72void
73GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key);
74
75/**
76 * @ingroup abe
77 * Create a new CP-ABE key. Caller must free return value.
78 *
79 * @param key the master key
80 * @param attrs the attributes to append to the key
81 * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
82 */
83struct GNUNET_ABE_AbeKey *
84GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
85 char **attrs);
86
87/**
88 * @ingroup abe
89 * Delete a CP-ABE key.
90 *
91 * @param key the key to delete
92 * @param delete_pub GNUNE_YES if the public key should also be freed (bug in gabe)
93 * @return fresh private key; free using #GNUNET_free
94 */
95void
96GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
97 int delete_pub);
98
99
100/**
101 * @ingroup abe
102 * Encrypt a block using sessionkey.
103 *
104 * @param block the block to encrypt
105 * @param size the size of the @a block
106 * @param policy the ABE policy
107 * @param key the key used to encrypt
108 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
109 * @return the size of the encrypted block, -1 for errors
110 */
111ssize_t
112GNUNET_ABE_cpabe_encrypt (const void *block,
113 size_t size,
114 const char *policy,
115 const struct GNUNET_ABE_AbeMasterKey *key,
116 void **result);
117
118/**
119 * @ingroup abe
120 * Decrypt a block using the ABE key.
121 *
122 * @param block the block to encrypt
123 * @param size the size of the @a block
124 * @param key the key used to decrypt
125 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
126 * @return the size of the encrypted block, -1 for errors
127 */
128ssize_t
129GNUNET_ABE_cpabe_decrypt (const void *block,
130 size_t size,
131 const struct GNUNET_ABE_AbeKey *key,
132 void **result);
133
134/**
135 * @ingroup abe
136 * Serialize an ABE key.
137 *
138 * @param key the key to serialize
139 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
140 * @return the size of the encrypted block, -1 for errors
141 */
142ssize_t
143GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
144 void **result);
145
146/**
147 * @ingroup abe
148 * Deserialize a serialized ABE key.
149 *
150 * @param data the data to deserialize
151 * @param len the length of the data.
152 * @return the ABE key. NULL of unsuccessful
153 */
154struct GNUNET_ABE_AbeKey*
155GNUNET_ABE_cpabe_deserialize_key (const void *data,
156 size_t len);
157
158/**
159 * @ingroup abe
160 * Serialize an ABE master key.
161 *
162 * @param key the key to serialize
163 * @param result the result buffer. Will be allocated. Free using #GNUNET_free
164 * @return the size of the encrypted block, -1 for errors
165 */
166ssize_t
167GNUNET_ABE_cpabe_serialize_master_key (const struct GNUNET_ABE_AbeMasterKey *key,
168 void **result);
169
170/**
171 * @ingroup abe
172 * Deserialize an ABE master key.
173 *
174 * @param data the data to deserialize
175 * @param len the length of the data.
176 * @return the ABE key. NULL of unsuccessful
177 */
178struct GNUNET_ABE_AbeMasterKey*
179GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
180 size_t len);
181
182
183#if 0 /* keep Emacsens' auto-indent happy */
184{
185#endif
186#ifdef __cplusplus
187}
188#endif
189
190
191/* ifndef GNUNET_ABE_LIB_H */
192#endif
193/* end of gnunet_abe_lib.h */
diff --git a/src/include/gnunet_credential_service.h b/src/include/gnunet_credential_service.h
index 9e765c12b..7d6f9e973 100644
--- a/src/include/gnunet_credential_service.h
+++ b/src/include/gnunet_credential_service.h
@@ -34,6 +34,7 @@
34 34
35#include "gnunet_util_lib.h" 35#include "gnunet_util_lib.h"
36#include "gnunet_gns_service.h" 36#include "gnunet_gns_service.h"
37#include "gnunet_identity_service.h"
37 38
38#ifdef __cplusplus 39#ifdef __cplusplus
39extern "C" 40extern "C"
@@ -52,7 +53,157 @@ struct GNUNET_CREDENTIAL_Handle;
52/** 53/**
53 * Handle to control a lookup operation. 54 * Handle to control a lookup operation.
54 */ 55 */
55struct GNUNET_CREDENTIAL_LookupRequest; 56struct GNUNET_CREDENTIAL_Request;
57
58/*
59* Enum used for checking whether the issuer has the authority to issue credentials or is just a subject
60*/
61enum GNUNET_CREDENTIAL_CredentialFlags {
62
63 //Subject had credentials before, but have been revoked now
64 GNUNET_CREDENTIAL_FLAG_REVOKED=0,
65
66 //Subject flag indicates that the subject is a holder of this credential and may present it as such
67 GNUNET_CREDENTIAL_FLAG_SUBJECT=1,
68
69 //Issuer flag is used to signify that the subject is allowed to issue this credential and delegate issuance
70 GNUNET_CREDENTIAL_FLAG_ISSUER=2
71
72};
73
74GNUNET_NETWORK_STRUCT_BEGIN
75/**
76 * The attribute delegation record
77 */
78struct GNUNET_CREDENTIAL_DelegationRecord {
79
80 /**
81 * Number of delegation sets in this record
82 */
83 uint32_t set_count;
84
85 /**
86 * Length of delegation sets
87 */
88 uint64_t data_size;
89 /**
90 * Followed by set_count DelegationSetRecords
91 *
92 */
93};
94
95/**
96 * The attribute delegation record
97 */
98struct GNUNET_CREDENTIAL_DelegationRecordSet {
99
100 /**
101 * Public key of the subject this attribute was delegated to
102 */
103 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
104
105 /**
106 * Length of attribute, may be 0
107 */
108 uint32_t subject_attribute_len;
109};
110
111
112GNUNET_NETWORK_STRUCT_END
113
114/**
115 * The attribute delegation record
116 */
117struct GNUNET_CREDENTIAL_DelegationSet {
118
119 /**
120 * Public key of the subject this attribute was delegated to
121 */
122 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
123
124 uint32_t subject_attribute_len;
125
126 /**
127 * The subject attribute
128 */
129 const char *subject_attribute;
130};
131
132
133/**
134 * A delegation
135 */
136struct GNUNET_CREDENTIAL_Delegation {
137
138 /**
139 * The issuer of the delegation
140 */
141 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
142
143 /**
144 * Public key of the subject this attribute was delegated to
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
147
148 /**
149 * Length of the attribute
150 */
151 uint32_t issuer_attribute_len;
152
153 /**
154 * The attribute
155 */
156 const char *issuer_attribute;
157
158 /**
159 * Length of the attribute
160 */
161 uint32_t subject_attribute_len;
162
163 /**
164 * The attribute
165 */
166 const char *subject_attribute;
167};
168
169
170/**
171 * A credential
172 */
173struct GNUNET_CREDENTIAL_Credential {
174
175 /**
176 * The issuer of the credential
177 */
178 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
179
180 /**
181 * Public key of the subject this credential was issued to
182 */
183 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
184
185 /**
186 * Signature of this credential
187 */
188 struct GNUNET_CRYPTO_EcdsaSignature signature;
189
190 /**
191 * Expiration of this credential
192 */
193 struct GNUNET_TIME_Absolute expiration;
194
195 /**
196 * Length of the attribute
197 */
198 uint32_t issuer_attribute_len;
199
200 /**
201 * The attribute
202 */
203 const char *issuer_attribute;
204
205};
206
56 207
57 208
58/** 209/**
@@ -61,7 +212,7 @@ struct GNUNET_CREDENTIAL_LookupRequest;
61 * @param cfg configuration to use 212 * @param cfg configuration to use
62 * @return handle to the Credential service, or NULL on error 213 * @return handle to the Credential service, or NULL on error
63 */ 214 */
64struct GNUNET_Credential_Handle * 215struct GNUNET_CREDENTIAL_Handle *
65GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); 216GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
66 217
67 218
@@ -75,73 +226,131 @@ GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle);
75 226
76 227
77/** 228/**
78 * Iterator called on obtained result for a Credential lookup. 229 * Iterator called on obtained result for an attribute verification.
230 *
231 * @param cls closure
232 * @param d_count the number of delegations processed
233 * @param delegation_chain the delegations processed
234 * @param c_count the number of credentials found
235 * @param credential the credentials
236 */
237typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls,
238 unsigned int d_count,
239 struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
240 unsigned int c_count,
241 struct GNUNET_CREDENTIAL_Credential *credential);
242
243/**
244 * Iterator called on obtained result for an attribute delegation.
245 *
246 * @param cls closure
247 * @param success GNUNET_YES if successful
248 * @param result the record data that can be handed to the subject
249 */
250typedef void (*GNUNET_CREDENTIAL_DelegateResultProcessor) (void *cls,
251 uint32_t success);
252
253/**
254 * Iterator called on obtained result for an attribute delegation removal.
79 * 255 *
80 * @param cls closure 256 * @param cls closure
81 * @param issuer the issuer chain 257 * @param success GNUNET_YES if successful
82 * @param issuer_len length of issuer chain 258 * @param result the record data that can be handed to the subject
83 * @param value the value returned
84 */ 259 */
85typedef void 260typedef void (*GNUNET_CREDENTIAL_RemoveDelegateResultProcessor) (void *cls,
86(*GNUNET_CREDENTIAL_LookupResultProcessor) (void *cls, 261 uint32_t success);
87 struct GNUNET_IDENTITY_Ego *issuer,
88 uint16_t issuer_len,
89 const struct GNUNET_CREDENTIAL_Value *value);
90 262
91 263
92/** 264/**
93 * Perform an asynchronous lookup operation for a credential. 265 * Performs attribute verification.
266 * Checks if there is a delegation chain from
267 * attribute ``issuer_attribute'' issued by the issuer
268 * with public key ``issuer_key'' maps to the attribute
269 * ``subject_attribute'' claimed by the subject with key
270 * ``subject_key''
94 * 271 *
95 * @param handle handle to the Credential service 272 * @param handle handle to the Credential service
96 * @param credential the credential to look up 273 * @param issuer_key the issuer public key
97 * @param subject Ego to check the credential for 274 * @param issuer_attribute the issuer attribute
275 * @param subject_key the subject public key
276 * @param credential_count number of credentials
277 * @param credentials the subject credentials
98 * @param proc function to call on result 278 * @param proc function to call on result
99 * @param proc_cls closure for processor 279 * @param proc_cls closure for processor
100 * @return handle to the queued request 280 * @return handle to the queued request
101 */ 281 */
102struct GNUNET_CREDENTIAL_LookupRequest * 282struct GNUNET_CREDENTIAL_Request*
103GNUNET_CREDENTIAL_lookup (struct GNUNET_CREDENTIAL_Handle *handle, 283GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
104 const char *credential, 284 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
105 const struct GNUNET_IDENTITY_Ego *subject, 285 const char *issuer_attribute,
106 GNUNET_CREDENTIAL_LookupResultProcessor proc, 286 const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
287 uint32_t credential_count,
288 const struct GNUNET_CREDENTIAL_Credential *credentials,
289 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
107 void *proc_cls); 290 void *proc_cls);
108 291
292struct GNUNET_CREDENTIAL_Request*
293GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
294 const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
295 const char *issuer_attribute,
296 const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
297 GNUNET_CREDENTIAL_CredentialResultProcessor proc,
298 void *proc_cls);
109 299
110/** 300/**
111 * Issue a credential to an identity 301 * Delegate an attribute
112 * 302 *
113 * @param handle handle to the Credential service 303 * @param handle handle to the Credential service
114 * @param issuer the identity that issues the credential 304 * @param issuer the ego that should be used to delegate the attribute
115 * @param subject the subject of the credential 305 * @param attribute the name of the attribute to delegate
116 * @param credential the name of the credential 306 * @param subject the subject of the delegation
117 * @param value the value of the credential 307 * @param delegated_attribute the name of the attribute that is delegated to
308 * @param proc the result callback
309 * @param proc_cls the result closure context
118 * @return handle to the queued request 310 * @return handle to the queued request
119 */ 311 */
120struct GNUNET_CREDENTIAL_IssueRequest * 312struct GNUNET_CREDENTIAL_Request *
121GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle, 313GNUNET_CREDENTIAL_add_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
122 struct GNUNET_IDENTITY_Ego *issuer, 314 struct GNUNET_IDENTITY_Ego *issuer,
123 struct GNUNET_IDENTITY_Ego *subject, 315 const char *attribute,
124 const char *credential, 316 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
125 struct GNUNET_CREDENTIAL_Value *value, 317 const char *delegated_attribute,
126 GNUNET_CREDENTIAL_IssueResultProcessor proc, 318 GNUNET_CREDENTIAL_DelegateResultProcessor proc,
127 void *proc_cls); 319 void *proc_cls);
128 320
129/** 321/**
130 * Remove a credential 322 * Remove a delegation
131 * 323 *
132 * @param handle handle to the Credential service 324 * @param handle handle to the Credential service
133 * @param issuer the identity that issued the credential 325 * @param issuer the ego that was used to delegate the attribute
134 * @param subject the subject of the credential 326 * @param attribute the name of the attribute that is delegated
135 * @param credential the name of the credential 327 * @param proc the callback
328 * @param proc_cls callback closure
136 * @return handle to the queued request 329 * @return handle to the queued request
137 */ 330 */
138struct GNUNET_CREDENTIAL_IssueRequest * 331struct GNUNET_CREDENTIAL_Request *
139GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle, 332GNUNET_CREDENTIAL_remove_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
140 struct GNUNET_IDENTITY_Ego *issuer, 333 struct GNUNET_IDENTITY_Ego *issuer,
141 struct GNUNET_IDENTITY_Ego *subject, 334 const char *attribute,
142 const char *credential, 335 GNUNET_CREDENTIAL_RemoveDelegateResultProcessor proc,
143 GNUNET_CREDENTIAL_IssueResultProcessor proc, 336 void *proc_cls);
144 void *proc_cls); 337
338
339
340/**
341 * Issue an attribute to a subject
342 *
343 * @param issuer the ego that should be used to issue the attribute
344 * @param subject the subject of the attribute
345 * @param attribute the name of the attribute
346 * @param expiration the TTL of the credential
347 * @return handle to the queued request
348 */
349struct GNUNET_CREDENTIAL_Credential*
350GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
351 struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
352 const char *attribute,
353 struct GNUNET_TIME_Absolute *expiration);
145 354
146 355
147 356
@@ -151,7 +360,7 @@ GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle,
151 * @param lr the lookup request to cancel 360 * @param lr the lookup request to cancel
152 */ 361 */
153void 362void
154GNUNET_CREDENTIAL_lookup_cancel (struct GNUNET_CREDENTIAL_LookupRequest *lr); 363GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *lr);
155 364
156 365
157#if 0 /* keep Emacsens' auto-indent happy */ 366#if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index 985ae1f7a..d03b4db3b 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -109,9 +109,29 @@ extern "C"
109#define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546 109#define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546
110 110
111/** 111/**
112 * Record type for credential
113 */
114#define GNUNET_GNSRECORD_TYPE_CREDENTIAL 65547
115
116/**
117 * Record type for policies
118 */
119#define GNUNET_GNSRECORD_TYPE_POLICY 65548
120
121/**
112 * Record type for reverse lookups 122 * Record type for reverse lookups
113 */ 123 */
114#define GNUNET_GNSRECORD_TYPE_REVERSE 65548 124#define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549
125
126/**
127 * Record type for ABE records
128 */
129#define GNUNET_GNSRECORD_TYPE_ABE_KEY 65550
130
131/**
132 * Record type for ABE master keys
133 */
134#define GNUNET_GNSRECORD_TYPE_ABE_MASTER 65551
115 135
116/** 136/**
117 * Flags that can be set for a record. 137 * Flags that can be set for a record.
diff --git a/src/include/gnunet_identity_attribute_lib.h b/src/include/gnunet_identity_attribute_lib.h
new file mode 100644
index 000000000..316b0bf95
--- /dev/null
+++ b/src/include/gnunet_identity_attribute_lib.h
@@ -0,0 +1,277 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @author Martin Schanzenbach
23 *
24 * @file
25 * Identity attribute definitions
26 *
27 * @defgroup identity-provider Identity Provider service
28 * @{
29 */
30#ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H
31#define GNUNET_IDENTITY_ATTRIBUTE_LIB_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "gnunet_util_lib.h"
42
43
44/**
45 * No value attribute.
46 */
47#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_NONE 0
48
49/**
50 * String attribute.
51 */
52#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING 1
53
54
55
56/**
57 * An attribute.
58 */
59struct GNUNET_IDENTITY_ATTRIBUTE_Claim
60{
61 /**
62 * The name of the attribute. Note "name" must never be individually
63 * free'd
64 */
65 const char* name;
66
67 /**
68 * Type of Claim
69 */
70 uint32_t type;
71
72 /**
73 * Version
74 */
75 uint32_t version;
76
77 /**
78 * Number of bytes in @e data.
79 */
80 size_t data_size;
81
82 /**
83 * Binary value stored as attribute value. Note: "data" must never
84 * be individually 'malloc'ed, but instead always points into some
85 * existing data area.
86 */
87 const void *data;
88
89};
90
91struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList
92{
93 /**
94 * List head
95 */
96 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_head;
97
98 /**
99 * List tail
100 */
101 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_tail;
102};
103
104struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry
105{
106 /**
107 * DLL
108 */
109 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *prev;
110
111 /**
112 * DLL
113 */
114 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *next;
115
116 /**
117 * The attribute claim
118 */
119 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
120};
121
122/**
123 * Create a new attribute claim.
124 *
125 * @param attr_name the attribute name
126 * @param type the attribute type
127 * @param data the attribute value
128 * @param data_size the attribute value size
129 * @return the new attribute
130 */
131struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
132GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
133 uint32_t type,
134 const void* data,
135 size_t data_size);
136
137
138/**
139 * Get required size for serialization buffer
140 *
141 * @param attrs the attribute list to serialize
142 *
143 * @return the required buffer size
144 */
145size_t
146GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
147
148void
149GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
150
151
152/**
153 * Serialize an attribute list
154 *
155 * @param attrs the attribute list to serialize
156 * @param result the serialized attribute
157 *
158 * @return length of serialized data
159 */
160size_t
161GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
162 char *result);
163
164/**
165 * Deserialize an attribute list
166 *
167 * @param data the serialized attribute list
168 * @param data_size the length of the serialized data
169 *
170 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
171 */
172struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
173GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
174 size_t data_size);
175
176
177/**
178 * Get required size for serialization buffer
179 *
180 * @param attr the attribute to serialize
181 *
182 * @return the required buffer size
183 */
184size_t
185GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
186
187
188
189/**
190 * Serialize an attribute
191 *
192 * @param attr the attribute to serialize
193 * @param result the serialized attribute
194 *
195 * @return length of serialized data
196 */
197size_t
198GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
199 char *result);
200
201/**
202 * Deserialize an attribute
203 *
204 * @param data the serialized attribute
205 * @param data_size the length of the serialized data
206 *
207 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
208 */
209struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
210GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
211 size_t data_size);
212
213struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
214GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
215
216/**
217 * Convert a type name to the corresponding number
218 *
219 * @param typename name to convert
220 * @return corresponding number, UINT32_MAX on error
221 */
222uint32_t
223GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename);
224
225/**
226 * Convert human-readable version of a 'claim' of an attribute to the binary
227 * representation
228 *
229 * @param type type of the claim
230 * @param s human-readable string
231 * @param data set to value in binary encoding (will be allocated)
232 * @param data_size set to number of bytes in @a data
233 * @return #GNUNET_OK on success
234 */
235int
236GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
237 const char *s,
238 void **data,
239 size_t *data_size);
240
241/**
242 * Convert the 'claim' of an attribute to a string
243 *
244 * @param type the type of attribute
245 * @param data claim in binary encoding
246 * @param data_size number of bytes in @a data
247 * @return NULL on error, otherwise human-readable representation of the claim
248 */
249char *
250GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
251 const void* data,
252 size_t data_size);
253
254/**
255 * Convert a type number to the corresponding type string
256 *
257 * @param type number of a type
258 * @return corresponding typestring, NULL on error
259 */
260const char*
261GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type);
262
263
264#if 0 /* keep Emacsens' auto-indent happy */
265{
266#endif
267#ifdef __cplusplus
268}
269#endif
270
271
272/* ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H */
273#endif
274
275/** @} */ /* end of group identity */
276
277/* end of gnunet_identity_attribute_lib.h */
diff --git a/src/include/gnunet_identity_attribute_plugin.h b/src/include/gnunet_identity_attribute_plugin.h
new file mode 100644
index 000000000..edeed57fd
--- /dev/null
+++ b/src/include/gnunet_identity_attribute_plugin.h
@@ -0,0 +1,149 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012, 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @author Martin Schanzenbach
23 *
24 * @file
25 * Plugin API for the idp database backend
26 *
27 * @defgroup identity-provider-plugin IdP service plugin API
28 * Plugin API for the idp database backend
29 * @{
30 */
31#ifndef GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H
32#define GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H
33
34#include "gnunet_util_lib.h"
35#include "gnunet_identity_attribute_lib.h"
36
37#ifdef __cplusplus
38extern "C"
39{
40#if 0 /* keep Emacsens' auto-indent happy */
41}
42#endif
43#endif
44
45
46/**
47 * Function called to convert the binary value @a data of an attribute of
48 * type @a type to a human-readable string.
49 *
50 * @param cls closure
51 * @param type type of the attribute
52 * @param data value in binary encoding
53 * @param data_size number of bytes in @a data
54 * @return NULL on error, otherwise human-readable representation of the value
55 */
56typedef char * (*GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction) (void *cls,
57 uint32_t type,
58 const void *data,
59 size_t data_size);
60
61
62/**
63 * Function called to convert human-readable version of the value @a s
64 * of an attribute of type @a type to the respective binary
65 * representation.
66 *
67 * @param cls closure
68 * @param type type of the attribute
69 * @param s human-readable string
70 * @param data set to value in binary encoding (will be allocated)
71 * @param data_size set to number of bytes in @a data
72 * @return #GNUNET_OK on success
73 */
74typedef int (*GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction) (void *cls,
75 uint32_t type,
76 const char *s,
77 void **data,
78 size_t *data_size);
79
80
81/**
82 * Function called to convert a type name to the
83 * corresponding number.
84 *
85 * @param cls closure
86 * @param typename name to convert
87 * @return corresponding number, UINT32_MAX on error
88 */
89typedef uint32_t (*GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction) (void *cls,
90 const char *typename);
91
92
93/**
94 * Function called to convert a type number (i.e. 1) to the
95 * corresponding type string
96 *
97 * @param cls closure
98 * @param type number of a type to convert
99 * @return corresponding typestring, NULL on error
100 */
101typedef const char * (*GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction) (void *cls,
102 uint32_t type);
103
104
105/**
106 * Each plugin is required to return a pointer to a struct of this
107 * type as the return value from its entry point.
108 */
109struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions
110{
111
112 /**
113 * Closure for all of the callbacks.
114 */
115 void *cls;
116
117 /**
118 * Conversion to string.
119 */
120 GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction value_to_string;
121
122 /**
123 * Conversion to binary.
124 */
125 GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction string_to_value;
126
127 /**
128 * Typename to number.
129 */
130 GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction typename_to_number;
131
132 /**
133 * Number to typename.
134 */
135 GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction number_to_typename;
136
137};
138
139
140#if 0 /* keep Emacsens' auto-indent happy */
141{
142#endif
143#ifdef __cplusplus
144}
145#endif
146
147#endif
148
149/** @} */ /* end of group */
diff --git a/src/include/gnunet_identity_provider_plugin.h b/src/include/gnunet_identity_provider_plugin.h
new file mode 100644
index 000000000..4b5098d58
--- /dev/null
+++ b/src/include/gnunet_identity_provider_plugin.h
@@ -0,0 +1,123 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012, 2013 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @author Martin Schanzenbach
23 *
24 * @file
25 * Plugin API for the idp database backend
26 *
27 * @defgroup identity-provider-plugin IdP service plugin API
28 * Plugin API for the idp database backend
29 * @{
30 */
31#ifndef GNUNET_IDENTITY_PROVIDER_PLUGIN_H
32#define GNUNET_IDENTITY_PROVIDER_PLUGIN_H
33
34#include "gnunet_util_lib.h"
35#include "gnunet_identity_provider_service.h"
36
37#ifdef __cplusplus
38extern "C"
39{
40#if 0 /* keep Emacsens' auto-indent happy */
41}
42#endif
43#endif
44
45
46/**
47 * Function called by for each matching ticket.
48 *
49 * @param cls closure
50 * @param ticket the ticket
51 */
52typedef void (*GNUNET_IDENTITY_PROVIDER_TicketIterator) (void *cls,
53 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
54 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
55
56
57/**
58 * @brief struct returned by the initialization function of the plugin
59 */
60struct GNUNET_IDENTITY_PROVIDER_PluginFunctions
61{
62
63 /**
64 * Closure to pass to all plugin functions.
65 */
66 void *cls;
67
68 /**
69 * Store a ticket in the database.
70 *
71 * @param cls closure (internal context for the plugin)
72 * @param ticket the ticket to store
73 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
74 */
75 int (*store_ticket) (void *cls,
76 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
77 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
78
79 /**
80 * Delete a ticket from the database.
81 *
82 * @param cls closure (internal context for the plugin)
83 * @param ticket the ticket to store
84 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
85 */
86 int (*delete_ticket) (void *cls,
87 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
88
89
90
91 /**
92 * Iterate over all tickets
93 *
94 * @param cls closure (internal context for the plugin)
95 * @param identity the identity
96 * @param audience GNUNET_YES if the identity is the audience of the ticket
97 * else it is considered the issuer
98 * @param iter function to call with the result
99 * @param iter_cls closure for @a iter
100 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
101 */
102 int (*iterate_tickets) (void *cls,
103 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
104 int audience,
105 uint64_t offset,
106 GNUNET_IDENTITY_PROVIDER_TicketIterator iter, void *iter_cls);
107
108 int (*get_ticket_attributes) (void* cls,
109 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
110 GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
111 void *iter_cls);
112};
113
114#if 0 /* keep Emacsens' auto-indent happy */
115{
116#endif
117#ifdef __cplusplus
118}
119#endif
120
121#endif
122
123/** @} */ /* end of group */
diff --git a/src/include/gnunet_identity_provider_service.h b/src/include/gnunet_identity_provider_service.h
index e533f6f8c..be935e898 100644
--- a/src/include/gnunet_identity_provider_service.h
+++ b/src/include/gnunet_identity_provider_service.h
@@ -39,7 +39,7 @@ extern "C"
39#endif 39#endif
40 40
41#include "gnunet_util_lib.h" 41#include "gnunet_util_lib.h"
42 42#include "gnunet_identity_attribute_lib.h"
43 43
44/** 44/**
45 * Version number of GNUnet Identity Provider API. 45 * Version number of GNUnet Identity Provider API.
@@ -57,169 +57,310 @@ struct GNUNET_IDENTITY_PROVIDER_Handle;
57struct GNUNET_IDENTITY_PROVIDER_Token; 57struct GNUNET_IDENTITY_PROVIDER_Token;
58 58
59/** 59/**
60 * Handle for a ticket 60 * The ticket
61 */ 61 */
62struct GNUNET_IDENTITY_PROVIDER_Ticket; 62struct GNUNET_IDENTITY_PROVIDER_Ticket
63{
64 /**
65 * The ticket issuer
66 */
67 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
68
69 /**
70 * The ticket audience
71 */
72 struct GNUNET_CRYPTO_EcdsaPublicKey audience;
73
74 /**
75 * The ticket random (NBO)
76 */
77 uint64_t rnd;
78};
63 79
64/** 80/**
65 * Handle for an operation with the identity provider service. 81 * Handle for an operation with the identity provider service.
66 */ 82 */
67struct GNUNET_IDENTITY_PROVIDER_Operation; 83struct GNUNET_IDENTITY_PROVIDER_Operation;
68 84
85
69/** 86/**
70 * Method called when a token has been exchanged for a ticket. 87 * Connect to the identity provider service.
71 * On success returns a token
72 * 88 *
73 * @param cls closure 89 * @param cfg Configuration to contact the identity provider service.
74 * @param token the token 90 * @return handle to communicate with identity provider service
75 */ 91 */
76typedef void 92struct GNUNET_IDENTITY_PROVIDER_Handle *
77(*GNUNET_IDENTITY_PROVIDER_ExchangeCallback)(void *cls, 93GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
78 const struct GNUNET_IDENTITY_PROVIDER_Token *token,
79 uint64_t ticket_nonce);
80 94
81/** 95/**
82 * Method called when a token has been issued. 96 * Continuation called to notify client about result of the
83 * On success returns a ticket that can be given to the audience to retrive the 97 * operation.
84 * token
85 * 98 *
86 * @param cls closure 99 * @param cls closure
87 * @param grant the label in GNS pointing to the token 100 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
88 * @param ticket the ticket 101 * #GNUNET_NO if content was already there or not found
89 * @param token the issued token 102 * #GNUNET_YES (or other positive value) on success
90 * @param name name assigned by the user for this ego, 103 * @param emsg NULL on success, otherwise an error message
91 * NULL if the user just deleted the ego and it
92 * must thus no longer be used
93 */ 104 */
94typedef void 105typedef void
95(*GNUNET_IDENTITY_PROVIDER_IssueCallback)(void *cls, 106(*GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus) (void *cls,
96 const char *grant, 107 int32_t success,
97 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, 108 const char *emsg);
98 const struct GNUNET_IDENTITY_PROVIDER_Token *token);
99 109
100 110
101/** 111/**
102 * Connect to the identity provider service. 112 * Store an attribute. If the attribute is already present,
113 * it is replaced with the new attribute.
103 * 114 *
104 * @param cfg Configuration to contact the identity provider service. 115 * @param h handle to the identity provider
105 * @return handle to communicate with identity provider service 116 * @param pkey private key of the identity
117 * @param attr the attribute
118 * @param cont continuation to call when done
119 * @param cont_cls closure for @a cont
120 * @return handle to abort the request
106 */ 121 */
107struct GNUNET_IDENTITY_PROVIDER_Handle * 122struct GNUNET_IDENTITY_PROVIDER_Operation *
108GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); 123GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
124 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
125 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
126 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
127 void *cont_cls);
109 128
110 129
111/** 130/**
112 * Issue a token for a specific audience. 131 * Process an attribute that was stored in the idp.
113 * 132 *
114 * @param id identity provider service to use 133 * @param cls closure
115 * @param iss issuer (identity) 134 * @param identity the identity
116 * @param aud audience (identity) 135 * @param attr the attribute
117 * @param scope the identity attributes requested, comman separated
118 * @param expiration the token expiration
119 * @param nonce the nonce that will be included in token and ticket
120 * @param cb callback to call with result
121 * @param cb_cls closure
122 * @return handle to abort the operation
123 */ 136 */
124struct GNUNET_IDENTITY_PROVIDER_Operation * 137typedef void
125GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id, 138(*GNUNET_IDENTITY_PROVIDER_AttributeResult) (void *cls,
126 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key, 139 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
127 const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, 140 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
128 const char* scope, 141
129 struct GNUNET_TIME_Absolute expiration,
130 uint64_t nonce,
131 GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
132 void *cb_cls);
133 142
134 143
135/** 144/**
136 * Exchange a ticket for a token. Intended to be used by audience that 145 * List all attributes for a local identity.
137 * received a ticket. 146 * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
147 * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
148 * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
149 * immediately, and then again after
150 * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
138 * 151 *
139 * @param id identity provider service to use 152 * On error (disconnect), @a error_cb will be invoked.
140 * @param ticket the ticket to exchange 153 * On normal completion, @a finish_cb proc will be
141 * @param aud_privkey the audience of the ticket 154 * invoked.
142 * @param cont function to call once the operation finished 155 *
143 * @param cont_cls closure for @a cont 156 * @param h handle to the idp
144 * @return handle to abort the operation 157 * @param identity identity to access
158 * @param error_cb function to call on error (i.e. disconnect),
159 * the handle is afterwards invalid
160 * @param error_cb_cls closure for @a error_cb
161 * @param proc function to call on each attribute; it
162 * will be called repeatedly with a value (if available)
163 * @param proc_cls closure for @a proc
164 * @param finish_cb function to call on completion
165 * the handle is afterwards invalid
166 * @param finish_cb_cls closure for @a finish_cb
167 * @return an iterator handle to use for iteration
145 */ 168 */
146struct GNUNET_IDENTITY_PROVIDER_Operation * 169struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
147GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id, 170GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
148 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, 171 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
149 const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey, 172 GNUNET_SCHEDULER_TaskCallback error_cb,
150 GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont, 173 void *error_cb_cls,
151 void *cont_cls); 174 GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
175 void *proc_cls,
176 GNUNET_SCHEDULER_TaskCallback finish_cb,
177 void *finish_cb_cls);
152 178
153 179
154/** 180/**
155 * Disconnect from identity provider service. 181 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
182 * for the next record.
156 * 183 *
157 * @param h identity provider service to disconnect 184 * @param it the iterator
158 */ 185 */
159void 186void
160GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); 187GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
161 188
162 189
163/** 190/**
164 * Cancel an identity provider operation. Note that the operation MAY still 191 * Stops iteration and releases the idp handle for further calls. Must
165 * be executed; this merely cancels the continuation; if the request 192 * be called on any iteration that has not yet completed prior to calling
166 * was already transmitted, the service may still choose to complete 193 * #GNUNET_IDENTITY_PROVIDER_disconnect.
167 * the operation.
168 * 194 *
169 * @param op operation to cancel 195 * @param it the iterator
170 */ 196 */
171void 197void
172GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op); 198GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
173 199
174 200
175/** 201/**
176 * Convenience API 202 * Method called when a token has been issued.
203 * On success returns a ticket that can be given to the audience to retrive the
204 * token
205 *
206 * @param cls closure
207 * @param ticket the ticket
177 */ 208 */
209typedef void
210(*GNUNET_IDENTITY_PROVIDER_TicketCallback)(void *cls,
211 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
178 212
179/** 213/**
180 * Destroy token 214 * Issues a ticket to another identity. The identity may use
215 * GNUNET_IDENTITY_PROVIDER_ticket_consume to consume the ticket
216 * and retrieve the attributes specified in the AttributeList.
181 * 217 *
182 * @param token the token 218 * @param h the identity provider to use
219 * @param iss the issuing identity
220 * @param rp the subject of the ticket (the relying party)
221 * @param attrs the attributes that the relying party is given access to
222 * @param cb the callback
223 * @param cb_cls the callback closure
224 * @return handle to abort the operation
183 */ 225 */
184void 226struct GNUNET_IDENTITY_PROVIDER_Operation *
185GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token); 227GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
228 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
229 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
230 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
231 GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
232 void *cb_cls);
186 233
187/** 234/**
188 * Returns string representation of token. A JSON-Web-Token. 235 * Revoked an issued ticket. The relying party will be unable to retrieve
236 * updated attributes.
189 * 237 *
190 * @param token the token 238 * @param h the identity provider to use
191 * @return The JWT (must be freed) 239 * @param identity the issuing identity
240 * @param ticket the ticket to revoke
241 * @param cb the callback
242 * @param cb_cls the callback closure
243 * @return handle to abort the operation
192 */ 244 */
193char * 245struct GNUNET_IDENTITY_PROVIDER_Operation *
194GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token); 246GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
247 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
248 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
249 GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
250 void *cb_cls);
251
252
195 253
196/** 254/**
197 * Returns string representation of ticket. Base64-Encoded 255 * Consumes an issued ticket. The ticket is persisted
256 * and used to retrieve identity information from the issuer
198 * 257 *
199 * @param ticket the ticket 258 * @param h the identity provider to use
200 * @return the Base64-Encoded ticket 259 * @param identity the identity that is the subject of the issued ticket (the audience)
260 * @param ticket the issued ticket to consume
261 * @param cb the callback to call
262 * @param cb_cls the callback closure
263 * @return handle to abort the operation
264 */
265struct GNUNET_IDENTITY_PROVIDER_Operation *
266GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
267 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
268 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
269 GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
270 void *cb_cls);
271
272/**
273 * Lists all tickets that have been issued to remote
274 * identites (relying parties)
275 *
276 * @param h the identity provider to use
277 * @param identity the issuing identity
278 * @param error_cb function to call on error (i.e. disconnect),
279 * the handle is afterwards invalid
280 * @param error_cb_cls closure for @a error_cb
281 * @param proc function to call on each ticket; it
282 * will be called repeatedly with a value (if available)
283 * @param proc_cls closure for @a proc
284 * @param finish_cb function to call on completion
285 * the handle is afterwards invalid
286 * @param finish_cb_cls closure for @a finish_cb
287 * @return an iterator handle to use for iteration
288 */
289struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
290GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
291 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
292 GNUNET_SCHEDULER_TaskCallback error_cb,
293 void *error_cb_cls,
294 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
295 void *proc_cls,
296 GNUNET_SCHEDULER_TaskCallback finish_cb,
297 void *finish_cb_cls);
298
299/**
300 * Lists all tickets that have been issued to remote
301 * identites (relying parties)
302 *
303 * @param h the identity provider to use
304 * @param identity the issuing identity
305 * @param error_cb function to call on error (i.e. disconnect),
306 * the handle is afterwards invalid
307 * @param error_cb_cls closure for @a error_cb
308 * @param proc function to call on each ticket; it
309 * will be called repeatedly with a value (if available)
310 * @param proc_cls closure for @a proc
311 * @param finish_cb function to call on completion
312 * the handle is afterwards invalid
313 * @param finish_cb_cls closure for @a finish_cb
314 * @return an iterator handle to use for iteration
201 */ 315 */
202char * 316struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
203GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); 317GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
318 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
319 GNUNET_SCHEDULER_TaskCallback error_cb,
320 void *error_cb_cls,
321 GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
322 void *proc_cls,
323 GNUNET_SCHEDULER_TaskCallback finish_cb,
324 void *finish_cb_cls);
204 325
205/** 326/**
206 * Created a ticket from a string (Base64 encoded ticket) 327 * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
328 * for the next record.
207 * 329 *
208 * @param input Base64 encoded ticket 330 * @param it the iterator
209 * @param ticket pointer where the ticket is stored
210 * @return GNUNET_OK
211 */ 331 */
212int 332void
213GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, 333GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
214 struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket);
215 334
216/** 335/**
217 * Destroys a ticket 336 * Stops iteration and releases the idp handle for further calls. Must
337 * be called on any iteration that has not yet completed prior to calling
338 * #GNUNET_IDENTITY_PROVIDER_disconnect.
218 * 339 *
219 * @param ticket the ticket to destroy 340 * @param it the iterator
220 */ 341 */
221void 342void
222GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); 343GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
344
345/**
346 * Disconnect from identity provider service.
347 *
348 * @param h identity provider service to disconnect
349 */
350void
351GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
352
353
354/**
355 * Cancel an identity provider operation. Note that the operation MAY still
356 * be executed; this merely cancels the continuation; if the request
357 * was already transmitted, the service may still choose to complete
358 * the operation.
359 *
360 * @param op operation to cancel
361 */
362void
363GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op);
223 364
224#if 0 /* keep Emacsens' auto-indent happy */ 365#if 0 /* keep Emacsens' auto-indent happy */
225{ 366{
diff --git a/src/include/gnunet_jsonapi_lib.h b/src/include/gnunet_jsonapi_lib.h
index f95bff836..2f6b810f0 100644
--- a/src/include/gnunet_jsonapi_lib.h
+++ b/src/include/gnunet_jsonapi_lib.h
@@ -248,7 +248,7 @@ GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource
248 * @param res the JSON resource 248 * @param res the JSON resource
249 * @return the resource id 249 * @return the resource id
250 */ 250 */
251char* 251const char*
252GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource); 252GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource);
253 253
254 254
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 9cfd00e39..436adc5a4 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2628,13 +2628,47 @@ extern "C"
2628 * 2628 *
2629 * IDENTITY PROVIDER MESSAGE TYPES 2629 * IDENTITY PROVIDER MESSAGE TYPES
2630 */ 2630 */
2631#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE 961 2631#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE 961
2632 2632
2633#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE 962 2633#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE 962
2634 2634
2635#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT 963 2635#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START 963
2636 2636
2637#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT 964 2637#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP 964
2638
2639#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT 965
2640
2641#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 966
2642
2643#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET 967
2644
2645#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 968
2646
2647#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET 969
2648
2649#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT 970
2650
2651#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET 971
2652
2653#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT 972
2654
2655#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START 973
2656
2657#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP 974
2658
2659#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT 975
2660
2661/**************************************************
2662 *
2663 * CREDENTIAL MESSAGE TYPES
2664 */
2665#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY 981
2666
2667#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 982
2668
2669#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 983
2670
2671#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 984
2638 2672
2639/******************************************************************************/ 2673/******************************************************************************/
2640 2674
diff --git a/src/include/gnunet_rest_lib.h b/src/include/gnunet_rest_lib.h
index a4dbb0696..e571eead3 100644
--- a/src/include/gnunet_rest_lib.h
+++ b/src/include/gnunet_rest_lib.h
@@ -89,7 +89,7 @@ typedef void (*GNUNET_REST_ResultProcessor) (void *cls,
89 * 89 *
90 * @param url URL to check 90 * @param url URL to check
91 * @param namespace namespace to check against 91 * @param namespace namespace to check against
92 * @retun GNUNET_YES if namespace matches 92 * @return GNUNET_YES if namespace matches
93 */ 93 */
94int 94int
95GNUNET_REST_namespace_match (const char *url, const char *namespace); 95GNUNET_REST_namespace_match (const char *url, const char *namespace);
@@ -98,7 +98,7 @@ GNUNET_REST_namespace_match (const char *url, const char *namespace);
98 * Create REST MHD response 98 * Create REST MHD response
99 * 99 *
100 * @param data result 100 * @param data result
101 * @retun MHD response 101 * @return MHD response
102 */ 102 */
103 struct MHD_Response* 103 struct MHD_Response*
104GNUNET_REST_create_response (const char *data); 104GNUNET_REST_create_response (const char *data);
diff --git a/src/include/gnunet_rest_plugin.h b/src/include/gnunet_rest_plugin.h
index ecd5f66f1..424dbb1fc 100644
--- a/src/include/gnunet_rest_plugin.h
+++ b/src/include/gnunet_rest_plugin.h
@@ -57,7 +57,7 @@ struct GNUNET_REST_Plugin
57 57
58 /** 58 /**
59 * Plugin name. Used as the namespace for the API. 59 * Plugin name. Used as the namespace for the API.
60 * e.g. http://hostname:port/<name> 60 * e.g. http://hostname:port/name
61 */ 61 */
62 char *name; 62 char *name;
63 63
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index c1e0d005c..03bc4575e 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -185,6 +185,11 @@ extern "C"
185 */ 185 */
186#define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27 186#define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27
187 187
188/**
189 * Signature for a GNUnet credential
190 */
191#define GNUNET_SIGNATURE_PURPOSE_CREDENTIAL 28
192
188#if 0 /* keep Emacsens' auto-indent happy */ 193#if 0 /* keep Emacsens' auto-indent happy */
189{ 194{
190#endif 195#endif
diff --git a/src/jsonapi/jsonapi_document.c b/src/jsonapi/jsonapi_document.c
index 600b7ee6a..3a60940f6 100644
--- a/src/jsonapi/jsonapi_document.c
+++ b/src/jsonapi/jsonapi_document.c
@@ -332,28 +332,20 @@ GNUNET_JSONAPI_document_to_json (const struct GNUNET_JSONAPI_Document *doc,
332 GNUNET_JSONAPI_KEY_ERRORS, 332 GNUNET_JSONAPI_KEY_ERRORS,
333 res_json); 333 res_json);
334 } else { 334 } else {
335 switch (doc->res_count) 335 if (0 == doc->res_count)
336 { 336 {
337 case 0: 337 res_json = json_null();
338 res_json = json_null(); 338 } else {
339 break; 339 res_json = json_array ();
340 case 1: 340 for (res = doc->res_list_head;
341 res != NULL;
342 res = res->next)
343 {
341 GNUNET_assert (GNUNET_OK == 344 GNUNET_assert (GNUNET_OK ==
342 GNUNET_JSONAPI_resource_to_json (doc->res_list_head, 345 GNUNET_JSONAPI_resource_to_json (res,
343 &res_json)); 346 &res_json_tmp));
344 break; 347 json_array_append_new (res_json, res_json_tmp);
345 default: 348 }
346 res_json = json_array ();
347 for (res = doc->res_list_head;
348 res != NULL;
349 res = res->next)
350 {
351 GNUNET_assert (GNUNET_OK ==
352 GNUNET_JSONAPI_resource_to_json (res,
353 &res_json_tmp));
354 json_array_append (res_json, res_json_tmp);
355 }
356 break;
357 } 349 }
358 json_object_set_new (*root_json, 350 json_object_set_new (*root_json,
359 GNUNET_JSONAPI_KEY_DATA, 351 GNUNET_JSONAPI_KEY_DATA,
diff --git a/src/jsonapi/jsonapi_resource.c b/src/jsonapi/jsonapi_resource.c
index 85bca10ee..be28ad5df 100644
--- a/src/jsonapi/jsonapi_resource.c
+++ b/src/jsonapi/jsonapi_resource.c
@@ -92,9 +92,9 @@ GNUNET_JSONAPI_resource_new (const char *type, const char *id)
92{ 92{
93 struct GNUNET_JSONAPI_Resource *res; 93 struct GNUNET_JSONAPI_Resource *res;
94 94
95 if ( (NULL == type) || (0 == strlen (type)) ) 95 if (NULL == type)
96 return NULL; 96 return NULL;
97 if ( (NULL == id) || (0 == strlen (id)) ) 97 if (NULL == id)
98 return NULL; 98 return NULL;
99 99
100 res = GNUNET_new (struct GNUNET_JSONAPI_Resource); 100 res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
@@ -245,7 +245,7 @@ GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource
245 * @param res the JSON resource 245 * @param res the JSON resource
246 * @return the resource id 246 * @return the resource id
247 */ 247 */
248char* 248const char*
249GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource) 249GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource)
250{ 250{
251 return resource->id; 251 return resource->id;
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c
index 50957a5b4..05776801b 100644
--- a/src/namestore/plugin_rest_namestore.c
+++ b/src/namestore/plugin_rest_namestore.c
@@ -401,11 +401,16 @@ namestore_list_finished (void *cls)
401 struct MHD_Response *resp; 401 struct MHD_Response *resp;
402 402
403 handle->list_it = NULL; 403 handle->list_it = NULL;
404 if (NULL == handle->resp_object)
405 handle->resp_object = GNUNET_JSONAPI_document_new ();
406
404 if (GNUNET_SYSERR == 407 if (GNUNET_SYSERR ==
405 GNUNET_JSONAPI_document_serialize (handle->resp_object, 408 GNUNET_JSONAPI_document_serialize (handle->resp_object,
406 &result)) 409 &result))
407 { 410 {
408 do_error (handle); 411 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
412 GNUNET_SCHEDULER_add_now (&do_error,
413 handle);
409 return; 414 return;
410 } 415 }
411 resp = GNUNET_REST_create_response (result); 416 resp = GNUNET_REST_create_response (result);
@@ -467,10 +472,10 @@ namestore_list_response (void *cls,
467 if (0 < json_array_size(result_array)) 472 if (0 < json_array_size(result_array))
468 { 473 {
469 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO, 474 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
470 rname); 475 rname);
471 GNUNET_JSONAPI_resource_add_attr (json_resource, 476 GNUNET_JSONAPI_resource_add_attr (json_resource,
472 GNUNET_REST_JSONAPI_NAMESTORE_RECORD, 477 GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
473 result_array); 478 result_array);
474 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); 479 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
475 } 480 }
476 481
@@ -767,8 +772,8 @@ namestore_create_cont (struct GNUNET_REST_RequestHandle *con,
767 } 772 }
768 term_data[handle->rest_handle->data_size] = '\0'; 773 term_data[handle->rest_handle->data_size] = '\0';
769 GNUNET_memcpy (term_data, 774 GNUNET_memcpy (term_data,
770 handle->rest_handle->data, 775 handle->rest_handle->data,
771 handle->rest_handle->data_size); 776 handle->rest_handle->data_size);
772 data_js = json_loads (term_data, 777 data_js = json_loads (term_data,
773 JSON_DECODE_ANY, 778 JSON_DECODE_ANY,
774 &err); 779 &err);
@@ -902,7 +907,7 @@ namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con,
902 if ((NULL == handle->zkey_str) || 907 if ((NULL == handle->zkey_str) ||
903 (GNUNET_OK != 908 (GNUNET_OK !=
904 GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str, 909 GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str,
905 strlen (handle->zkey_str), 910 strlen (handle->zkey_str),
906 &pubkey))) 911 &pubkey)))
907 { 912 {
908 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 913 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1021,13 +1026,13 @@ identity_cb (void *cls,
1021 1026
1022 if (GNUNET_OK != 1027 if (GNUNET_OK !=
1023 GNUNET_JSONAPI_handle_request (handle->rest_handle, 1028 GNUNET_JSONAPI_handle_request (handle->rest_handle,
1024 handlers, 1029 handlers,
1025 &err, 1030 &err,
1026 handle)) 1031 handle))
1027 { 1032 {
1028 handle->response_code = err.error_code; 1033 handle->response_code = err.error_code;
1029 GNUNET_SCHEDULER_add_now (&do_error, 1034 GNUNET_SCHEDULER_add_now (&do_error,
1030 (void *) handle); 1035 (void *) handle);
1031 } 1036 }
1032} 1037}
1033 1038
diff --git a/src/rest/rest.conf b/src/rest/rest.conf
index 6cd013345..b86e6c1a0 100644
--- a/src/rest/rest.conf
+++ b/src/rest/rest.conf
@@ -1,4 +1,5 @@
1[rest] 1[rest]
2UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-rest.sock
2BINARY=gnunet-rest-server 3BINARY=gnunet-rest-server
3REST_PORT=7776 4REST_PORT=7776
4REST_ALLOW_HEADERS=Authorization,Accept,Content-Type 5REST_ALLOW_HEADERS=Authorization,Accept,Content-Type
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index c26e3e84b..eb655157d 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -123,7 +123,6 @@ libgnunetutil_la_LDFLAGS = \
123 $(GN_LIB_LDFLAGS) \ 123 $(GN_LIB_LDFLAGS) \
124 -version-info 13:0:0 124 -version-info 13:0:0
125 125
126
127libgnunetutil_taler_wallet_la_SOURCES = \ 126libgnunetutil_taler_wallet_la_SOURCES = \
128 common_allocation.c \ 127 common_allocation.c \
129 common_endian.c \ 128 common_endian.c \
diff --git a/src/util/crypto_abe.c b/src/util/crypto_abe.c
new file mode 100644
index 000000000..fcaa826ed
--- /dev/null
+++ b/src/util/crypto_abe.c
@@ -0,0 +1,416 @@
1/*
2 This file is part of GNUnet. Copyright (C) 2001-2014 Christian Grothoff
3 (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19
20*/
21
22/**
23 * @file util/crypto_random.c
24 * @brief functions to gather random numbers
25 * @author Christian Grothoff
26 */
27
28
29#include "platform.h"
30#include <pbc/pbc.h>
31#include <gabe.h>
32
33#include "gnunet_crypto_lib.h"
34
35struct GNUNET_CRYPTO_AbeMasterKey
36{
37 gabe_pub_t* pub;
38 gabe_msk_t* msk;
39};
40
41struct GNUNET_CRYPTO_AbeKey
42{
43 gabe_pub_t* pub;
44 gabe_prv_t* prv;
45};
46
47static int
48init_aes( element_t k, int enc,
49 gcry_cipher_hd_t* handle,
50 struct GNUNET_CRYPTO_SymmetricSessionKey *key,
51 unsigned char* iv)
52{
53 int rc;
54 int key_len;
55 unsigned char* key_buf;
56
57 key_len = element_length_in_bytes(k) < 33 ? 3 : element_length_in_bytes(k);
58 key_buf = (unsigned char*) malloc(key_len);
59 element_to_bytes(key_buf, k);
60
61 memcpy (key->aes_key, key_buf, GNUNET_CRYPTO_AES_KEY_LENGTH);
62 GNUNET_assert (0 ==
63 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
64 GCRY_CIPHER_MODE_CFB, 0));
65 rc = gcry_cipher_setkey (*handle,
66 key->aes_key,
67 sizeof (key->aes_key));
68 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
69 memset (iv, 0, 16); //TODO make reasonable
70 rc = gcry_cipher_setiv (*handle,
71 iv,
72 16);
73 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
74
75 free(key_buf);
76 return rc;
77}
78
79static int
80aes_128_cbc_encrypt( char* pt,
81 int size,
82 element_t k,
83 char **ct )
84{
85 gcry_cipher_hd_t handle;
86 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
87 unsigned char iv[16];
88 char* buf;
89 int padding;
90 int buf_size;
91 uint8_t len[4];
92 init_aes(k, 1, &handle, &skey, iv);
93
94 /* TODO make less crufty */
95
96 /* stuff in real length (big endian) before padding */
97 len[0] = (size & 0xff000000)>>24;
98 len[1] = (size & 0xff0000)>>16;
99 len[2] = (size & 0xff00)>>8;
100 len[3] = (size & 0xff)>>0;
101 padding = 16 - ((4+size) % 16);
102 buf_size = 4 + size + padding;
103 buf = GNUNET_malloc (buf_size);
104 GNUNET_memcpy (buf, len, 4);
105 GNUNET_memcpy (buf+4, pt, size);
106 *ct = GNUNET_malloc (buf_size);
107
108 GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf, buf_size));
109 gcry_cipher_close (handle);
110 //AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
111 GNUNET_free (buf);
112 return buf_size;
113}
114
115static int
116aes_128_cbc_decrypt( char* ct,
117 int size,
118 element_t k,
119 char **pt )
120{
121 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
122 gcry_cipher_hd_t handle;
123 unsigned char iv[16];
124 char* tmp;
125 uint32_t len;
126
127 init_aes(k, 1, &handle, &skey, iv);
128
129 tmp = GNUNET_malloc (size);
130
131 //AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
132 GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size));
133 gcry_cipher_close (handle);
134 /* TODO make less crufty */
135
136 /* get real length */
137 len = 0;
138 len = len
139 | ((tmp[0])<<24) | ((tmp[1])<<16)
140 | ((tmp[2])<<8) | ((tmp[3])<<0);
141 /* truncate any garbage from the padding */
142 *pt = GNUNET_malloc (len);
143 GNUNET_memcpy (*pt, tmp+4, len);
144 GNUNET_free (tmp);
145 return len;
146}
147
148struct GNUNET_CRYPTO_AbeMasterKey*
149GNUNET_CRYPTO_cpabe_create_master_key (void)
150{
151 struct GNUNET_CRYPTO_AbeMasterKey* key;
152 key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
153 gabe_setup(&key->pub, &key->msk);
154 GNUNET_assert (NULL != key->pub);
155 GNUNET_assert (NULL != key->msk);
156 return key;
157}
158
159void
160GNUNET_CRYPTO_cpabe_delete_master_key (struct GNUNET_CRYPTO_AbeMasterKey *key)
161{
162 gabe_msk_free (key->msk);
163 gabe_pub_free (key->pub);
164 //GNUNET_free (key->msk);
165 //gabe_msk_free (key->msk); //For some reason free of pub implicit?
166 GNUNET_free (key);
167}
168
169struct GNUNET_CRYPTO_AbeKey*
170GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *key,
171 char **attrs)
172{
173 struct GNUNET_CRYPTO_AbeKey *prv_key;
174 int size;
175 char *tmp;
176
177 prv_key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
178 prv_key->prv = gabe_keygen(key->pub, key->msk, attrs);
179 size = gabe_pub_serialize(key->pub, &tmp);
180 prv_key->pub = gabe_pub_unserialize(tmp, size);
181 GNUNET_free (tmp);
182 GNUNET_assert (NULL != prv_key->prv);
183 return prv_key;
184}
185
186void
187GNUNET_CRYPTO_cpabe_delete_key (struct GNUNET_CRYPTO_AbeKey *key,
188 int delete_pub)
189{
190 //Memory management in gabe is buggy
191 gabe_prv_free (key->prv);
192 if (GNUNET_YES == delete_pub)
193 gabe_pub_free (key->pub);
194 GNUNET_free (key);
195}
196
197ssize_t
198write_cpabe (void **result,
199 uint32_t file_len,
200 char* cph_buf,
201 int cph_buf_len,
202 char* aes_buf,
203 int aes_buf_len)
204{
205 char *ptr;
206 uint32_t *len;
207
208 *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
209 ptr = *result;
210 len = (uint32_t*) ptr;
211 *len = htonl (file_len);
212 ptr += 4;
213 len = (uint32_t*) ptr;
214 *len = htonl (aes_buf_len);
215 ptr += 4;
216 memcpy (ptr, aes_buf, aes_buf_len);
217 ptr += aes_buf_len;
218 len = (uint32_t*) ptr;
219 *len = htonl (cph_buf_len);
220 ptr += 4;
221 memcpy (ptr, cph_buf, cph_buf_len);
222 return 12 + cph_buf_len + aes_buf_len;
223}
224
225ssize_t
226read_cpabe (const void *data,
227 char** cph_buf,
228 int *cph_buf_len,
229 char** aes_buf,
230 int *aes_buf_len)
231{
232 int buf_len;
233 char *ptr;
234 uint32_t *len;
235
236 ptr = (char*)data;
237 len = (uint32_t*)ptr;
238 buf_len = ntohl (*len);
239 ptr += 4;
240 len = (uint32_t*)ptr;
241 *aes_buf_len = ntohl (*len);
242 ptr += 4;
243 *aes_buf = GNUNET_malloc (*aes_buf_len);
244 memcpy(*aes_buf, ptr, *aes_buf_len);
245 ptr += *aes_buf_len;
246 len = (uint32_t*)ptr;
247 *cph_buf_len = ntohl (*len);
248 ptr += 4;
249 *cph_buf = GNUNET_malloc (*cph_buf_len);
250 memcpy(*cph_buf, ptr, *cph_buf_len);
251
252 return buf_len;
253}
254
255ssize_t
256GNUNET_CRYPTO_cpabe_encrypt (const void *block,
257 size_t size,
258 const char *policy,
259 const struct GNUNET_CRYPTO_AbeMasterKey *key,
260 void **result)
261{
262 gabe_cph_t* cph;
263 char* plt;
264 char* cph_buf;
265 char* aes_buf;
266 element_t m;
267 int cph_buf_len;
268 int aes_buf_len;
269 ssize_t result_len;
270
271 if( !(cph = gabe_enc(key->pub, m, (char*)policy)) )
272 return GNUNET_SYSERR;
273 cph_buf_len = gabe_cph_serialize(cph,
274 &cph_buf);
275 gabe_cph_free(cph);
276 GNUNET_free (cph);
277 plt = GNUNET_memdup (block, size);
278 aes_buf_len = aes_128_cbc_encrypt(plt, size, m, &aes_buf);
279 GNUNET_free (plt);
280 element_clear(m);
281 result_len = write_cpabe(result, size, cph_buf, cph_buf_len, aes_buf, aes_buf_len);
282 GNUNET_free(cph_buf);
283 GNUNET_free(aes_buf);
284 return result_len;
285}
286
287ssize_t
288GNUNET_CRYPTO_cpabe_decrypt (const void *block,
289 size_t size,
290 const struct GNUNET_CRYPTO_AbeKey *key,
291 void **result)
292{
293 char* aes_buf;
294 char* cph_buf;
295 gabe_cph_t* cph;
296 element_t m;
297 int cph_buf_size;
298 int aes_buf_size;
299 int plt_len;
300
301 read_cpabe(block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
302 cph = gabe_cph_unserialize(key->pub, cph_buf, cph_buf_size);
303 if( !gabe_dec(key->pub, key->prv, cph, m) ) {
304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
305 "%s\n", gabe_error());
306 GNUNET_free (aes_buf);
307 GNUNET_free (cph_buf);
308 gabe_cph_free(cph);
309 GNUNET_free (cph);
310 element_clear (m);
311 return GNUNET_SYSERR;
312 }
313 gabe_cph_free(cph);
314 GNUNET_free (cph);
315 plt_len = aes_128_cbc_decrypt(aes_buf, aes_buf_size, m, (char**)result);
316 GNUNET_free (cph_buf);
317 GNUNET_free (aes_buf);
318 element_clear (m);
319 //freeing is buggy in gabe
320 //gabe_prv_free (prv);
321 //gabe_pub_free (pub);
322 return plt_len;
323}
324
325ssize_t
326GNUNET_CRYPTO_cpabe_serialize_key (const struct GNUNET_CRYPTO_AbeKey *key,
327 void **result)
328{
329 ssize_t len;
330 char *pub;
331 char *prv;
332 int pub_len;
333 int prv_len;
334
335 pub_len = gabe_pub_serialize (key->pub, &pub);
336 prv_len = gabe_prv_serialize (key->prv, &prv);
337
338 len = pub_len + prv_len + 12;
339 write_cpabe (result, len, pub, pub_len, prv, prv_len);
340
341 GNUNET_free (pub);
342 GNUNET_free (prv);
343
344 return len;
345}
346
347struct GNUNET_CRYPTO_AbeKey*
348GNUNET_CRYPTO_cpabe_deserialize_key (const void *data,
349 size_t len)
350{
351 struct GNUNET_CRYPTO_AbeKey *key;
352 char *pub;
353 char *prv;
354 int prv_len;
355 int pub_len;
356
357 key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
358 read_cpabe (data,
359 &pub,
360 &pub_len,
361 &prv,
362 &prv_len);
363 key->pub = gabe_pub_unserialize (pub, pub_len);
364 key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
365
366 GNUNET_free (pub);
367 GNUNET_free (prv);
368 return key;
369}
370
371ssize_t
372GNUNET_CRYPTO_cpabe_serialize_master_key (const struct GNUNET_CRYPTO_AbeMasterKey *key,
373 void **result)
374{
375 ssize_t len;
376 char *pub;
377 char *msk;
378 int pub_len;
379 int msk_len;
380
381 pub_len = gabe_pub_serialize (key->pub, &pub);
382 msk_len = gabe_msk_serialize (key->msk, &msk);
383
384 len = pub_len + msk_len + 12;
385 write_cpabe (result, len, pub, pub_len, msk, msk_len);
386
387 GNUNET_free (pub);
388 GNUNET_free (msk);
389
390 return len;
391}
392
393struct GNUNET_CRYPTO_AbeMasterKey*
394GNUNET_CRYPTO_cpabe_deserialize_master_key (const void *data,
395 size_t len)
396{
397 struct GNUNET_CRYPTO_AbeMasterKey *key;
398 char *msk;
399 char *pub;
400 int msk_len;
401 int pub_len;
402
403 key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
404 read_cpabe (data,
405 &pub,
406 &pub_len,
407 &msk,
408 &msk_len);
409 key->pub = gabe_pub_unserialize (pub, pub_len);
410 key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
411
412 GNUNET_free (pub);
413 GNUNET_free (msk);
414
415 return key;
416}