diff options
73 files changed, 13818 insertions, 3742 deletions
diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..5a193a46d --- /dev/null +++ b/Dockerfile | |||
@@ -0,0 +1,63 @@ | |||
1 | from fedora:26 | ||
2 | |||
3 | # Install the required build tools | ||
4 | RUN 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 | |||
6 | WORKDIR /usr/src | ||
7 | |||
8 | # Install gnurl from source at version gnurl-7.54.0 | ||
9 | RUN git clone https://git.taler.net/gnurl.git --branch gnurl-7.54.0 | ||
10 | WORKDIR /usr/src/gnurl | ||
11 | RUN autoreconf -i | ||
12 | RUN ./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 | ||
20 | RUN make install | ||
21 | WORKDIR /usr/src | ||
22 | |||
23 | RUN dnf -y install wget flex bison | ||
24 | |||
25 | # Install libpbc | ||
26 | RUN wget https://crypto.stanford.edu/pbc/files/pbc-0.5.14.tar.gz | ||
27 | RUN tar xvzpf pbc-0.5.14.tar.gz | ||
28 | WORKDIR /usr/src/pbc-0.5.14 | ||
29 | RUN ./configure --prefix=/usr | ||
30 | RUN make install | ||
31 | WORKDIR /usr/src | ||
32 | |||
33 | RUN dnf -y install glib2-devel | ||
34 | |||
35 | # Install libbswabe | ||
36 | RUN git clone https://github.com/schanzen/libgabe.git | ||
37 | WORKDIR /usr/src/libgabe | ||
38 | RUN ./configure --prefix=/usr | ||
39 | RUN make install | ||
40 | |||
41 | # Install WebUI | ||
42 | WORKDIR /usr/src/ | ||
43 | RUN git clone https://github.com/schanzen/gnunet-webui.git | ||
44 | WORKDIR /usr/src/gnunet-webui | ||
45 | RUN git checkout gnuidentity | ||
46 | |||
47 | RUN mkdir /usr/src/gnunet | ||
48 | WORKDIR /usr/src/gnunet | ||
49 | ADD . . | ||
50 | ARG NUM_JOBS | ||
51 | RUN ./bootstrap | ||
52 | RUN ./configure --prefix=/usr/local | ||
53 | RUN make -j$NUM_JOBS | ||
54 | RUN make install | ||
55 | |||
56 | RUN groupadd gnunetdns | ||
57 | RUN adduser --system -m --home-dir /var/lib/gnunet gnunet | ||
58 | RUN chown gnunet:gnunet /var/lib/gnunet | ||
59 | RUN echo '[arm]\nSYSTEM_ONLY = YES\nUSER_ONLY = NO\n' > /etc/gnunet.conf | ||
60 | |||
61 | ADD docker-entrypoint.sh . | ||
62 | |||
63 | CMD ["sh", "docker-entrypoint.sh"] | ||
diff --git a/configure.ac b/configure.ac index eae03b01b..ac00bd5d6 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -446,6 +446,27 @@ AC_CHECK_LIB(ogg, ogg_stream_flush_fill, | |||
446 | ogg=0) | 446 | ogg=0) |
447 | 447 | ||
448 | 448 | ||
449 | PKG_CHECK_MODULES([GLIB], [glib-2.0]) | ||
450 | # check for pbc library | ||
451 | pbc=0 | ||
452 | AC_CHECK_HEADER([pbc/pbc.h],pbc=1) | ||
453 | AC_CHECK_HEADER([gabe.h],abe=1) | ||
454 | AM_CONDITIONAL(HAVE_PBC, [test "$pbc" = 1]) | ||
455 | AM_CONDITIONAL(HAVE_ABE, [test "$abe" = 1]) | ||
456 | if test "x$pbc" = x1 | ||
457 | then | ||
458 | AC_DEFINE([HAVE_PBC],[1],[Have pbc library]) | ||
459 | else | ||
460 | AC_DEFINE([HAVE_PBC],[0],[Lacking pbc library]) | ||
461 | fi | ||
462 | if test "x$abe" = x1 | ||
463 | then | ||
464 | AC_DEFINE([HAVE_ABE],[1],[Have ABE library]) | ||
465 | else | ||
466 | AC_DEFINE([HAVE_ABE],[0],[Lacking ABE library]) | ||
467 | fi | ||
468 | |||
469 | |||
449 | 470 | ||
450 | gst=0 | 471 | gst=0 |
451 | PKG_CHECK_MODULES( | 472 | PKG_CHECK_MODULES( |
@@ -1570,6 +1591,8 @@ src/gnsrecord/Makefile | |||
1570 | src/hello/Makefile | 1591 | src/hello/Makefile |
1571 | src/identity/Makefile | 1592 | src/identity/Makefile |
1572 | src/identity/identity.conf | 1593 | src/identity/identity.conf |
1594 | src/credential/Makefile | ||
1595 | src/credential/credential.conf | ||
1573 | src/include/Makefile | 1596 | src/include/Makefile |
1574 | src/integration-tests/Makefile | 1597 | src/integration-tests/Makefile |
1575 | src/json/Makefile | 1598 | src/json/Makefile |
@@ -1635,6 +1658,7 @@ src/vpn/vpn.conf | |||
1635 | src/zonemaster/Makefile | 1658 | src/zonemaster/Makefile |
1636 | src/zonemaster/zonemaster.conf | 1659 | src/zonemaster/zonemaster.conf |
1637 | src/rest/Makefile | 1660 | src/rest/Makefile |
1661 | src/identity-attribute/Makefile | ||
1638 | src/identity-provider/Makefile | 1662 | src/identity-provider/Makefile |
1639 | pkgconfig/Makefile | 1663 | pkgconfig/Makefile |
1640 | pkgconfig/gnunetarm.pc | 1664 | pkgconfig/gnunetarm.pc |
diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 000000000..807d86d6f --- /dev/null +++ b/docker-entrypoint.sh | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/bash | ||
2 | gnunet-arm -s > $HOME/gnunet.log 2>&1 | ||
3 | exec bash \ No newline at end of file | ||
diff --git a/po/POTFILES.in b/po/POTFILES.in index 4a4cfbd96..e0654d4b4 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in | |||
@@ -3,13 +3,21 @@ src/arm/arm_monitor_api.c | |||
3 | src/arm/gnunet-arm.c | 3 | src/arm/gnunet-arm.c |
4 | src/arm/gnunet-service-arm.c | 4 | src/arm/gnunet-service-arm.c |
5 | src/arm/mockup-service.c | 5 | src/arm/mockup-service.c |
6 | src/ats-tests/ats-testing-experiment.c | ||
7 | src/ats-tests/ats-testing-log.c | ||
8 | src/ats-tests/ats-testing-preferences.c | ||
9 | src/ats-tests/ats-testing-traffic.c | ||
10 | src/ats-tests/ats-testing.c | ||
11 | src/ats-tests/gnunet-ats-sim.c | ||
12 | src/ats-tests/gnunet-solver-eval.c | ||
13 | src/ats-tool/gnunet-ats.c | ||
6 | src/ats/ats_api_connectivity.c | 14 | src/ats/ats_api_connectivity.c |
7 | src/ats/ats_api_performance.c | 15 | src/ats/ats_api_performance.c |
8 | src/ats/ats_api_scanner.c | 16 | src/ats/ats_api_scanner.c |
9 | src/ats/ats_api_scheduling.c | 17 | src/ats/ats_api_scheduling.c |
10 | src/ats/gnunet-ats-solver-eval.c | 18 | src/ats/gnunet-ats-solver-eval.c |
11 | src/ats/gnunet-service-ats_addresses.c | ||
12 | src/ats/gnunet-service-ats.c | 19 | src/ats/gnunet-service-ats.c |
20 | src/ats/gnunet-service-ats_addresses.c | ||
13 | src/ats/gnunet-service-ats_connectivity.c | 21 | src/ats/gnunet-service-ats_connectivity.c |
14 | src/ats/gnunet-service-ats_normalization.c | 22 | src/ats/gnunet-service-ats_normalization.c |
15 | src/ats/gnunet-service-ats_performance.c | 23 | src/ats/gnunet-service-ats_performance.c |
@@ -20,14 +28,6 @@ src/ats/gnunet-service-ats_scheduling.c | |||
20 | src/ats/plugin_ats_mlp.c | 28 | src/ats/plugin_ats_mlp.c |
21 | src/ats/plugin_ats_proportional.c | 29 | src/ats/plugin_ats_proportional.c |
22 | src/ats/plugin_ats_ril.c | 30 | src/ats/plugin_ats_ril.c |
23 | src/ats-tests/ats-testing.c | ||
24 | src/ats-tests/ats-testing-experiment.c | ||
25 | src/ats-tests/ats-testing-log.c | ||
26 | src/ats-tests/ats-testing-preferences.c | ||
27 | src/ats-tests/ats-testing-traffic.c | ||
28 | src/ats-tests/gnunet-ats-sim.c | ||
29 | src/ats-tests/gnunet-solver-eval.c | ||
30 | src/ats-tool/gnunet-ats.c | ||
31 | src/auction/gnunet-auction-create.c | 31 | src/auction/gnunet-auction-create.c |
32 | src/auction/gnunet-auction-info.c | 32 | src/auction/gnunet-auction-info.c |
33 | src/auction/gnunet-auction-join.c | 33 | src/auction/gnunet-auction-join.c |
@@ -39,8 +39,8 @@ src/block/plugin_block_test.c | |||
39 | src/cadet/cadet_api.c | 39 | src/cadet/cadet_api.c |
40 | src/cadet/cadet_test_lib.c | 40 | src/cadet/cadet_test_lib.c |
41 | src/cadet/desirability_table.c | 41 | src/cadet/desirability_table.c |
42 | src/cadet/gnunet-cadet.c | ||
43 | src/cadet/gnunet-cadet-profiler.c | 42 | src/cadet/gnunet-cadet-profiler.c |
43 | src/cadet/gnunet-cadet.c | ||
44 | src/cadet/gnunet-service-cadet.c | 44 | src/cadet/gnunet-service-cadet.c |
45 | src/cadet/gnunet-service-cadet_channel.c | 45 | src/cadet/gnunet-service-cadet_channel.c |
46 | src/cadet/gnunet-service-cadet_connection.c | 46 | src/cadet/gnunet-service-cadet_connection.c |
@@ -56,15 +56,15 @@ src/consensus/gnunet-service-consensus.c | |||
56 | src/consensus/plugin_block_consensus.c | 56 | src/consensus/plugin_block_consensus.c |
57 | src/conversation/conversation_api.c | 57 | src/conversation/conversation_api.c |
58 | src/conversation/conversation_api_call.c | 58 | src/conversation/conversation_api_call.c |
59 | src/conversation/gnunet-conversation.c | ||
60 | src/conversation/gnunet-conversation-test.c | 59 | src/conversation/gnunet-conversation-test.c |
61 | src/conversation/gnunet_gst.c | 60 | src/conversation/gnunet-conversation.c |
62 | src/conversation/gnunet_gst_test.c | ||
63 | src/conversation/gnunet-helper-audio-playback.c | ||
64 | src/conversation/gnunet-helper-audio-playback-gst.c | 61 | src/conversation/gnunet-helper-audio-playback-gst.c |
65 | src/conversation/gnunet-helper-audio-record.c | 62 | src/conversation/gnunet-helper-audio-playback.c |
66 | src/conversation/gnunet-helper-audio-record-gst.c | 63 | src/conversation/gnunet-helper-audio-record-gst.c |
64 | src/conversation/gnunet-helper-audio-record.c | ||
67 | src/conversation/gnunet-service-conversation.c | 65 | src/conversation/gnunet-service-conversation.c |
66 | src/conversation/gnunet_gst.c | ||
67 | src/conversation/gnunet_gst_test.c | ||
68 | src/conversation/microphone.c | 68 | src/conversation/microphone.c |
69 | src/conversation/plugin_gnsrecord_conversation.c | 69 | src/conversation/plugin_gnsrecord_conversation.c |
70 | src/conversation/speaker.c | 70 | src/conversation/speaker.c |
@@ -75,6 +75,13 @@ src/core/gnunet-service-core.c | |||
75 | src/core/gnunet-service-core_kx.c | 75 | src/core/gnunet-service-core_kx.c |
76 | src/core/gnunet-service-core_sessions.c | 76 | src/core/gnunet-service-core_sessions.c |
77 | src/core/gnunet-service-core_typemap.c | 77 | src/core/gnunet-service-core_typemap.c |
78 | src/credential/credential_api.c | ||
79 | src/credential/credential_misc.c | ||
80 | src/credential/credential_serialization.c | ||
81 | src/credential/gnunet-credential.c | ||
82 | src/credential/gnunet-service-credential.c | ||
83 | src/credential/plugin_gnsrecord_credential.c | ||
84 | src/credential/plugin_rest_credential.c | ||
78 | src/curl/curl.c | 85 | src/curl/curl.c |
79 | src/curl/curl_reschedule.c | 86 | src/curl/curl_reschedule.c |
80 | src/datacache/datacache.c | 87 | src/datacache/datacache.c |
@@ -94,7 +101,6 @@ src/dht/dht_api.c | |||
94 | src/dht/dht_test_lib.c | 101 | src/dht/dht_test_lib.c |
95 | src/dht/gnunet-dht-get.c | 102 | src/dht/gnunet-dht-get.c |
96 | src/dht/gnunet-dht-monitor.c | 103 | src/dht/gnunet-dht-monitor.c |
97 | src/dht/gnunet_dht_profiler.c | ||
98 | src/dht/gnunet-dht-put.c | 104 | src/dht/gnunet-dht-put.c |
99 | src/dht/gnunet-service-dht.c | 105 | src/dht/gnunet-service-dht.c |
100 | src/dht/gnunet-service-dht_clients.c | 106 | src/dht/gnunet-service-dht_clients.c |
@@ -103,6 +109,7 @@ src/dht/gnunet-service-dht_hello.c | |||
103 | src/dht/gnunet-service-dht_neighbours.c | 109 | src/dht/gnunet-service-dht_neighbours.c |
104 | src/dht/gnunet-service-dht_nse.c | 110 | src/dht/gnunet-service-dht_nse.c |
105 | src/dht/gnunet-service-dht_routing.c | 111 | src/dht/gnunet-service-dht_routing.c |
112 | src/dht/gnunet_dht_profiler.c | ||
106 | src/dht/plugin_block_dht.c | 113 | src/dht/plugin_block_dht.c |
107 | src/dns/dns_api.c | 114 | src/dns/dns_api.c |
108 | src/dns/dnsparser.c | 115 | src/dns/dnsparser.c |
@@ -117,8 +124,8 @@ src/dv/gnunet-dv.c | |||
117 | src/dv/gnunet-service-dv.c | 124 | src/dv/gnunet-service-dv.c |
118 | src/dv/plugin_transport_dv.c | 125 | src/dv/plugin_transport_dv.c |
119 | src/exit/gnunet-daemon-exit.c | 126 | src/exit/gnunet-daemon-exit.c |
120 | src/exit/gnunet-helper-exit.c | ||
121 | src/exit/gnunet-helper-exit-windows.c | 127 | src/exit/gnunet-helper-exit-windows.c |
128 | src/exit/gnunet-helper-exit.c | ||
122 | src/fragmentation/defragmentation.c | 129 | src/fragmentation/defragmentation.c |
123 | src/fragmentation/fragmentation.c | 130 | src/fragmentation/fragmentation.c |
124 | src/fs/fs_api.c | 131 | src/fs/fs_api.c |
@@ -143,8 +150,8 @@ src/fs/gnunet-auto-share.c | |||
143 | src/fs/gnunet-daemon-fsprofiler.c | 150 | src/fs/gnunet-daemon-fsprofiler.c |
144 | src/fs/gnunet-directory.c | 151 | src/fs/gnunet-directory.c |
145 | src/fs/gnunet-download.c | 152 | src/fs/gnunet-download.c |
146 | src/fs/gnunet-fs.c | ||
147 | src/fs/gnunet-fs-profiler.c | 153 | src/fs/gnunet-fs-profiler.c |
154 | src/fs/gnunet-fs.c | ||
148 | src/fs/gnunet-helper-fs-publish.c | 155 | src/fs/gnunet-helper-fs-publish.c |
149 | src/fs/gnunet-publish.c | 156 | src/fs/gnunet-publish.c |
150 | src/fs/gnunet-search.c | 157 | src/fs/gnunet-search.c |
@@ -162,10 +169,10 @@ src/fs/plugin_block_fs.c | |||
162 | src/gns/gns_api.c | 169 | src/gns/gns_api.c |
163 | src/gns/gnunet-bcd.c | 170 | src/gns/gnunet-bcd.c |
164 | src/gns/gnunet-dns2gns.c | 171 | src/gns/gnunet-dns2gns.c |
165 | src/gns/gnunet-gns.c | ||
166 | src/gns/gnunet-gns-helper-service-w32.c | 172 | src/gns/gnunet-gns-helper-service-w32.c |
167 | src/gns/gnunet-gns-import.c | 173 | src/gns/gnunet-gns-import.c |
168 | src/gns/gnunet-gns-proxy.c | 174 | src/gns/gnunet-gns-proxy.c |
175 | src/gns/gnunet-gns.c | ||
169 | src/gns/gnunet-service-gns.c | 176 | src/gns/gnunet-service-gns.c |
170 | src/gns/gnunet-service-gns_interceptor.c | 177 | src/gns/gnunet-service-gns_interceptor.c |
171 | src/gns/gnunet-service-gns_resolver.c | 178 | src/gns/gnunet-service-gns_resolver.c |
@@ -174,41 +181,44 @@ src/gns/nss/nss_gns_query.c | |||
174 | src/gns/plugin_block_gns.c | 181 | src/gns/plugin_block_gns.c |
175 | src/gns/plugin_gnsrecord_gns.c | 182 | src/gns/plugin_gnsrecord_gns.c |
176 | src/gns/plugin_rest_gns.c | 183 | src/gns/plugin_rest_gns.c |
184 | src/gns/w32nsp-install.c | ||
185 | src/gns/w32nsp-resolve.c | ||
186 | src/gns/w32nsp-uninstall.c | ||
187 | src/gns/w32nsp.c | ||
177 | src/gnsrecord/gnsrecord.c | 188 | src/gnsrecord/gnsrecord.c |
178 | src/gnsrecord/gnsrecord_crypto.c | 189 | src/gnsrecord/gnsrecord_crypto.c |
179 | src/gnsrecord/gnsrecord_misc.c | 190 | src/gnsrecord/gnsrecord_misc.c |
180 | src/gnsrecord/gnsrecord_serialization.c | 191 | src/gnsrecord/gnsrecord_serialization.c |
181 | src/gnsrecord/plugin_gnsrecord_dns.c | 192 | src/gnsrecord/plugin_gnsrecord_dns.c |
182 | src/gns/w32nsp.c | ||
183 | src/gns/w32nsp-install.c | ||
184 | src/gns/w32nsp-resolve.c | ||
185 | src/gns/w32nsp-uninstall.c | ||
186 | src/hello/address.c | 193 | src/hello/address.c |
187 | src/hello/gnunet-hello.c | 194 | src/hello/gnunet-hello.c |
188 | src/hello/hello.c | 195 | src/hello/hello.c |
189 | src/hostlist/gnunet-daemon-hostlist.c | 196 | src/hostlist/gnunet-daemon-hostlist.c |
190 | src/hostlist/gnunet-daemon-hostlist_client.c | 197 | src/hostlist/gnunet-daemon-hostlist_client.c |
191 | src/hostlist/gnunet-daemon-hostlist_server.c | 198 | src/hostlist/gnunet-daemon-hostlist_server.c |
199 | src/identity-attribute/identity_attribute.c | ||
200 | src/identity-attribute/plugin_identity_attribute_gnuid.c | ||
201 | src/identity-provider/gnunet-idp.c | ||
202 | src/identity-provider/gnunet-service-identity-provider.c | ||
203 | src/identity-provider/identity_provider_api.c | ||
204 | src/identity-provider/jwt.c | ||
205 | src/identity-provider/plugin_gnsrecord_identity_provider.c | ||
206 | src/identity-provider/plugin_identity_provider_sqlite.c | ||
207 | src/identity-provider/plugin_rest_identity_provider.c | ||
192 | src/identity/gnunet-identity.c | 208 | src/identity/gnunet-identity.c |
193 | src/identity/gnunet-service-identity.c | 209 | src/identity/gnunet-service-identity.c |
194 | src/identity/identity_api.c | 210 | src/identity/identity_api.c |
195 | src/identity/identity_api_lookup.c | 211 | src/identity/identity_api_lookup.c |
196 | src/identity/plugin_gnsrecord_identity.c | ||
197 | src/identity/plugin_rest_identity.c | 212 | src/identity/plugin_rest_identity.c |
198 | src/identity-provider/gnunet-identity-token.c | 213 | src/json/json.c |
199 | src/identity-provider/gnunet-service-identity-provider.c | 214 | src/json/json_generator.c |
200 | src/identity-provider/identity_provider_api.c | 215 | src/json/json_helper.c |
201 | src/identity-provider/identity_token.c | 216 | src/json/json_mhd.c |
202 | src/identity-provider/plugin_rest_identity_provider.c | ||
203 | src/jsonapi/jsonapi.c | 217 | src/jsonapi/jsonapi.c |
204 | src/jsonapi/jsonapi_document.c | 218 | src/jsonapi/jsonapi_document.c |
205 | src/jsonapi/jsonapi_error.c | 219 | src/jsonapi/jsonapi_error.c |
206 | src/jsonapi/jsonapi_relationship.c | 220 | src/jsonapi/jsonapi_relationship.c |
207 | src/jsonapi/jsonapi_resource.c | 221 | src/jsonapi/jsonapi_resource.c |
208 | src/json/json.c | ||
209 | src/json/json_generator.c | ||
210 | src/json/json_helper.c | ||
211 | src/json/json_mhd.c | ||
212 | src/multicast/gnunet-multicast.c | 222 | src/multicast/gnunet-multicast.c |
213 | src/multicast/gnunet-service-multicast.c | 223 | src/multicast/gnunet-service-multicast.c |
214 | src/multicast/multicast_api.c | 224 | src/multicast/multicast_api.c |
@@ -222,8 +232,8 @@ src/namecache/namecache_api.c | |||
222 | src/namecache/plugin_namecache_flat.c | 232 | src/namecache/plugin_namecache_flat.c |
223 | src/namecache/plugin_namecache_postgres.c | 233 | src/namecache/plugin_namecache_postgres.c |
224 | src/namecache/plugin_namecache_sqlite.c | 234 | src/namecache/plugin_namecache_sqlite.c |
225 | src/namestore/gnunet-namestore.c | ||
226 | src/namestore/gnunet-namestore-fcfsd.c | 235 | src/namestore/gnunet-namestore-fcfsd.c |
236 | src/namestore/gnunet-namestore.c | ||
227 | src/namestore/gnunet-service-namestore.c | 237 | src/namestore/gnunet-service-namestore.c |
228 | src/namestore/namestore_api.c | 238 | src/namestore/namestore_api.c |
229 | src/namestore/namestore_api_monitor.c | 239 | src/namestore/namestore_api_monitor.c |
@@ -238,10 +248,10 @@ src/nat-auto/gnunet-service-nat-auto.c | |||
238 | src/nat-auto/gnunet-service-nat-auto_legacy.c | 248 | src/nat-auto/gnunet-service-nat-auto_legacy.c |
239 | src/nat-auto/nat_auto_api.c | 249 | src/nat-auto/nat_auto_api.c |
240 | src/nat-auto/nat_auto_api_test.c | 250 | src/nat-auto/nat_auto_api_test.c |
241 | src/nat/gnunet-helper-nat-client.c | ||
242 | src/nat/gnunet-helper-nat-client-windows.c | 251 | src/nat/gnunet-helper-nat-client-windows.c |
243 | src/nat/gnunet-helper-nat-server.c | 252 | src/nat/gnunet-helper-nat-client.c |
244 | src/nat/gnunet-helper-nat-server-windows.c | 253 | src/nat/gnunet-helper-nat-server-windows.c |
254 | src/nat/gnunet-helper-nat-server.c | ||
245 | src/nat/gnunet-nat.c | 255 | src/nat/gnunet-nat.c |
246 | src/nat/gnunet-service-nat.c | 256 | src/nat/gnunet-service-nat.c |
247 | src/nat/gnunet-service-nat_externalip.c | 257 | src/nat/gnunet-service-nat_externalip.c |
@@ -250,15 +260,15 @@ src/nat/gnunet-service-nat_mini.c | |||
250 | src/nat/gnunet-service-nat_stun.c | 260 | src/nat/gnunet-service-nat_stun.c |
251 | src/nat/nat_api.c | 261 | src/nat/nat_api.c |
252 | src/nat/nat_api_stun.c | 262 | src/nat/nat_api_stun.c |
253 | src/nse/gnunet-nse.c | ||
254 | src/nse/gnunet-nse-profiler.c | 263 | src/nse/gnunet-nse-profiler.c |
264 | src/nse/gnunet-nse.c | ||
255 | src/nse/gnunet-service-nse.c | 265 | src/nse/gnunet-service-nse.c |
256 | src/nse/nse_api.c | 266 | src/nse/nse_api.c |
267 | src/peerinfo-tool/gnunet-peerinfo.c | ||
268 | src/peerinfo-tool/gnunet-peerinfo_plugins.c | ||
257 | src/peerinfo/gnunet-service-peerinfo.c | 269 | src/peerinfo/gnunet-service-peerinfo.c |
258 | src/peerinfo/peerinfo_api.c | 270 | src/peerinfo/peerinfo_api.c |
259 | src/peerinfo/peerinfo_api_notify.c | 271 | src/peerinfo/peerinfo_api_notify.c |
260 | src/peerinfo-tool/gnunet-peerinfo.c | ||
261 | src/peerinfo-tool/gnunet-peerinfo_plugins.c | ||
262 | src/peerstore/gnunet-peerstore.c | 272 | src/peerstore/gnunet-peerstore.c |
263 | src/peerstore/gnunet-service-peerstore.c | 273 | src/peerstore/gnunet-service-peerstore.c |
264 | src/peerstore/peerstore_api.c | 274 | src/peerstore/peerstore_api.c |
@@ -309,13 +319,13 @@ src/rps/gnunet-service-rps_custommap.c | |||
309 | src/rps/gnunet-service-rps_sampler.c | 319 | src/rps/gnunet-service-rps_sampler.c |
310 | src/rps/gnunet-service-rps_sampler_elem.c | 320 | src/rps/gnunet-service-rps_sampler_elem.c |
311 | src/rps/gnunet-service-rps_view.c | 321 | src/rps/gnunet-service-rps_view.c |
312 | src/rps/rps_api.c | ||
313 | src/rps/rps-test_util.c | 322 | src/rps/rps-test_util.c |
323 | src/rps/rps_api.c | ||
314 | src/scalarproduct/gnunet-scalarproduct.c | 324 | src/scalarproduct/gnunet-scalarproduct.c |
315 | src/scalarproduct/gnunet-service-scalarproduct_alice.c | ||
316 | src/scalarproduct/gnunet-service-scalarproduct_bob.c | ||
317 | src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c | 325 | src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c |
318 | src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c | 326 | src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c |
327 | src/scalarproduct/gnunet-service-scalarproduct_alice.c | ||
328 | src/scalarproduct/gnunet-service-scalarproduct_bob.c | ||
319 | src/scalarproduct/scalarproduct_api.c | 329 | src/scalarproduct/scalarproduct_api.c |
320 | src/secretsharing/gnunet-secretsharing-profiler.c | 330 | src/secretsharing/gnunet-secretsharing-profiler.c |
321 | src/secretsharing/gnunet-service-secretsharing.c | 331 | src/secretsharing/gnunet-service-secretsharing.c |
@@ -342,15 +352,16 @@ src/statistics/gnunet-statistics.c | |||
342 | src/statistics/statistics_api.c | 352 | src/statistics/statistics_api.c |
343 | src/template/gnunet-service-template.c | 353 | src/template/gnunet-service-template.c |
344 | src/template/gnunet-template.c | 354 | src/template/gnunet-template.c |
355 | src/testbed-logger/gnunet-service-testbed-logger.c | ||
356 | src/testbed-logger/testbed_logger_api.c | ||
345 | src/testbed/generate-underlay-topology.c | 357 | src/testbed/generate-underlay-topology.c |
346 | src/testbed/gnunet-daemon-latency-logger.c | 358 | src/testbed/gnunet-daemon-latency-logger.c |
347 | src/testbed/gnunet-daemon-testbed-blacklist.c | 359 | src/testbed/gnunet-daemon-testbed-blacklist.c |
348 | src/testbed/gnunet-daemon-testbed-underlay.c | 360 | src/testbed/gnunet-daemon-testbed-underlay.c |
349 | src/testbed/gnunet-helper-testbed.c | 361 | src/testbed/gnunet-helper-testbed.c |
350 | src/testbed/gnunet_mpi_test.c | ||
351 | src/testbed/gnunet-service-test-barriers.c | 362 | src/testbed/gnunet-service-test-barriers.c |
352 | src/testbed/gnunet-service-testbed_barriers.c | ||
353 | src/testbed/gnunet-service-testbed.c | 363 | src/testbed/gnunet-service-testbed.c |
364 | src/testbed/gnunet-service-testbed_barriers.c | ||
354 | src/testbed/gnunet-service-testbed_cache.c | 365 | src/testbed/gnunet-service-testbed_cache.c |
355 | src/testbed/gnunet-service-testbed_connectionpool.c | 366 | src/testbed/gnunet-service-testbed_connectionpool.c |
356 | src/testbed/gnunet-service-testbed_cpustatus.c | 367 | src/testbed/gnunet-service-testbed_cpustatus.c |
@@ -358,20 +369,19 @@ src/testbed/gnunet-service-testbed_links.c | |||
358 | src/testbed/gnunet-service-testbed_meminfo.c | 369 | src/testbed/gnunet-service-testbed_meminfo.c |
359 | src/testbed/gnunet-service-testbed_oc.c | 370 | src/testbed/gnunet-service-testbed_oc.c |
360 | src/testbed/gnunet-service-testbed_peers.c | 371 | src/testbed/gnunet-service-testbed_peers.c |
361 | src/testbed/gnunet_testbed_mpi_spawn.c | ||
362 | src/testbed/gnunet-testbed-profiler.c | 372 | src/testbed/gnunet-testbed-profiler.c |
363 | src/testbed-logger/gnunet-service-testbed-logger.c | 373 | src/testbed/gnunet_mpi_test.c |
364 | src/testbed-logger/testbed_logger_api.c | 374 | src/testbed/gnunet_testbed_mpi_spawn.c |
365 | src/testbed/testbed_api_barriers.c | ||
366 | src/testbed/testbed_api.c | 375 | src/testbed/testbed_api.c |
376 | src/testbed/testbed_api_barriers.c | ||
367 | src/testbed/testbed_api_hosts.c | 377 | src/testbed/testbed_api_hosts.c |
368 | src/testbed/testbed_api_operations.c | 378 | src/testbed/testbed_api_operations.c |
369 | src/testbed/testbed_api_peers.c | 379 | src/testbed/testbed_api_peers.c |
370 | src/testbed/testbed_api_sd.c | 380 | src/testbed/testbed_api_sd.c |
371 | src/testbed/testbed_api_services.c | 381 | src/testbed/testbed_api_services.c |
372 | src/testbed/testbed_api_statistics.c | 382 | src/testbed/testbed_api_statistics.c |
373 | src/testbed/testbed_api_testbed.c | ||
374 | src/testbed/testbed_api_test.c | 383 | src/testbed/testbed_api_test.c |
384 | src/testbed/testbed_api_testbed.c | ||
375 | src/testbed/testbed_api_topology.c | 385 | src/testbed/testbed_api_topology.c |
376 | src/testbed/testbed_api_underlay.c | 386 | src/testbed/testbed_api_underlay.c |
377 | src/testing/gnunet-testing.c | 387 | src/testing/gnunet-testing.c |
@@ -380,34 +390,39 @@ src/testing/testing.c | |||
380 | src/topology/friends.c | 390 | src/topology/friends.c |
381 | src/topology/gnunet-daemon-topology.c | 391 | src/topology/gnunet-daemon-topology.c |
382 | src/transport/gnunet-helper-transport-bluetooth.c | 392 | src/transport/gnunet-helper-transport-bluetooth.c |
383 | src/transport/gnunet-helper-transport-wlan.c | ||
384 | src/transport/gnunet-helper-transport-wlan-dummy.c | 393 | src/transport/gnunet-helper-transport-wlan-dummy.c |
385 | src/transport/gnunet-service-transport_ats.c | 394 | src/transport/gnunet-helper-transport-wlan.c |
386 | src/transport/gnunet-service-transport.c | 395 | src/transport/gnunet-service-transport.c |
396 | src/transport/gnunet-service-transport_ats.c | ||
387 | src/transport/gnunet-service-transport_hello.c | 397 | src/transport/gnunet-service-transport_hello.c |
388 | src/transport/gnunet-service-transport_manipulation.c | 398 | src/transport/gnunet-service-transport_manipulation.c |
389 | src/transport/gnunet-service-transport_neighbours.c | 399 | src/transport/gnunet-service-transport_neighbours.c |
390 | src/transport/gnunet-service-transport_plugins.c | 400 | src/transport/gnunet-service-transport_plugins.c |
391 | src/transport/gnunet-service-transport_validation.c | 401 | src/transport/gnunet-service-transport_validation.c |
392 | src/transport/gnunet-transport.c | ||
393 | src/transport/gnunet-transport-certificate-creation.c | 402 | src/transport/gnunet-transport-certificate-creation.c |
394 | src/transport/gnunet-transport-profiler.c | 403 | src/transport/gnunet-transport-profiler.c |
395 | src/transport/gnunet-transport-wlan-receiver.c | 404 | src/transport/gnunet-transport-wlan-receiver.c |
396 | src/transport/gnunet-transport-wlan-sender.c | 405 | src/transport/gnunet-transport-wlan-sender.c |
406 | src/transport/gnunet-transport.c | ||
397 | src/transport/plugin_transport_http_client.c | 407 | src/transport/plugin_transport_http_client.c |
398 | src/transport/plugin_transport_http_common.c | 408 | src/transport/plugin_transport_http_common.c |
399 | src/transport/plugin_transport_http_server.c | 409 | src/transport/plugin_transport_http_server.c |
400 | src/transport/plugin_transport_smtp.c | 410 | src/transport/plugin_transport_smtp.c |
401 | src/transport/plugin_transport_tcp.c | 411 | src/transport/plugin_transport_tcp.c |
402 | src/transport/plugin_transport_template.c | 412 | src/transport/plugin_transport_template.c |
403 | src/transport/plugin_transport_udp_broadcasting.c | ||
404 | src/transport/plugin_transport_udp.c | 413 | src/transport/plugin_transport_udp.c |
414 | src/transport/plugin_transport_udp_broadcasting.c | ||
405 | src/transport/plugin_transport_unix.c | 415 | src/transport/plugin_transport_unix.c |
406 | src/transport/plugin_transport_wlan.c | 416 | src/transport/plugin_transport_wlan.c |
407 | src/transport/tcp_connection_legacy.c | 417 | src/transport/tcp_connection_legacy.c |
408 | src/transport/tcp_server_legacy.c | 418 | src/transport/tcp_server_legacy.c |
409 | src/transport/tcp_server_mst_legacy.c | 419 | src/transport/tcp_server_mst_legacy.c |
410 | src/transport/tcp_service_legacy.c | 420 | src/transport/tcp_service_legacy.c |
421 | src/transport/transport-testing-filenames.c | ||
422 | src/transport/transport-testing-loggers.c | ||
423 | src/transport/transport-testing-main.c | ||
424 | src/transport/transport-testing-send.c | ||
425 | src/transport/transport-testing.c | ||
411 | src/transport/transport_api_address_to_string.c | 426 | src/transport/transport_api_address_to_string.c |
412 | src/transport/transport_api_blacklist.c | 427 | src/transport/transport_api_blacklist.c |
413 | src/transport/transport_api_core.c | 428 | src/transport/transport_api_core.c |
@@ -416,11 +431,6 @@ src/transport/transport_api_manipulation.c | |||
416 | src/transport/transport_api_monitor_peers.c | 431 | src/transport/transport_api_monitor_peers.c |
417 | src/transport/transport_api_monitor_plugins.c | 432 | src/transport/transport_api_monitor_plugins.c |
418 | src/transport/transport_api_offer_hello.c | 433 | src/transport/transport_api_offer_hello.c |
419 | src/transport/transport-testing.c | ||
420 | src/transport/transport-testing-filenames.c | ||
421 | src/transport/transport-testing-loggers.c | ||
422 | src/transport/transport-testing-main.c | ||
423 | src/transport/transport-testing-send.c | ||
424 | src/tun/regex.c | 434 | src/tun/regex.c |
425 | src/tun/tun.c | 435 | src/tun/tun.c |
426 | src/util/bandwidth.c | 436 | src/util/bandwidth.c |
@@ -434,10 +444,11 @@ src/util/configuration_loader.c | |||
434 | src/util/container_bloomfilter.c | 444 | src/util/container_bloomfilter.c |
435 | src/util/container_heap.c | 445 | src/util/container_heap.c |
436 | src/util/container_meta_data.c | 446 | src/util/container_meta_data.c |
437 | src/util/container_multihashmap32.c | ||
438 | src/util/container_multihashmap.c | 447 | src/util/container_multihashmap.c |
448 | src/util/container_multihashmap32.c | ||
439 | src/util/container_multipeermap.c | 449 | src/util/container_multipeermap.c |
440 | src/util/container_multishortmap.c | 450 | src/util/container_multishortmap.c |
451 | src/util/crypto_abe.c | ||
441 | src/util/crypto_crc.c | 452 | src/util/crypto_crc.c |
442 | src/util/crypto_ecc.c | 453 | src/util/crypto_ecc.c |
443 | src/util/crypto_ecc_dlog.c | 454 | src/util/crypto_ecc_dlog.c |
@@ -454,8 +465,8 @@ src/util/crypto_symmetric.c | |||
454 | src/util/disk.c | 465 | src/util/disk.c |
455 | src/util/getopt.c | 466 | src/util/getopt.c |
456 | src/util/getopt_helpers.c | 467 | src/util/getopt_helpers.c |
457 | src/util/gnunet-config.c | ||
458 | src/util/gnunet-config-diff.c | 468 | src/util/gnunet-config-diff.c |
469 | src/util/gnunet-config.c | ||
459 | src/util/gnunet-ecc.c | 470 | src/util/gnunet-ecc.c |
460 | src/util/gnunet-helper-w32-console.c | 471 | src/util/gnunet-helper-w32-console.c |
461 | src/util/gnunet-resolver.c | 472 | src/util/gnunet-resolver.c |
@@ -486,8 +497,8 @@ src/util/time.c | |||
486 | src/util/w32cat.c | 497 | src/util/w32cat.c |
487 | src/util/win.c | 498 | src/util/win.c |
488 | src/util/winproc.c | 499 | src/util/winproc.c |
489 | src/vpn/gnunet-helper-vpn.c | ||
490 | src/vpn/gnunet-helper-vpn-windows.c | 500 | src/vpn/gnunet-helper-vpn-windows.c |
501 | src/vpn/gnunet-helper-vpn.c | ||
491 | src/vpn/gnunet-service-vpn.c | 502 | src/vpn/gnunet-service-vpn.c |
492 | src/vpn/gnunet-vpn.c | 503 | src/vpn/gnunet-vpn.c |
493 | src/vpn/vpn_api.c | 504 | src/vpn/vpn_api.c |
diff --git a/src/Makefile.am b/src/Makefile.am index 7f1a00177..fcdd44bfb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -12,11 +12,11 @@ endif | |||
12 | if HAVE_EXPERIMENTAL | 12 | if HAVE_EXPERIMENTAL |
13 | EXP_DIR = \ | 13 | EXP_DIR = \ |
14 | rps | 14 | rps |
15 | endif | 15 | # dv (FTBFS) |
16 | 16 | if HAVE_ABE | |
17 | if HAVE_JSON | 17 | EXP_DIR += identity-attribute \ |
18 | if HAVE_MHD | 18 | identity-provider \ |
19 | PROVIDER_DIR = identity-provider | 19 | credential |
20 | endif | 20 | endif |
21 | endif | 21 | endif |
22 | 22 | ||
@@ -128,7 +128,6 @@ SUBDIRS = \ | |||
128 | psyc \ | 128 | psyc \ |
129 | social \ | 129 | social \ |
130 | $(AUCTION_DIR) \ | 130 | $(AUCTION_DIR) \ |
131 | $(EXP_DIR) \ | 131 | $(EXP_DIR) |
132 | $(PROVIDER_DIR) | ||
133 | 132 | ||
134 | endif | 133 | endif |
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 | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | EXTRA_DIST = \ | ||
5 | test_credential_defaults.conf \ | ||
6 | test_credential_lookup.conf | ||
7 | |||
8 | |||
9 | if USE_COVERAGE | ||
10 | AM_CFLAGS = --coverage -O0 | ||
11 | endif | ||
12 | |||
13 | pkgcfgdir = $(pkgdatadir)/config.d/ | ||
14 | |||
15 | libexecdir= $(pkglibdir)/libexec/ | ||
16 | |||
17 | plugindir = $(libdir)/gnunet | ||
18 | |||
19 | pkgcfg_DATA = \ | ||
20 | credential.conf | ||
21 | |||
22 | |||
23 | # /usr/lib - compiles a layer which can be used to be communicagte with the service | ||
24 | lib_LTLIBRARIES = \ | ||
25 | libgnunetcredential.la | ||
26 | |||
27 | # /usr/lib/gnunet/libexec - Business logic . Separate process | ||
28 | libexec_PROGRAMS = \ | ||
29 | gnunet-service-credential | ||
30 | |||
31 | bin_PROGRAMS = \ | ||
32 | gnunet-credential | ||
33 | |||
34 | plugin_LTLIBRARIES = \ | ||
35 | libgnunet_plugin_gnsrecord_credential.la | ||
36 | |||
37 | |||
38 | if HAVE_MHD | ||
39 | if HAVE_JSON | ||
40 | plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la | ||
41 | endif | ||
42 | endif | ||
43 | |||
44 | |||
45 | gnunet_credential_SOURCES = \ | ||
46 | gnunet-credential.c | ||
47 | gnunet_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 | |||
55 | libgnunet_plugin_gnsrecord_credential_la_SOURCES = \ | ||
56 | plugin_gnsrecord_credential.c | ||
57 | libgnunet_plugin_gnsrecord_credential_la_LIBADD = \ | ||
58 | libgnunetcredential.la \ | ||
59 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
60 | $(LTLIBINTL) | ||
61 | libgnunet_plugin_gnsrecord_credential_la_LDFLAGS = \ | ||
62 | $(GN_PLUGIN_LDFLAGS) | ||
63 | |||
64 | |||
65 | |||
66 | gnunet_service_credential_SOURCES = \ | ||
67 | gnunet-service-credential.c | ||
68 | gnunet_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 | |||
77 | libgnunetcredential_la_SOURCES = \ | ||
78 | credential_api.c \ | ||
79 | credential_serialization.c \ | ||
80 | credential_misc.c | ||
81 | libgnunetcredential_la_LIBADD = \ | ||
82 | $(top_builddir)/src/util/libgnunetutil.la $(XLIB) | ||
83 | libgnunetcredential_la_LDFLAGS = \ | ||
84 | $(GN_LIB_LDFLAGS) | ||
85 | |||
86 | |||
87 | libgnunet_plugin_rest_credential_la_SOURCES = \ | ||
88 | plugin_rest_credential.c | ||
89 | libgnunet_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 | ||
97 | libgnunet_plugin_rest_credential_la_LDFLAGS = \ | ||
98 | $(GN_PLUGIN_LDFLAGS) | ||
99 | |||
100 | |||
101 | check_SCRIPTS = \ | ||
102 | test_credential_issue.sh \ | ||
103 | test_credential_verify_simple.sh \ | ||
104 | test_credential_verify.sh \ | ||
105 | test_credential_verify_and.sh | ||
106 | |||
107 | if ENABLE_TEST_RUN | ||
108 | if HAVE_SQLITE | ||
109 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; | ||
110 | TESTS = $(check_SCRIPTS) | ||
111 | endif | ||
112 | endif | ||
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] | ||
2 | BINARY = gnunet-service-credential | ||
3 | UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-credential.sock | ||
4 | USER_SERVICE = YES | ||
5 | OPTIONS = -L DEBUG \ No newline at end of file | ||
diff --git a/src/credential/credential.h b/src/credential/credential.h new file mode 100644 index 000000000..f16249c1b --- /dev/null +++ b/src/credential/credential.h | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2012-2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file credential/credential.h | ||
22 | * @brief IPC messages between CREDENTIAL API and CREDENTIAL service | ||
23 | * @author Adnan Husain | ||
24 | */ | ||
25 | #ifndef CREDENTIAL_H | ||
26 | #define CREDENTIAL_H | ||
27 | |||
28 | #include "gnunet_credential_service.h" | ||
29 | |||
30 | GNUNET_NETWORK_STRUCT_BEGIN | ||
31 | |||
32 | /** | ||
33 | * Message from client to Credential service to collect credentials. | ||
34 | */ | ||
35 | struct 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 | */ | ||
70 | struct 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 | */ | ||
110 | struct 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 | |||
141 | struct 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 | |||
155 | struct 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 | |||
179 | struct 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 | |||
218 | GNUNET_NETWORK_STRUCT_END | ||
219 | |||
220 | #endif | ||
221 | |||
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c new file mode 100644 index 000000000..ca54137ad --- /dev/null +++ b/src/credential/credential_api.c | |||
@@ -0,0 +1,513 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009-2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file credential/credential_api.c | ||
22 | * @brief library to access the CREDENTIAL service | ||
23 | * @author Adnan Husain | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_constants.h" | ||
28 | #include "gnunet_arm_service.h" | ||
29 | #include "gnunet_hello_lib.h" | ||
30 | #include "gnunet_protocols.h" | ||
31 | #include "gnunet_signatures.h" | ||
32 | #include "credential.h" | ||
33 | #include "credential_serialization.h" | ||
34 | #include "gnunet_credential_service.h" | ||
35 | #include "gnunet_identity_service.h" | ||
36 | |||
37 | |||
38 | #define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__) | ||
39 | |||
40 | /** | ||
41 | * Handle to a verify request | ||
42 | */ | ||
43 | struct 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 | */ | ||
87 | struct 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 | */ | ||
133 | static void | ||
134 | reconnect (struct GNUNET_CREDENTIAL_Handle *handle); | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Reconnect to CREDENTIAL | ||
139 | * | ||
140 | * @param cls the handle | ||
141 | */ | ||
142 | static void | ||
143 | reconnect_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 | */ | ||
157 | static void | ||
158 | force_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 | */ | ||
179 | static void | ||
180 | mq_error_handler (void *cls, | ||
181 | enum GNUNET_MQ_Error error) | ||
182 | { | ||
183 | struct GNUNET_CREDENTIAL_Handle *handle = cls; | ||
184 | |||
185 | force_reconnect (handle); | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Check validity of message received from the CREDENTIAL service | ||
190 | * | ||
191 | * @param cls the `struct GNUNET_CREDENTIAL_Handle *` | ||
192 | * @param loookup_msg the incoming message | ||
193 | */ | ||
194 | static int | ||
195 | check_result (void *cls, | ||
196 | const struct DelegationChainResultMessage *vr_msg) | ||
197 | { | ||
198 | //TODO | ||
199 | return GNUNET_OK; | ||
200 | } | ||
201 | |||
202 | |||
203 | /** | ||
204 | * Handler for messages received from the CREDENTIAL service | ||
205 | * | ||
206 | * @param cls the `struct GNUNET_CREDENTIAL_Handle *` | ||
207 | * @param loookup_msg the incoming message | ||
208 | */ | ||
209 | static void | ||
210 | handle_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 | */ | ||
267 | static void | ||
268 | reconnect (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 | */ | ||
305 | struct GNUNET_CREDENTIAL_Handle * | ||
306 | GNUNET_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 | */ | ||
327 | void | ||
328 | GNUNET_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 | */ | ||
350 | void | ||
351 | GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *vr) | ||
352 | { | ||
353 | struct GNUNET_CREDENTIAL_Handle *handle = vr->credential_handle; | ||
354 | |||
355 | GNUNET_CONTAINER_DLL_remove (handle->request_head, | ||
356 | handle->request_tail, | ||
357 | vr); | ||
358 | GNUNET_MQ_discard (vr->env); | ||
359 | GNUNET_free (vr); | ||
360 | } | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Performs attribute collection. | ||
365 | * Collects all credentials of subject to fulfill the | ||
366 | * attribute, if possible | ||
367 | * | ||
368 | * @param handle handle to the Credential service | ||
369 | * @param issuer_key the issuer public key | ||
370 | * @param issuer_attribute the issuer attribute | ||
371 | * @param subject_key the subject public key | ||
372 | * @param credential_count number of credentials provided | ||
373 | * @param credentials subject credentials | ||
374 | * @param proc function to call on result | ||
375 | * @param proc_cls closure for processor | ||
376 | * @return handle to the queued request | ||
377 | */ | ||
378 | struct GNUNET_CREDENTIAL_Request* | ||
379 | GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle, | ||
380 | const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, | ||
381 | const char *issuer_attribute, | ||
382 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key, | ||
383 | GNUNET_CREDENTIAL_CredentialResultProcessor proc, | ||
384 | void *proc_cls) | ||
385 | { | ||
386 | /* IPC to shorten credential names, return shorten_handle */ | ||
387 | struct CollectMessage *c_msg; | ||
388 | struct GNUNET_CREDENTIAL_Request *vr; | ||
389 | size_t nlen; | ||
390 | |||
391 | if (NULL == issuer_attribute) | ||
392 | { | ||
393 | GNUNET_break (0); | ||
394 | return NULL; | ||
395 | } | ||
396 | |||
397 | //DEBUG LOG | ||
398 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
399 | "Trying to collect `%s' in CREDENTIAL\n", | ||
400 | issuer_attribute); | ||
401 | nlen = strlen (issuer_attribute) + 1; | ||
402 | if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr)) | ||
403 | { | ||
404 | GNUNET_break (0); | ||
405 | return NULL; | ||
406 | } | ||
407 | vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request); | ||
408 | vr->credential_handle = handle; | ||
409 | vr->verify_proc = proc; | ||
410 | vr->proc_cls = proc_cls; | ||
411 | vr->r_id = handle->r_id_gen++; | ||
412 | vr->env = GNUNET_MQ_msg_extra (c_msg, | ||
413 | nlen, | ||
414 | GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT); | ||
415 | c_msg->id = htonl (vr->r_id); | ||
416 | c_msg->subject_key = *subject_key; | ||
417 | c_msg->issuer_key = *issuer_key; | ||
418 | c_msg->issuer_attribute_len = htons(strlen(issuer_attribute)); | ||
419 | GNUNET_memcpy (&c_msg[1], | ||
420 | issuer_attribute, | ||
421 | strlen (issuer_attribute)); | ||
422 | GNUNET_CONTAINER_DLL_insert (handle->request_head, | ||
423 | handle->request_tail, | ||
424 | vr); | ||
425 | if (NULL != handle->mq) | ||
426 | GNUNET_MQ_send_copy (handle->mq, | ||
427 | vr->env); | ||
428 | return vr; | ||
429 | } | ||
430 | /** | ||
431 | * Performs attribute verification. | ||
432 | * Checks if there is a delegation chain from | ||
433 | * attribute ``issuer_attribute'' issued by the issuer | ||
434 | * with public key ``issuer_key'' maps to the attribute | ||
435 | * ``subject_attribute'' claimed by the subject with key | ||
436 | * ``subject_key'' | ||
437 | * | ||
438 | * @param handle handle to the Credential service | ||
439 | * @param issuer_key the issuer public key | ||
440 | * @param issuer_attribute the issuer attribute | ||
441 | * @param subject_key the subject public key | ||
442 | * @param credential_count number of credentials provided | ||
443 | * @param credentials subject credentials | ||
444 | * @param proc function to call on result | ||
445 | * @param proc_cls closure for processor | ||
446 | * @return handle to the queued request | ||
447 | */ | ||
448 | struct GNUNET_CREDENTIAL_Request* | ||
449 | GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle, | ||
450 | const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, | ||
451 | const char *issuer_attribute, | ||
452 | const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key, | ||
453 | uint32_t credential_count, | ||
454 | const struct GNUNET_CREDENTIAL_Credential *credentials, | ||
455 | GNUNET_CREDENTIAL_CredentialResultProcessor proc, | ||
456 | void *proc_cls) | ||
457 | { | ||
458 | /* IPC to shorten credential names, return shorten_handle */ | ||
459 | struct VerifyMessage *v_msg; | ||
460 | struct GNUNET_CREDENTIAL_Request *vr; | ||
461 | size_t nlen; | ||
462 | size_t clen; | ||
463 | |||
464 | if (NULL == issuer_attribute || NULL == credentials) | ||
465 | { | ||
466 | GNUNET_break (0); | ||
467 | return NULL; | ||
468 | } | ||
469 | |||
470 | clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count, | ||
471 | credentials); | ||
472 | |||
473 | //DEBUG LOG | ||
474 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
475 | "Trying to verify `%s' in CREDENTIAL\n", | ||
476 | issuer_attribute); | ||
477 | nlen = strlen (issuer_attribute) + 1 + clen; | ||
478 | if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr)) | ||
479 | { | ||
480 | GNUNET_break (0); | ||
481 | return NULL; | ||
482 | } | ||
483 | vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request); | ||
484 | vr->credential_handle = handle; | ||
485 | vr->verify_proc = proc; | ||
486 | vr->proc_cls = proc_cls; | ||
487 | vr->r_id = handle->r_id_gen++; | ||
488 | vr->env = GNUNET_MQ_msg_extra (v_msg, | ||
489 | nlen, | ||
490 | GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY); | ||
491 | v_msg->id = htonl (vr->r_id); | ||
492 | v_msg->subject_key = *subject_key; | ||
493 | v_msg->c_count = htonl(credential_count); | ||
494 | v_msg->issuer_key = *issuer_key; | ||
495 | v_msg->issuer_attribute_len = htons(strlen(issuer_attribute)); | ||
496 | GNUNET_memcpy (&v_msg[1], | ||
497 | issuer_attribute, | ||
498 | strlen (issuer_attribute)); | ||
499 | GNUNET_CREDENTIAL_credentials_serialize (credential_count, | ||
500 | credentials, | ||
501 | clen, | ||
502 | ((char*)&v_msg[1]) | ||
503 | + strlen (issuer_attribute) + 1); | ||
504 | GNUNET_CONTAINER_DLL_insert (handle->request_head, | ||
505 | handle->request_tail, | ||
506 | vr); | ||
507 | if (NULL != handle->mq) | ||
508 | GNUNET_MQ_send_copy (handle->mq, | ||
509 | vr->env); | ||
510 | return vr; | ||
511 | } | ||
512 | |||
513 | /* end of credential_api.c */ | ||
diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c new file mode 100644 index 000000000..7849e81e6 --- /dev/null +++ b/src/credential/credential_misc.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009-2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file credential/credential_mic.c | ||
24 | * @brief Misc API for credentials | ||
25 | * | ||
26 | * @author Martin Schanzenbach | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_constants.h" | ||
31 | #include "gnunet_credential_service.h" | ||
32 | #include "gnunet_signatures.h" | ||
33 | #include "credential.h" | ||
34 | #include <inttypes.h> | ||
35 | |||
36 | char* | ||
37 | GNUNET_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 | |||
63 | struct GNUNET_CREDENTIAL_Credential* | ||
64 | GNUNET_CREDENTIAL_credential_from_string (const char* s) | ||
65 | { | ||
66 | struct GNUNET_CREDENTIAL_Credential *cred; | ||
67 | size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8; | ||
68 | if (enclen % 5 > 0) | ||
69 | enclen += 5 - enclen % 5; | ||
70 | enclen /= 5; /* 260/5 = 52 */ | ||
71 | char subject_pkey[enclen + 1]; | ||
72 | char issuer_pkey[enclen + 1]; | ||
73 | char name[253 + 1]; | ||
74 | char signature[256]; //TODO max payload size | ||
75 | |||
76 | struct GNUNET_CRYPTO_EcdsaSignature *sig; | ||
77 | struct GNUNET_TIME_Absolute etime_abs; | ||
78 | |||
79 | if (5 != SSCANF (s, | ||
80 | "%52s.%253s -> %52s | %s | %"SCNu64, | ||
81 | issuer_pkey, | ||
82 | name, | ||
83 | subject_pkey, | ||
84 | signature, | ||
85 | &etime_abs.abs_value_us)) | ||
86 | { | ||
87 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
88 | _("Unable to parse CRED record string `%s'\n"), | ||
89 | s); | ||
90 | return NULL; | ||
91 | } | ||
92 | cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1); | ||
93 | GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey, | ||
94 | strlen (subject_pkey), | ||
95 | &cred->subject_key); | ||
96 | GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey, | ||
97 | strlen (issuer_pkey), | ||
98 | &cred->issuer_key); | ||
99 | GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature, | ||
100 | strlen (signature), | ||
101 | (char**)&sig)); | ||
102 | cred->signature = *sig; | ||
103 | cred->expiration = etime_abs; | ||
104 | GNUNET_free (sig); | ||
105 | GNUNET_memcpy (&cred[1], | ||
106 | name, | ||
107 | strlen (name)+1); | ||
108 | cred->issuer_attribute_len = strlen ((char*)&cred[1]); | ||
109 | cred->issuer_attribute = (char*)&cred[1]; | ||
110 | return cred; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Issue an attribute to a subject | ||
115 | * | ||
116 | * @param handle handle to the Credential service | ||
117 | * @param issuer the ego that should be used to issue the attribute | ||
118 | * @param subject the subject of the attribute | ||
119 | * @param attribute the name of the attribute | ||
120 | * @return handle to the queued request | ||
121 | */ | ||
122 | struct GNUNET_CREDENTIAL_Credential * | ||
123 | GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | ||
124 | struct GNUNET_CRYPTO_EcdsaPublicKey *subject, | ||
125 | const char *attribute, | ||
126 | struct GNUNET_TIME_Absolute *expiration) | ||
127 | { | ||
128 | struct CredentialEntry *crd; | ||
129 | struct GNUNET_CREDENTIAL_Credential *cred; | ||
130 | size_t size; | ||
131 | |||
132 | size = sizeof (struct CredentialEntry) + strlen (attribute) + 1; | ||
133 | crd = GNUNET_malloc (size); | ||
134 | cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1); | ||
135 | crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); | ||
136 | |||
137 | crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL); | ||
138 | GNUNET_CRYPTO_ecdsa_key_get_public (issuer, | ||
139 | &crd->issuer_key); | ||
140 | crd->subject_key = *subject; | ||
141 | crd->expiration = GNUNET_htonll (expiration->abs_value_us); | ||
142 | crd->issuer_attribute_len = htonl (strlen (attribute)+1); | ||
143 | GNUNET_memcpy ((char*)&crd[1], | ||
144 | attribute, | ||
145 | strlen (attribute)+1); | ||
146 | if (GNUNET_OK != | ||
147 | GNUNET_CRYPTO_ecdsa_sign (issuer, | ||
148 | &crd->purpose, | ||
149 | &crd->signature)) | ||
150 | { | ||
151 | GNUNET_break (0); | ||
152 | GNUNET_free (crd); | ||
153 | return NULL; | ||
154 | } | ||
155 | cred->signature = crd->signature; | ||
156 | cred->expiration = *expiration; | ||
157 | GNUNET_CRYPTO_ecdsa_key_get_public (issuer, | ||
158 | &cred->issuer_key); | ||
159 | |||
160 | cred->subject_key = *subject; | ||
161 | GNUNET_memcpy (&cred[1], | ||
162 | attribute, | ||
163 | strlen (attribute)+1); | ||
164 | cred->issuer_attribute = (char*)&cred[1]; | ||
165 | GNUNET_free (crd); | ||
166 | return cred; | ||
167 | } | ||
168 | |||
169 | |||
diff --git a/src/credential/credential_misc.h b/src/credential/credential_misc.h new file mode 100644 index 000000000..c3aa8c214 --- /dev/null +++ b/src/credential/credential_misc.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2012-2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file credential/credential_misc.h | ||
22 | * @brief Credential helper functions | ||
23 | */ | ||
24 | #ifndef CREDENTIAL_MISC_H | ||
25 | #define CREDENTIAL_MISC_H | ||
26 | |||
27 | |||
28 | |||
29 | char* | ||
30 | GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred); | ||
31 | |||
32 | struct GNUNET_CREDENTIAL_Credential* | ||
33 | GNUNET_CREDENTIAL_credential_from_string (const char* str); | ||
34 | |||
35 | #endif | ||
diff --git a/src/credential/credential_serialization.c b/src/credential/credential_serialization.c new file mode 100644 index 000000000..1fc72c203 --- /dev/null +++ b/src/credential/credential_serialization.c | |||
@@ -0,0 +1,463 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009-2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file credential/credential_serialization.c | ||
24 | * @brief API to serialize and deserialize delegation chains | ||
25 | * and credentials | ||
26 | * @author Martin Schanzenbach | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_constants.h" | ||
31 | #include "gnunet_credential_service.h" | ||
32 | #include "gnunet_signatures.h" | ||
33 | #include "credential.h" | ||
34 | |||
35 | /** | ||
36 | * Calculate how many bytes we will need to serialize | ||
37 | * the given delegation chain and credential | ||
38 | * | ||
39 | * @param d_count number of delegation chain entries | ||
40 | * @param dd array of #GNUNET_CREDENTIAL_Delegation | ||
41 | * @param cd a #GNUNET_CREDENTIAL_Credential | ||
42 | * @return the required size to serialize | ||
43 | */ | ||
44 | size_t | ||
45 | GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count, | ||
46 | const struct GNUNET_CREDENTIAL_DelegationSet *dsr) | ||
47 | { | ||
48 | unsigned int i; | ||
49 | size_t ret; | ||
50 | |||
51 | ret = sizeof (struct DelegationRecordData) * (ds_count); | ||
52 | |||
53 | for (i=0; i<ds_count;i++) | ||
54 | { | ||
55 | GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret); | ||
56 | ret += dsr[i].subject_attribute_len; | ||
57 | } | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * Serizalize the given delegation chain entries and credential | ||
63 | * | ||
64 | * @param d_count number of delegation chain entries | ||
65 | * @param dd array of #GNUNET_CREDENTIAL_Delegation | ||
66 | * @param cd a #GNUNET_CREDENTIAL_Credential | ||
67 | * @param dest_size size of the destination | ||
68 | * @param dest where to store the result | ||
69 | * @return the size of the data, -1 on failure | ||
70 | */ | ||
71 | ssize_t | ||
72 | GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count, | ||
73 | const struct GNUNET_CREDENTIAL_DelegationSet *dsr, | ||
74 | size_t dest_size, | ||
75 | char *dest) | ||
76 | { | ||
77 | struct DelegationRecordData rec; | ||
78 | unsigned int i; | ||
79 | size_t off; | ||
80 | |||
81 | off = 0; | ||
82 | for (i=0;i<d_count;i++) | ||
83 | { | ||
84 | rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len); | ||
85 | rec.subject_key = dsr[i].subject_key; | ||
86 | if (off + sizeof (rec) > dest_size) | ||
87 | return -1; | ||
88 | GNUNET_memcpy (&dest[off], | ||
89 | &rec, | ||
90 | sizeof (rec)); | ||
91 | off += sizeof (rec); | ||
92 | if (0 == dsr[i].subject_attribute_len) | ||
93 | continue; | ||
94 | if (off + dsr[i].subject_attribute_len > dest_size) | ||
95 | return -1; | ||
96 | GNUNET_memcpy (&dest[off], | ||
97 | dsr[i].subject_attribute, | ||
98 | dsr[i].subject_attribute_len); | ||
99 | off += dsr[i].subject_attribute_len; | ||
100 | } | ||
101 | return off; | ||
102 | } | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Deserialize the given destination | ||
107 | * | ||
108 | * @param len size of the serialized delegation chain and cred | ||
109 | * @param src the serialized data | ||
110 | * @param d_count the number of delegation chain entries | ||
111 | * @param dd where to put the delegation chain entries | ||
112 | * @param cd where to put the credential data | ||
113 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
114 | */ | ||
115 | int | ||
116 | GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len, | ||
117 | const char *src, | ||
118 | unsigned int d_count, | ||
119 | struct GNUNET_CREDENTIAL_DelegationSet *dsr) | ||
120 | { | ||
121 | struct DelegationRecordData rec; | ||
122 | unsigned int i; | ||
123 | size_t off; | ||
124 | |||
125 | off = 0; | ||
126 | for (i=0;i<d_count;i++) | ||
127 | { | ||
128 | if (off + sizeof (rec) > len) | ||
129 | return GNUNET_SYSERR; | ||
130 | GNUNET_memcpy (&rec, &src[off], sizeof (rec)); | ||
131 | dsr[i].subject_key = rec.subject_key; | ||
132 | off += sizeof (rec); | ||
133 | dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len); | ||
134 | if (off + dsr[i].subject_attribute_len > len) | ||
135 | return GNUNET_SYSERR; | ||
136 | dsr[i].subject_attribute = (char*)&src[off]; | ||
137 | off += dsr[i].subject_attribute_len; | ||
138 | } | ||
139 | return GNUNET_OK; | ||
140 | } | ||
141 | |||
142 | |||
143 | /** | ||
144 | * Calculate how many bytes we will need to serialize | ||
145 | * the credentials | ||
146 | * | ||
147 | * @param c_count number of credential entries | ||
148 | * @param cd a #GNUNET_CREDENTIAL_Credential | ||
149 | * @return the required size to serialize | ||
150 | */ | ||
151 | size_t | ||
152 | GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count, | ||
153 | const struct GNUNET_CREDENTIAL_Credential *cd) | ||
154 | { | ||
155 | unsigned int i; | ||
156 | size_t ret; | ||
157 | |||
158 | ret = sizeof (struct CredentialEntry) * (c_count); | ||
159 | |||
160 | for (i=0; i<c_count;i++) | ||
161 | { | ||
162 | GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret); | ||
163 | ret += cd[i].issuer_attribute_len; | ||
164 | } | ||
165 | return ret; | ||
166 | } | ||
167 | /** | ||
168 | * Serizalize the given credentials | ||
169 | * | ||
170 | * @param c_count number of credential entries | ||
171 | * @param cd a #GNUNET_CREDENTIAL_Credential | ||
172 | * @param dest_size size of the destination | ||
173 | * @param dest where to store the result | ||
174 | * @return the size of the data, -1 on failure | ||
175 | */ | ||
176 | ssize_t | ||
177 | GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count, | ||
178 | const struct GNUNET_CREDENTIAL_Credential *cd, | ||
179 | size_t dest_size, | ||
180 | char *dest) | ||
181 | { | ||
182 | struct CredentialEntry c_rec; | ||
183 | unsigned int i; | ||
184 | size_t off; | ||
185 | |||
186 | off = 0; | ||
187 | for (i=0;i<c_count;i++) | ||
188 | { | ||
189 | c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len); | ||
190 | c_rec.issuer_key = cd[i].issuer_key; | ||
191 | c_rec.subject_key = cd[i].subject_key; | ||
192 | c_rec.signature = cd[i].signature; | ||
193 | c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL); | ||
194 | c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); | ||
195 | c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us); | ||
196 | if (off + sizeof (c_rec) > dest_size) | ||
197 | return -1; | ||
198 | GNUNET_memcpy (&dest[off], | ||
199 | &c_rec, | ||
200 | sizeof (c_rec)); | ||
201 | off += sizeof (c_rec); | ||
202 | if (off + cd[i].issuer_attribute_len > dest_size) | ||
203 | return -1; | ||
204 | GNUNET_memcpy (&dest[off], | ||
205 | cd[i].issuer_attribute, | ||
206 | cd[i].issuer_attribute_len); | ||
207 | off += cd[i].issuer_attribute_len; | ||
208 | } | ||
209 | |||
210 | return off; | ||
211 | } | ||
212 | |||
213 | |||
214 | |||
215 | /** | ||
216 | * Deserialize the given destination | ||
217 | * | ||
218 | * @param len size of the serialized creds | ||
219 | * @param src the serialized data | ||
220 | * @param c_count the number of credential entries | ||
221 | * @param cd where to put the credential data | ||
222 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
223 | */ | ||
224 | int | ||
225 | GNUNET_CREDENTIAL_credentials_deserialize (size_t len, | ||
226 | const char *src, | ||
227 | unsigned int c_count, | ||
228 | struct GNUNET_CREDENTIAL_Credential *cd) | ||
229 | { | ||
230 | struct CredentialEntry c_rec; | ||
231 | unsigned int i; | ||
232 | size_t off; | ||
233 | |||
234 | off = 0; | ||
235 | for (i=0;i<c_count;i++) | ||
236 | { | ||
237 | if (off + sizeof (c_rec) > len) | ||
238 | return GNUNET_SYSERR; | ||
239 | GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec)); | ||
240 | cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len); | ||
241 | cd[i].issuer_key = c_rec.issuer_key; | ||
242 | cd[i].subject_key = c_rec.subject_key; | ||
243 | cd[i].signature = c_rec.signature; | ||
244 | cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration); | ||
245 | off += sizeof (c_rec); | ||
246 | if (off + cd[i].issuer_attribute_len > len) | ||
247 | return GNUNET_SYSERR; | ||
248 | cd[i].issuer_attribute = &src[off]; | ||
249 | off += cd[i].issuer_attribute_len; | ||
250 | } | ||
251 | return GNUNET_OK; | ||
252 | } | ||
253 | |||
254 | |||
255 | |||
256 | /** | ||
257 | * Calculate how many bytes we will need to serialize | ||
258 | * the given delegation chain and credential | ||
259 | * | ||
260 | * @param d_count number of delegation chain entries | ||
261 | * @param dd array of #GNUNET_CREDENTIAL_Delegation | ||
262 | * @param c_count number of credential entries | ||
263 | * @param cd a #GNUNET_CREDENTIAL_Credential | ||
264 | * @return the required size to serialize | ||
265 | */ | ||
266 | size_t | ||
267 | GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count, | ||
268 | const struct GNUNET_CREDENTIAL_Delegation *dd, | ||
269 | unsigned int c_count, | ||
270 | const struct GNUNET_CREDENTIAL_Credential *cd) | ||
271 | { | ||
272 | unsigned int i; | ||
273 | size_t ret; | ||
274 | |||
275 | ret = sizeof (struct ChainEntry) * (d_count); | ||
276 | |||
277 | for (i=0; i<d_count;i++) | ||
278 | { | ||
279 | GNUNET_assert ((ret + | ||
280 | dd[i].issuer_attribute_len + | ||
281 | dd[i].subject_attribute_len) >= ret); | ||
282 | ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len; | ||
283 | } | ||
284 | return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd); | ||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * Serizalize the given delegation chain entries and credential | ||
290 | * | ||
291 | * @param d_count number of delegation chain entries | ||
292 | * @param dd array of #GNUNET_CREDENTIAL_Delegation | ||
293 | * @param c_count number of credential entries | ||
294 | * @param cd a #GNUNET_CREDENTIAL_Credential | ||
295 | * @param dest_size size of the destination | ||
296 | * @param dest where to store the result | ||
297 | * @return the size of the data, -1 on failure | ||
298 | */ | ||
299 | ssize_t | ||
300 | GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count, | ||
301 | const struct GNUNET_CREDENTIAL_Delegation *dd, | ||
302 | unsigned int c_count, | ||
303 | const struct GNUNET_CREDENTIAL_Credential *cd, | ||
304 | size_t dest_size, | ||
305 | char *dest) | ||
306 | { | ||
307 | struct ChainEntry rec; | ||
308 | unsigned int i; | ||
309 | size_t off; | ||
310 | |||
311 | off = 0; | ||
312 | for (i=0;i<d_count;i++) | ||
313 | { | ||
314 | rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len); | ||
315 | rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len); | ||
316 | rec.issuer_key = dd[i].issuer_key; | ||
317 | rec.subject_key = dd[i].subject_key; | ||
318 | if (off + sizeof (rec) > dest_size) | ||
319 | return -1; | ||
320 | GNUNET_memcpy (&dest[off], | ||
321 | &rec, | ||
322 | sizeof (rec)); | ||
323 | off += sizeof (rec); | ||
324 | if (off + dd[i].issuer_attribute_len > dest_size) | ||
325 | return -1; | ||
326 | GNUNET_memcpy (&dest[off], | ||
327 | dd[i].issuer_attribute, | ||
328 | dd[i].issuer_attribute_len); | ||
329 | off += dd[i].issuer_attribute_len; | ||
330 | if (0 == dd[i].subject_attribute_len) | ||
331 | continue; | ||
332 | if (off + dd[i].subject_attribute_len > dest_size) | ||
333 | return -1; | ||
334 | GNUNET_memcpy (&dest[off], | ||
335 | dd[i].subject_attribute, | ||
336 | dd[i].subject_attribute_len); | ||
337 | off += dd[i].subject_attribute_len; | ||
338 | } | ||
339 | return off+GNUNET_CREDENTIAL_credentials_serialize (c_count, | ||
340 | cd, | ||
341 | dest_size-off, | ||
342 | &dest[off]); | ||
343 | } | ||
344 | |||
345 | |||
346 | /** | ||
347 | * Deserialize the given destination | ||
348 | * | ||
349 | * @param len size of the serialized delegation chain and cred | ||
350 | * @param src the serialized data | ||
351 | * @param d_count the number of delegation chain entries | ||
352 | * @param dd where to put the delegation chain entries | ||
353 | * @param c_count the number of credential entries | ||
354 | * @param cd where to put the credential data | ||
355 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
356 | */ | ||
357 | int | ||
358 | GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len, | ||
359 | const char *src, | ||
360 | unsigned int d_count, | ||
361 | struct GNUNET_CREDENTIAL_Delegation *dd, | ||
362 | unsigned int c_count, | ||
363 | struct GNUNET_CREDENTIAL_Credential *cd) | ||
364 | { | ||
365 | struct ChainEntry rec; | ||
366 | unsigned int i; | ||
367 | size_t off; | ||
368 | |||
369 | off = 0; | ||
370 | for (i=0;i<d_count;i++) | ||
371 | { | ||
372 | if (off + sizeof (rec) > len) | ||
373 | return GNUNET_SYSERR; | ||
374 | GNUNET_memcpy (&rec, &src[off], sizeof (rec)); | ||
375 | dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len); | ||
376 | dd[i].issuer_key = rec.issuer_key; | ||
377 | dd[i].subject_key = rec.subject_key; | ||
378 | off += sizeof (rec); | ||
379 | if (off + dd[i].issuer_attribute_len > len) | ||
380 | return GNUNET_SYSERR; | ||
381 | dd[i].issuer_attribute = &src[off]; | ||
382 | off += dd[i].issuer_attribute_len; | ||
383 | dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len); | ||
384 | if (off + dd[i].subject_attribute_len > len) | ||
385 | return GNUNET_SYSERR; | ||
386 | dd[i].subject_attribute = &src[off]; | ||
387 | off += dd[i].subject_attribute_len; | ||
388 | } | ||
389 | return GNUNET_CREDENTIAL_credentials_deserialize (len-off, | ||
390 | &src[off], | ||
391 | c_count, | ||
392 | cd); | ||
393 | } | ||
394 | int | ||
395 | GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred, | ||
396 | char **data) | ||
397 | { | ||
398 | size_t size; | ||
399 | struct CredentialEntry *cdata; | ||
400 | |||
401 | size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1; | ||
402 | *data = GNUNET_malloc (size); | ||
403 | cdata = (struct CredentialEntry*)*data; | ||
404 | cdata->subject_key = cred->subject_key; | ||
405 | cdata->issuer_key = cred->issuer_key; | ||
406 | cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us); | ||
407 | cdata->signature = cred->signature; | ||
408 | cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1); | ||
409 | cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL); | ||
410 | cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); | ||
411 | GNUNET_memcpy (&cdata[1], | ||
412 | cred->issuer_attribute, | ||
413 | strlen (cred->issuer_attribute)); | ||
414 | |||
415 | if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, | ||
416 | &cdata->purpose, | ||
417 | &cdata->signature, | ||
418 | &cdata->issuer_key)) | ||
419 | { | ||
420 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
421 | "Invalid credential\n"); | ||
422 | //return NULL; | ||
423 | } | ||
424 | return size; | ||
425 | } | ||
426 | |||
427 | struct GNUNET_CREDENTIAL_Credential* | ||
428 | GNUNET_CREDENTIAL_credential_deserialize (const char* data, | ||
429 | size_t data_size) | ||
430 | { | ||
431 | struct GNUNET_CREDENTIAL_Credential *cred; | ||
432 | struct CredentialEntry *cdata; | ||
433 | char *issuer_attribute; | ||
434 | |||
435 | if (data_size < sizeof (struct CredentialEntry)) | ||
436 | return NULL; | ||
437 | cdata = (struct CredentialEntry*)data; | ||
438 | if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, | ||
439 | &cdata->purpose, | ||
440 | &cdata->signature, | ||
441 | &cdata->issuer_key)) | ||
442 | { | ||
443 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
444 | "Invalid credential\n"); | ||
445 | //return NULL; | ||
446 | } | ||
447 | issuer_attribute = (char*)&cdata[1]; | ||
448 | |||
449 | cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len)); | ||
450 | |||
451 | cred->issuer_key = cdata->issuer_key; | ||
452 | cred->subject_key = cdata->subject_key; | ||
453 | GNUNET_memcpy (&cred[1], | ||
454 | issuer_attribute, | ||
455 | ntohl (cdata->issuer_attribute_len)); | ||
456 | cred->signature = cdata->signature; | ||
457 | cred->issuer_attribute = (char*)&cred[1]; | ||
458 | cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration); | ||
459 | return cred; | ||
460 | } | ||
461 | |||
462 | |||
463 | /* end of credential_serialization.c */ | ||
diff --git a/src/credential/credential_serialization.h b/src/credential/credential_serialization.h new file mode 100644 index 000000000..b870d47dc --- /dev/null +++ b/src/credential/credential_serialization.h | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009-2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file credential/credential_serialization.h | ||
24 | * @brief API to serialize and deserialize delegation chains | ||
25 | * and credentials | ||
26 | * @author Martin Schanzenbach | ||
27 | */ | ||
28 | #ifndef CREDENTIAL_SERIALIZATION_H | ||
29 | #define CREDENTIAL_SERIALIZATION_H | ||
30 | |||
31 | #include "platform.h" | ||
32 | #include "gnunet_util_lib.h" | ||
33 | #include "gnunet_constants.h" | ||
34 | #include "gnunet_credential_service.h" | ||
35 | |||
36 | /** | ||
37 | * Calculate how many bytes we will need to serialize | ||
38 | * the given delegation record | ||
39 | * | ||
40 | * @param ds_count number of delegation chain entries | ||
41 | * @param dsr array of #GNUNET_CREDENTIAL_Delegation | ||
42 | * @return the required size to serialize | ||
43 | */ | ||
44 | size_t | ||
45 | GNUNET_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 | */ | ||
57 | ssize_t | ||
58 | GNUNET_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 | */ | ||
73 | int | ||
74 | GNUNET_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 | |||
137 | ssize_t | ||
138 | GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count, | ||
139 | const struct GNUNET_CREDENTIAL_Credential *cd, | ||
140 | size_t dest_size, | ||
141 | char *dest); | ||
142 | |||
143 | |||
144 | int | ||
145 | GNUNET_CREDENTIAL_credentials_deserialize (size_t len, | ||
146 | const char *src, | ||
147 | unsigned int c_count, | ||
148 | struct GNUNET_CREDENTIAL_Credential *cd); | ||
149 | |||
150 | |||
151 | int | ||
152 | GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred, | ||
153 | char **data); | ||
154 | |||
155 | struct GNUNET_CREDENTIAL_Credential* | ||
156 | GNUNET_CREDENTIAL_credential_deserialize (const char* data, | ||
157 | size_t data_size); | ||
158 | #endif | ||
159 | /* end of credential_serialization.h */ | ||
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c new file mode 100644 index 000000000..4a6dc5ccd --- /dev/null +++ b/src/credential/gnunet-credential.c | |||
@@ -0,0 +1,602 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file gnunet-credential.c | ||
22 | * @brief command line tool to access command line Credential service | ||
23 | * @author Adnan Husain | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include <gnunet_util_lib.h> | ||
27 | #include <gnunet_credential_service.h> | ||
28 | #include <gnunet_gnsrecord_lib.h> | ||
29 | #include "credential_misc.h" | ||
30 | #include "credential_serialization.h" | ||
31 | |||
32 | /** | ||
33 | * Configuration we are using. | ||
34 | */ | ||
35 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
36 | |||
37 | /** | ||
38 | * EgoLookup | ||
39 | */ | ||
40 | static struct GNUNET_IDENTITY_EgoLookup *el; | ||
41 | |||
42 | /** | ||
43 | * Handle to Credential service. | ||
44 | */ | ||
45 | static struct GNUNET_CREDENTIAL_Handle *credential; | ||
46 | |||
47 | /** | ||
48 | * Desired timeout for the lookup (default is no timeout). | ||
49 | */ | ||
50 | static struct GNUNET_TIME_Relative timeout; | ||
51 | |||
52 | /** | ||
53 | * Handle to verify request | ||
54 | */ | ||
55 | static struct GNUNET_CREDENTIAL_Request *verify_request; | ||
56 | |||
57 | /** | ||
58 | * Handle to collect request | ||
59 | */ | ||
60 | static struct GNUNET_CREDENTIAL_Request *collect_request; | ||
61 | |||
62 | /** | ||
63 | * Task scheduled to handle timeout. | ||
64 | */ | ||
65 | static struct GNUNET_SCHEDULER_Task *tt; | ||
66 | |||
67 | /** | ||
68 | * Subject pubkey string | ||
69 | */ | ||
70 | static char *subject_key; | ||
71 | |||
72 | /** | ||
73 | * Subject credential string | ||
74 | */ | ||
75 | static char *subject_credential; | ||
76 | |||
77 | /** | ||
78 | * Credential TTL | ||
79 | */ | ||
80 | static char *expiration; | ||
81 | |||
82 | /** | ||
83 | * Subject key | ||
84 | */ | ||
85 | struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey; | ||
86 | |||
87 | /** | ||
88 | * Issuer key | ||
89 | */ | ||
90 | struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey; | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Issuer pubkey string | ||
95 | */ | ||
96 | static char *issuer_key; | ||
97 | |||
98 | /** | ||
99 | * ego | ||
100 | */ | ||
101 | static char *ego_name; | ||
102 | |||
103 | /** | ||
104 | * Issuer attribute | ||
105 | */ | ||
106 | static char *issuer_attr; | ||
107 | |||
108 | /** | ||
109 | * Verify mode | ||
110 | */ | ||
111 | static int verify; | ||
112 | |||
113 | /** | ||
114 | * Issue mode | ||
115 | */ | ||
116 | static int create_cred; | ||
117 | |||
118 | /** | ||
119 | * Collect mode | ||
120 | */ | ||
121 | static int collect; | ||
122 | |||
123 | /** | ||
124 | * Task run on shutdown. Cleans up everything. | ||
125 | * | ||
126 | * @param cls unused | ||
127 | */ | ||
128 | static void | ||
129 | do_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 | */ | ||
154 | static void | ||
155 | do_timeout (void *cls) | ||
156 | { | ||
157 | tt = NULL; | ||
158 | GNUNET_SCHEDULER_shutdown (); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * Function called with the result of a Credential lookup. | ||
163 | * | ||
164 | * @param cls the 'const char *' name that was resolved | ||
165 | * @param cd_count number of records returned | ||
166 | * @param cd array of @a cd_count records with the results | ||
167 | */ | ||
168 | static void | ||
169 | handle_collect_result (void *cls, | ||
170 | unsigned int d_count, | ||
171 | struct GNUNET_CREDENTIAL_Delegation *dc, | ||
172 | unsigned int c_count, | ||
173 | struct GNUNET_CREDENTIAL_Credential *cred) | ||
174 | { | ||
175 | int i; | ||
176 | char* line; | ||
177 | |||
178 | verify_request = NULL; | ||
179 | if (NULL != cred) | ||
180 | { | ||
181 | for (i=0;i<c_count;i++) | ||
182 | { | ||
183 | line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]); | ||
184 | printf ("%s\n", | ||
185 | line); | ||
186 | GNUNET_free (line); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | |||
191 | GNUNET_SCHEDULER_shutdown (); | ||
192 | } | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Function called with the result of a Credential lookup. | ||
197 | * | ||
198 | * @param cls the 'const char *' name that was resolved | ||
199 | * @param cd_count number of records returned | ||
200 | * @param cd array of @a cd_count records with the results | ||
201 | */ | ||
202 | static void | ||
203 | handle_verify_result (void *cls, | ||
204 | unsigned int d_count, | ||
205 | struct GNUNET_CREDENTIAL_Delegation *dc, | ||
206 | unsigned int c_count, | ||
207 | struct GNUNET_CREDENTIAL_Credential *cred) | ||
208 | { | ||
209 | int i; | ||
210 | char* iss_key; | ||
211 | char* sub_key; | ||
212 | |||
213 | verify_request = NULL; | ||
214 | if (NULL == cred) | ||
215 | printf ("Failed.\n"); | ||
216 | else | ||
217 | { | ||
218 | printf("Delegation Chain:\n"); | ||
219 | for (i=0;i<d_count;i++) | ||
220 | { | ||
221 | iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key); | ||
222 | sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key); | ||
223 | if (0 != dc[i].subject_attribute_len) | ||
224 | { | ||
225 | printf ("(%d) %s.%s <- %s.%s\n", i, | ||
226 | iss_key, dc[i].issuer_attribute, | ||
227 | sub_key, dc[i].subject_attribute); | ||
228 | } else { | ||
229 | printf ("(%d) %s.%s <- %s\n", i, | ||
230 | iss_key, dc[i].issuer_attribute, | ||
231 | sub_key); | ||
232 | } | ||
233 | GNUNET_free (iss_key); | ||
234 | GNUNET_free (sub_key); | ||
235 | } | ||
236 | printf("\nCredentials:\n"); | ||
237 | for (i=0;i<c_count;i++) | ||
238 | { | ||
239 | iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key); | ||
240 | sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key); | ||
241 | printf ("%s.%s <- %s\n", | ||
242 | iss_key, cred[i].issuer_attribute, | ||
243 | sub_key); | ||
244 | GNUNET_free (iss_key); | ||
245 | GNUNET_free (sub_key); | ||
246 | |||
247 | } | ||
248 | printf ("Successful.\n"); | ||
249 | } | ||
250 | |||
251 | |||
252 | GNUNET_SCHEDULER_shutdown (); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * Callback invoked from identity service with ego information. | ||
257 | * An @a ego of NULL means the ego was not found. | ||
258 | * | ||
259 | * @param cls closure with the configuration | ||
260 | * @param ego an ego known to identity service, or NULL | ||
261 | */ | ||
262 | static void | ||
263 | identity_cb (void *cls, | ||
264 | const struct GNUNET_IDENTITY_Ego *ego) | ||
265 | { | ||
266 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; | ||
267 | struct GNUNET_CREDENTIAL_Credential *crd; | ||
268 | struct GNUNET_TIME_Absolute etime_abs; | ||
269 | struct GNUNET_TIME_Relative etime_rel; | ||
270 | char *res; | ||
271 | |||
272 | el = NULL; | ||
273 | if (NULL == ego) | ||
274 | { | ||
275 | if (NULL != ego_name) | ||
276 | { | ||
277 | fprintf (stderr, | ||
278 | _("Ego `%s' not known to identity service\n"), | ||
279 | ego_name); | ||
280 | } | ||
281 | GNUNET_SCHEDULER_shutdown (); | ||
282 | return; | ||
283 | } | ||
284 | |||
285 | if (GNUNET_YES == collect) | ||
286 | { | ||
287 | |||
288 | if (GNUNET_OK != | ||
289 | GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key, | ||
290 | strlen (issuer_key), | ||
291 | &issuer_pkey)) | ||
292 | { | ||
293 | fprintf (stderr, | ||
294 | _("Issuer public key `%s' is not well-formed\n"), | ||
295 | issuer_key); | ||
296 | GNUNET_SCHEDULER_shutdown (); | ||
297 | } | ||
298 | privkey = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
299 | |||
300 | collect_request = GNUNET_CREDENTIAL_collect(credential, | ||
301 | &issuer_pkey, | ||
302 | issuer_attr, //TODO argument | ||
303 | privkey, | ||
304 | &handle_collect_result, | ||
305 | NULL); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | //Else issue | ||
310 | |||
311 | if (NULL == expiration) | ||
312 | { | ||
313 | fprintf (stderr, | ||
314 | "Please specify a TTL\n"); | ||
315 | GNUNET_SCHEDULER_shutdown (); | ||
316 | return; | ||
317 | } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration, | ||
318 | &etime_rel)) | ||
319 | { | ||
320 | etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel); | ||
321 | } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration, | ||
322 | &etime_abs)) | ||
323 | { | ||
324 | fprintf (stderr, | ||
325 | "%s is not a valid ttl!\n", | ||
326 | expiration); | ||
327 | GNUNET_SCHEDULER_shutdown (); | ||
328 | return; | ||
329 | } | ||
330 | |||
331 | |||
332 | privkey = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
333 | GNUNET_free_non_null (ego_name); | ||
334 | ego_name = NULL; | ||
335 | crd = GNUNET_CREDENTIAL_credential_issue (privkey, | ||
336 | &subject_pkey, | ||
337 | issuer_attr, | ||
338 | &etime_abs); | ||
339 | |||
340 | res = GNUNET_CREDENTIAL_credential_to_string (crd); | ||
341 | GNUNET_free (crd); | ||
342 | printf ("%s\n", res); | ||
343 | GNUNET_SCHEDULER_shutdown (); | ||
344 | } | ||
345 | |||
346 | |||
347 | |||
348 | |||
349 | /** | ||
350 | * Main function that will be run. | ||
351 | * | ||
352 | * @param cls closure | ||
353 | * @param args remaining command-line arguments | ||
354 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
355 | * @param c configuration | ||
356 | */ | ||
357 | static void | ||
358 | run (void *cls, | ||
359 | char *const *args, | ||
360 | const char *cfgfile, | ||
361 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
362 | { | ||
363 | |||
364 | cfg = c; | ||
365 | |||
366 | |||
367 | tt = GNUNET_SCHEDULER_add_delayed (timeout, | ||
368 | &do_timeout, NULL); | ||
369 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
370 | |||
371 | if (GNUNET_YES == collect) { | ||
372 | if (NULL == issuer_key) | ||
373 | { | ||
374 | fprintf (stderr, | ||
375 | _("Issuer public key not well-formed\n")); | ||
376 | GNUNET_SCHEDULER_shutdown (); | ||
377 | return; | ||
378 | |||
379 | } | ||
380 | |||
381 | credential = GNUNET_CREDENTIAL_connect (cfg); | ||
382 | |||
383 | if (NULL == credential) | ||
384 | { | ||
385 | fprintf (stderr, | ||
386 | _("Failed to connect to CREDENTIAL\n")); | ||
387 | GNUNET_SCHEDULER_shutdown (); | ||
388 | } | ||
389 | if (NULL == issuer_attr) | ||
390 | { | ||
391 | fprintf (stderr, | ||
392 | _("You must provide issuer the attribute\n")); | ||
393 | GNUNET_SCHEDULER_shutdown (); | ||
394 | } | ||
395 | |||
396 | if (NULL == ego_name) | ||
397 | { | ||
398 | fprintf (stderr, | ||
399 | _("ego required\n")); | ||
400 | GNUNET_SCHEDULER_shutdown (); | ||
401 | return; | ||
402 | |||
403 | } | ||
404 | el = GNUNET_IDENTITY_ego_lookup (cfg, | ||
405 | ego_name, | ||
406 | &identity_cb, | ||
407 | (void *) cfg); | ||
408 | return; | ||
409 | |||
410 | } | ||
411 | |||
412 | if (NULL == subject_key) | ||
413 | { | ||
414 | fprintf (stderr, | ||
415 | _("Subject public key needed\n")); | ||
416 | GNUNET_SCHEDULER_shutdown (); | ||
417 | return; | ||
418 | |||
419 | } | ||
420 | if (GNUNET_OK != | ||
421 | GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key, | ||
422 | strlen (subject_key), | ||
423 | &subject_pkey)) | ||
424 | { | ||
425 | fprintf (stderr, | ||
426 | _("Subject public key `%s' is not well-formed\n"), | ||
427 | subject_key); | ||
428 | GNUNET_SCHEDULER_shutdown (); | ||
429 | return; | ||
430 | } | ||
431 | if (GNUNET_YES == verify) { | ||
432 | if (NULL == issuer_key) | ||
433 | { | ||
434 | fprintf (stderr, | ||
435 | _("Issuer public key not well-formed\n")); | ||
436 | GNUNET_SCHEDULER_shutdown (); | ||
437 | return; | ||
438 | |||
439 | } | ||
440 | if (GNUNET_OK != | ||
441 | GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key, | ||
442 | strlen (issuer_key), | ||
443 | &issuer_pkey)) | ||
444 | { | ||
445 | fprintf (stderr, | ||
446 | _("Issuer public key `%s' is not well-formed\n"), | ||
447 | issuer_key); | ||
448 | GNUNET_SCHEDULER_shutdown (); | ||
449 | } | ||
450 | credential = GNUNET_CREDENTIAL_connect (cfg); | ||
451 | |||
452 | if (NULL == credential) | ||
453 | { | ||
454 | fprintf (stderr, | ||
455 | _("Failed to connect to CREDENTIAL\n")); | ||
456 | GNUNET_SCHEDULER_shutdown (); | ||
457 | } | ||
458 | if (NULL == issuer_attr || NULL == subject_credential) | ||
459 | { | ||
460 | fprintf (stderr, | ||
461 | _("You must provide issuer and subject attributes\n")); | ||
462 | GNUNET_SCHEDULER_shutdown (); | ||
463 | } | ||
464 | |||
465 | //Subject credentials are comma separated | ||
466 | char *tmp = GNUNET_strdup (subject_credential); | ||
467 | char *tok = strtok (tmp, ","); | ||
468 | if (NULL == tok) | ||
469 | { | ||
470 | fprintf (stderr, | ||
471 | "Invalid subject credentials\n"); | ||
472 | GNUNET_free (tmp); | ||
473 | GNUNET_SCHEDULER_shutdown (); | ||
474 | } | ||
475 | int count = 1; | ||
476 | int i; | ||
477 | while (NULL != (tok = strtok(NULL, ","))) | ||
478 | count++; | ||
479 | struct GNUNET_CREDENTIAL_Credential credentials[count]; | ||
480 | struct GNUNET_CREDENTIAL_Credential *cred; | ||
481 | GNUNET_free (tmp); | ||
482 | tmp = GNUNET_strdup (subject_credential); | ||
483 | tok = strtok (tmp, ","); | ||
484 | for (i=0;i<count;i++) | ||
485 | { | ||
486 | cred = GNUNET_CREDENTIAL_credential_from_string (tok); | ||
487 | GNUNET_memcpy (&credentials[i], | ||
488 | cred, | ||
489 | sizeof (struct GNUNET_CREDENTIAL_Credential)); | ||
490 | credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute); | ||
491 | tok = strtok(NULL, ","); | ||
492 | GNUNET_free (cred); | ||
493 | } | ||
494 | |||
495 | verify_request = GNUNET_CREDENTIAL_verify(credential, | ||
496 | &issuer_pkey, | ||
497 | issuer_attr, //TODO argument | ||
498 | &subject_pkey, | ||
499 | count, | ||
500 | credentials, | ||
501 | &handle_verify_result, | ||
502 | NULL); | ||
503 | for (i=0;i<count;i++) | ||
504 | { | ||
505 | GNUNET_free ((char*)credentials[i].issuer_attribute); | ||
506 | } | ||
507 | } else if (GNUNET_YES == create_cred) { | ||
508 | if (NULL == ego_name) | ||
509 | { | ||
510 | fprintf (stderr, | ||
511 | _("Issuer ego required\n")); | ||
512 | GNUNET_SCHEDULER_shutdown (); | ||
513 | return; | ||
514 | |||
515 | } | ||
516 | el = GNUNET_IDENTITY_ego_lookup (cfg, | ||
517 | ego_name, | ||
518 | &identity_cb, | ||
519 | (void *) cfg); | ||
520 | return; | ||
521 | } else { | ||
522 | fprintf (stderr, | ||
523 | _("Please specify name to lookup, subject key and issuer key!\n")); | ||
524 | GNUNET_SCHEDULER_shutdown (); | ||
525 | } | ||
526 | return; | ||
527 | } | ||
528 | |||
529 | |||
530 | /** | ||
531 | * The main function for gnunet-gns. | ||
532 | * | ||
533 | * @param argc number of arguments from the command line | ||
534 | * @param argv command line arguments | ||
535 | * @return 0 ok, 1 on error | ||
536 | */ | ||
537 | int | ||
538 | main (int argc, char *const *argv) | ||
539 | { | ||
540 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
541 | GNUNET_GETOPT_option_flag ('I', | ||
542 | "issue", | ||
543 | gettext_noop ("create credential"), | ||
544 | &create_cred), | ||
545 | GNUNET_GETOPT_option_flag ('V', | ||
546 | "verify", | ||
547 | gettext_noop ("verify credential against attribute"), | ||
548 | &verify), | ||
549 | GNUNET_GETOPT_option_string ('s', | ||
550 | "subject", | ||
551 | "PKEY", | ||
552 | gettext_noop ("The public key of the subject to lookup the credential for"), | ||
553 | &subject_key), | ||
554 | GNUNET_GETOPT_option_string ('b', | ||
555 | "credential", | ||
556 | "CRED", | ||
557 | gettext_noop ("The name of the credential presented by the subject"), | ||
558 | &subject_credential), | ||
559 | GNUNET_GETOPT_option_string ('i', | ||
560 | "issuer", | ||
561 | "PKEY", | ||
562 | gettext_noop ("The public key of the authority to verify the credential against"), | ||
563 | &issuer_key), | ||
564 | GNUNET_GETOPT_option_string ('e', | ||
565 | "ego", | ||
566 | "EGO", | ||
567 | gettext_noop ("The ego to use"), | ||
568 | &ego_name), | ||
569 | GNUNET_GETOPT_option_string ('a', | ||
570 | "attribute", | ||
571 | "ATTR", | ||
572 | gettext_noop ("The issuer attribute to verify against or to issue"), | ||
573 | &issuer_attr), | ||
574 | GNUNET_GETOPT_option_string ('T', | ||
575 | "ttl", | ||
576 | "EXP", | ||
577 | gettext_noop ("The time to live for the credential"), | ||
578 | &expiration), | ||
579 | GNUNET_GETOPT_option_flag ('g', | ||
580 | "collect", | ||
581 | gettext_noop ("collect credentials"), | ||
582 | &collect), | ||
583 | GNUNET_GETOPT_OPTION_END | ||
584 | }; | ||
585 | int ret; | ||
586 | |||
587 | timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
588 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
589 | return 2; | ||
590 | |||
591 | GNUNET_log_setup ("gnunet-credential", "WARNING", NULL); | ||
592 | ret = | ||
593 | (GNUNET_OK == | ||
594 | GNUNET_PROGRAM_run (argc, argv, "gnunet-credential", | ||
595 | _("GNUnet credential resolver tool"), | ||
596 | options, | ||
597 | &run, NULL)) ? 0 : 1; | ||
598 | GNUNET_free ((void*) argv); | ||
599 | return ret; | ||
600 | } | ||
601 | |||
602 | /* end of gnunet-credential.c */ | ||
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c new file mode 100644 index 000000000..be75e485e --- /dev/null +++ b/src/credential/gnunet-service-credential.c | |||
@@ -0,0 +1,1238 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011-2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file gns/gnunet-service-credential.c | ||
22 | * @brief GNU Credential Service (main service) | ||
23 | * @author Adnan Husain | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_credential_service.h" | ||
28 | #include "gnunet_statistics_service.h" | ||
29 | #include "credential.h" | ||
30 | #include "credential_serialization.h" | ||
31 | #include "gnunet_protocols.h" | ||
32 | #include "gnunet_signatures.h" | ||
33 | |||
34 | #include <gnunet_dnsparser_lib.h> | ||
35 | #include <gnunet_identity_service.h> | ||
36 | #include <gnunet_gnsrecord_lib.h> | ||
37 | #include <gnunet_namestore_service.h> | ||
38 | #include <gnunet_gns_service.h> | ||
39 | |||
40 | |||
41 | #define GNUNET_CREDENTIAL_MAX_LENGTH 255 | ||
42 | |||
43 | struct VerifyRequestHandle; | ||
44 | |||
45 | struct DelegationSetQueueEntry; | ||
46 | |||
47 | |||
48 | struct 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 | */ | ||
84 | struct 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 | */ | ||
111 | struct 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 | */ | ||
148 | struct 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 | */ | ||
226 | struct 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 | */ | ||
330 | static struct VerifyRequestHandle *vrh_head; | ||
331 | |||
332 | /** | ||
333 | * Tail of the DLL. | ||
334 | */ | ||
335 | static struct VerifyRequestHandle *vrh_tail; | ||
336 | |||
337 | /** | ||
338 | * Handle to the statistics service | ||
339 | */ | ||
340 | static struct GNUNET_STATISTICS_Handle *statistics; | ||
341 | |||
342 | /** | ||
343 | * Handle to GNS service. | ||
344 | */ | ||
345 | static struct GNUNET_GNS_Handle *gns; | ||
346 | |||
347 | |||
348 | /** | ||
349 | * Handle to namestore service | ||
350 | */ | ||
351 | static struct GNUNET_NAMESTORE_Handle *namestore; | ||
352 | |||
353 | static void | ||
354 | cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry) | ||
355 | { | ||
356 | struct DelegationQueueEntry *dq_entry; | ||
357 | struct DelegationSetQueueEntry *child; | ||
358 | |||
359 | if (NULL == ds_entry) | ||
360 | return; | ||
361 | |||
362 | for (dq_entry = ds_entry->queue_entries_head; | ||
363 | NULL != dq_entry; | ||
364 | dq_entry = ds_entry->queue_entries_head) | ||
365 | { | ||
366 | GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head, | ||
367 | ds_entry->queue_entries_tail, | ||
368 | dq_entry); | ||
369 | for (child = dq_entry->set_entries_head; | ||
370 | NULL != child; | ||
371 | child = dq_entry->set_entries_head) | ||
372 | { | ||
373 | GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head, | ||
374 | dq_entry->set_entries_tail, | ||
375 | child); | ||
376 | cleanup_delegation_set (child); | ||
377 | } | ||
378 | GNUNET_free (dq_entry); | ||
379 | } | ||
380 | if (NULL != ds_entry->issuer_key) | ||
381 | GNUNET_free (ds_entry->issuer_key); | ||
382 | if (NULL != ds_entry->lookup_attribute) | ||
383 | GNUNET_free (ds_entry->lookup_attribute); | ||
384 | if (NULL != ds_entry->issuer_attribute) | ||
385 | GNUNET_free (ds_entry->issuer_attribute); | ||
386 | if (NULL != ds_entry->unresolved_attribute_delegation) | ||
387 | GNUNET_free (ds_entry->unresolved_attribute_delegation); | ||
388 | if (NULL != ds_entry->attr_trailer) | ||
389 | GNUNET_free (ds_entry->attr_trailer); | ||
390 | if (NULL != ds_entry->lookup_request) | ||
391 | { | ||
392 | GNUNET_GNS_lookup_cancel (ds_entry->lookup_request); | ||
393 | ds_entry->lookup_request = NULL; | ||
394 | } | ||
395 | if (NULL != ds_entry->delegation_chain_entry) | ||
396 | { | ||
397 | if (NULL != ds_entry->delegation_chain_entry->subject_attribute) | ||
398 | GNUNET_free (ds_entry->delegation_chain_entry->subject_attribute); | ||
399 | if (NULL != ds_entry->delegation_chain_entry->issuer_attribute) | ||
400 | GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute); | ||
401 | GNUNET_free (ds_entry->delegation_chain_entry); | ||
402 | } | ||
403 | GNUNET_free (ds_entry); | ||
404 | } | ||
405 | |||
406 | static void | ||
407 | cleanup_handle (struct VerifyRequestHandle *vrh) | ||
408 | { | ||
409 | struct CredentialRecordEntry *cr_entry; | ||
410 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
411 | "Cleaning up...\n"); | ||
412 | if (NULL != vrh->lookup_request) | ||
413 | { | ||
414 | GNUNET_GNS_lookup_cancel (vrh->lookup_request); | ||
415 | vrh->lookup_request = NULL; | ||
416 | } | ||
417 | cleanup_delegation_set (vrh->root_set); | ||
418 | if (NULL != vrh->issuer_attribute) | ||
419 | GNUNET_free (vrh->issuer_attribute); | ||
420 | for (cr_entry = vrh->cred_chain_head; | ||
421 | NULL != vrh->cred_chain_head; | ||
422 | cr_entry = vrh->cred_chain_head) | ||
423 | { | ||
424 | GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head, | ||
425 | vrh->cred_chain_tail, | ||
426 | cr_entry); | ||
427 | if (NULL != cr_entry->credential); | ||
428 | GNUNET_free (cr_entry->credential); | ||
429 | GNUNET_free (cr_entry); | ||
430 | } | ||
431 | GNUNET_free (vrh); | ||
432 | } | ||
433 | |||
434 | /** | ||
435 | * Task run during shutdown. | ||
436 | * | ||
437 | * @param cls unused | ||
438 | * @param tc unused | ||
439 | */ | ||
440 | static void | ||
441 | shutdown_task (void *cls) | ||
442 | { | ||
443 | struct VerifyRequestHandle *vrh; | ||
444 | |||
445 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
446 | "Shutting down!\n"); | ||
447 | |||
448 | while (NULL != (vrh = vrh_head)) | ||
449 | { | ||
450 | //CREDENTIAL_resolver_lookup_cancel (clh->lookup); | ||
451 | GNUNET_CONTAINER_DLL_remove (vrh_head, | ||
452 | vrh_tail, | ||
453 | vrh); | ||
454 | cleanup_handle (vrh); | ||
455 | } | ||
456 | |||
457 | if (NULL != gns) | ||
458 | { | ||
459 | GNUNET_GNS_disconnect (gns); | ||
460 | gns = NULL; | ||
461 | } | ||
462 | if (NULL != namestore) | ||
463 | { | ||
464 | GNUNET_NAMESTORE_disconnect (namestore); | ||
465 | namestore = NULL; | ||
466 | } | ||
467 | if (NULL != statistics) | ||
468 | { | ||
469 | GNUNET_STATISTICS_destroy (statistics, | ||
470 | GNUNET_NO); | ||
471 | statistics = NULL; | ||
472 | } | ||
473 | |||
474 | } | ||
475 | |||
476 | |||
477 | |||
478 | /** | ||
479 | * Send. | ||
480 | * | ||
481 | * @param handle the handle to the request | ||
482 | */ | ||
483 | static void | ||
484 | send_lookup_response (struct VerifyRequestHandle *vrh) | ||
485 | { | ||
486 | struct GNUNET_MQ_Envelope *env; | ||
487 | struct DelegationChainResultMessage *rmsg; | ||
488 | struct DelegationChainEntry *dce; | ||
489 | struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size]; | ||
490 | struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size]; | ||
491 | struct CredentialRecordEntry *cd; | ||
492 | struct CredentialRecordEntry *tmp; | ||
493 | size_t size; | ||
494 | int i; | ||
495 | |||
496 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
497 | "Sending response\n"); | ||
498 | dce = vrh->delegation_chain_head; | ||
499 | for (i=0;i<vrh->delegation_chain_size;i++) | ||
500 | { | ||
501 | dd[i].issuer_key = dce->issuer_key; | ||
502 | dd[i].subject_key = dce->subject_key; | ||
503 | dd[i].issuer_attribute = dce->issuer_attribute; | ||
504 | dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1; | ||
505 | dd[i].subject_attribute_len = 0; | ||
506 | dd[i].subject_attribute = NULL; | ||
507 | if (NULL != dce->subject_attribute) | ||
508 | { | ||
509 | dd[i].subject_attribute = dce->subject_attribute; | ||
510 | dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1; | ||
511 | } | ||
512 | dce = dce->next; | ||
513 | } | ||
514 | |||
515 | /** | ||
516 | * Remove all credentials not needed | ||
517 | */ | ||
518 | for (cd = vrh->cred_chain_head; NULL != cd;) | ||
519 | { | ||
520 | if (cd->refcount > 0) | ||
521 | { | ||
522 | cd = cd->next; | ||
523 | continue; | ||
524 | } | ||
525 | tmp = cd; | ||
526 | cd = cd->next; | ||
527 | GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head, | ||
528 | vrh->cred_chain_tail, | ||
529 | tmp); | ||
530 | GNUNET_free (tmp->credential); | ||
531 | GNUNET_free (tmp); | ||
532 | vrh->cred_chain_size--; | ||
533 | } | ||
534 | |||
535 | /** | ||
536 | * Get serialized record data | ||
537 | * Append at the end of rmsg | ||
538 | */ | ||
539 | cd = vrh->cred_chain_head; | ||
540 | for (i=0;i<vrh->cred_chain_size;i++) | ||
541 | { | ||
542 | cred[i].issuer_key = cd->credential->issuer_key; | ||
543 | cred[i].subject_key = cd->credential->subject_key; | ||
544 | cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1; | ||
545 | cred[i].issuer_attribute = cd->credential->issuer_attribute; | ||
546 | cred[i].expiration = cd->credential->expiration; | ||
547 | cred[i].signature = cd->credential->signature; | ||
548 | cd = cd->next; | ||
549 | } | ||
550 | size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size, | ||
551 | dd, | ||
552 | vrh->cred_chain_size, | ||
553 | cred); | ||
554 | env = GNUNET_MQ_msg_extra (rmsg, | ||
555 | size, | ||
556 | GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT); | ||
557 | //Assign id so that client can find associated request | ||
558 | rmsg->id = vrh->request_id; | ||
559 | rmsg->d_count = htonl (vrh->delegation_chain_size); | ||
560 | rmsg->c_count = htonl (vrh->cred_chain_size); | ||
561 | |||
562 | if (0 < vrh->cred_chain_size) | ||
563 | rmsg->cred_found = htonl (GNUNET_YES); | ||
564 | else | ||
565 | rmsg->cred_found = htonl (GNUNET_NO); | ||
566 | |||
567 | GNUNET_assert (-1 != | ||
568 | GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size, | ||
569 | dd, | ||
570 | vrh->cred_chain_size, | ||
571 | cred, | ||
572 | size, | ||
573 | (char*)&rmsg[1])); | ||
574 | |||
575 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client), | ||
576 | env); | ||
577 | GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh); | ||
578 | cleanup_handle(vrh); | ||
579 | |||
580 | GNUNET_STATISTICS_update (statistics, | ||
581 | "Completed verifications", 1, | ||
582 | GNUNET_NO); | ||
583 | } | ||
584 | |||
585 | |||
586 | static void | ||
587 | backward_resolution (void* cls, | ||
588 | uint32_t rd_count, | ||
589 | const struct GNUNET_GNSRECORD_Data *rd) | ||
590 | { | ||
591 | |||
592 | struct VerifyRequestHandle *vrh; | ||
593 | const struct GNUNET_CREDENTIAL_DelegationRecord *sets; | ||
594 | struct CredentialRecordEntry *cred_pointer; | ||
595 | struct DelegationSetQueueEntry *current_set; | ||
596 | struct DelegationSetQueueEntry *ds_entry; | ||
597 | struct DelegationSetQueueEntry *tmp_set; | ||
598 | struct DelegationQueueEntry *dq_entry; | ||
599 | char *expanded_attr; | ||
600 | char *lookup_attribute; | ||
601 | int i; | ||
602 | int j; | ||
603 | |||
604 | |||
605 | current_set = cls; | ||
606 | current_set->lookup_request = NULL; | ||
607 | vrh = current_set->handle; | ||
608 | vrh->pending_lookups--; | ||
609 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
610 | "Got %d attrs\n", rd_count); | ||
611 | |||
612 | // Each OR | ||
613 | for (i=0; i < rd_count; i++) | ||
614 | { | ||
615 | if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type) | ||
616 | continue; | ||
617 | |||
618 | sets = rd[i].data; | ||
619 | struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)]; | ||
620 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
621 | "Found new attribute delegation with %d sets. Creating new Job...\n", | ||
622 | ntohl (sets->set_count)); | ||
623 | |||
624 | if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size), | ||
625 | (const char*)&sets[1], | ||
626 | ntohl(sets->set_count), | ||
627 | set)) | ||
628 | { | ||
629 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
630 | "Failed to deserialize!\n"); | ||
631 | continue; | ||
632 | } | ||
633 | dq_entry = GNUNET_new (struct DelegationQueueEntry); | ||
634 | dq_entry->required_solutions = ntohl(sets->set_count); | ||
635 | dq_entry->parent_set = current_set; | ||
636 | GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head, | ||
637 | current_set->queue_entries_tail, | ||
638 | dq_entry); | ||
639 | // Each AND | ||
640 | for (j=0; j<ntohl(sets->set_count); j++) | ||
641 | { | ||
642 | ds_entry = GNUNET_new (struct DelegationSetQueueEntry); | ||
643 | if (NULL != current_set->attr_trailer) | ||
644 | { | ||
645 | if (0 == set[j].subject_attribute_len) | ||
646 | { | ||
647 | GNUNET_asprintf (&expanded_attr, | ||
648 | "%s", | ||
649 | current_set->attr_trailer); | ||
650 | |||
651 | } else { | ||
652 | GNUNET_asprintf (&expanded_attr, | ||
653 | "%s.%s", | ||
654 | set[j].subject_attribute, | ||
655 | current_set->attr_trailer); | ||
656 | } | ||
657 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
658 | "Expanded to %s\n", expanded_attr); | ||
659 | ds_entry->unresolved_attribute_delegation = expanded_attr; | ||
660 | } else { | ||
661 | if (0 != set[j].subject_attribute_len) | ||
662 | { | ||
663 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
664 | "Not Expanding %s\n", set[j].subject_attribute); | ||
665 | ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute); | ||
666 | } | ||
667 | } | ||
668 | |||
669 | //Add a credential chain entry | ||
670 | ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry); | ||
671 | ds_entry->delegation_chain_entry->subject_key = set[j].subject_key; | ||
672 | ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
673 | GNUNET_memcpy (ds_entry->issuer_key, | ||
674 | &set[j].subject_key, | ||
675 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
676 | if (0 < set[j].subject_attribute_len) | ||
677 | ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute); | ||
678 | ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key; | ||
679 | ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute); | ||
680 | |||
681 | ds_entry->parent_queue_entry = dq_entry; //current_delegation; | ||
682 | GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head, | ||
683 | dq_entry->set_entries_tail, | ||
684 | ds_entry); | ||
685 | |||
686 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
687 | "Checking for cred match\n"); | ||
688 | /** | ||
689 | * Check if this delegation already matches one of our credentials | ||
690 | */ | ||
691 | for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL; | ||
692 | cred_pointer = cred_pointer->next) | ||
693 | { | ||
694 | if(0 != memcmp (&set->subject_key, | ||
695 | &cred_pointer->credential->issuer_key, | ||
696 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
697 | continue; | ||
698 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
699 | "Checking if %s matches %s\n", | ||
700 | ds_entry->unresolved_attribute_delegation, | ||
701 | cred_pointer->credential->issuer_attribute); | ||
702 | |||
703 | if (0 != strcmp (ds_entry->unresolved_attribute_delegation, | ||
704 | cred_pointer->credential->issuer_attribute)) | ||
705 | continue; | ||
706 | |||
707 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
708 | "Found issuer\n"); | ||
709 | cred_pointer->refcount++; | ||
710 | //Backtrack | ||
711 | for (tmp_set = ds_entry; | ||
712 | NULL != tmp_set->parent_queue_entry; | ||
713 | tmp_set = tmp_set->parent_queue_entry->parent_set) | ||
714 | { | ||
715 | tmp_set->parent_queue_entry->required_solutions--; | ||
716 | if (NULL != tmp_set->delegation_chain_entry) | ||
717 | { | ||
718 | vrh->delegation_chain_size++; | ||
719 | GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head, | ||
720 | vrh->delegation_chain_tail, | ||
721 | tmp_set->delegation_chain_entry); | ||
722 | } | ||
723 | if (0 < tmp_set->parent_queue_entry->required_solutions) | ||
724 | break; | ||
725 | } | ||
726 | |||
727 | if (NULL == tmp_set->parent_queue_entry) | ||
728 | { | ||
729 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
730 | "All solutions found\n"); | ||
731 | //Found match | ||
732 | send_lookup_response (vrh); | ||
733 | return; | ||
734 | } | ||
735 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
736 | "Not all solutions found yet.\n"); | ||
737 | continue; | ||
738 | |||
739 | } | ||
740 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
741 | "Building new lookup request from %s\n", | ||
742 | ds_entry->unresolved_attribute_delegation); | ||
743 | //Continue with backward resolution | ||
744 | char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1]; | ||
745 | strcpy (issuer_attribute_name, | ||
746 | ds_entry->unresolved_attribute_delegation); | ||
747 | char *next_attr = strtok (issuer_attribute_name, "."); | ||
748 | GNUNET_asprintf (&lookup_attribute, | ||
749 | "%s.gnu", | ||
750 | next_attr); | ||
751 | GNUNET_asprintf (&ds_entry->lookup_attribute, | ||
752 | "%s", | ||
753 | next_attr); | ||
754 | if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation)) | ||
755 | { | ||
756 | ds_entry->attr_trailer = NULL; | ||
757 | } else { | ||
758 | next_attr += strlen (next_attr) + 1; | ||
759 | ds_entry->attr_trailer = GNUNET_strdup (next_attr); | ||
760 | } | ||
761 | |||
762 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
763 | "Looking up %s\n", ds_entry->lookup_attribute); | ||
764 | if (NULL != ds_entry->attr_trailer) | ||
765 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
766 | "%s still to go...\n", ds_entry->attr_trailer); | ||
767 | |||
768 | vrh->pending_lookups++; | ||
769 | ds_entry->handle = vrh; | ||
770 | ds_entry->lookup_request = GNUNET_GNS_lookup (gns, | ||
771 | lookup_attribute, | ||
772 | ds_entry->issuer_key, //issuer_key, | ||
773 | GNUNET_GNSRECORD_TYPE_ATTRIBUTE, | ||
774 | GNUNET_GNS_LO_DEFAULT, | ||
775 | &backward_resolution, | ||
776 | ds_entry); | ||
777 | GNUNET_free (lookup_attribute); | ||
778 | } | ||
779 | } | ||
780 | |||
781 | if(0 == vrh->pending_lookups) | ||
782 | { | ||
783 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
784 | "We are all out of attributes...\n"); | ||
785 | send_lookup_response (vrh); | ||
786 | return; | ||
787 | |||
788 | } | ||
789 | } | ||
790 | |||
791 | |||
792 | /** | ||
793 | * Result from GNS lookup. | ||
794 | * | ||
795 | * @param cls the closure (our client lookup handle) | ||
796 | * @param rd_count the number of records in @a rd | ||
797 | * @param rd the record data | ||
798 | */ | ||
799 | static void | ||
800 | delegation_chain_resolution_start (void* cls) | ||
801 | { | ||
802 | struct VerifyRequestHandle *vrh = cls; | ||
803 | struct DelegationSetQueueEntry *ds_entry; | ||
804 | struct CredentialRecordEntry *cr_entry; | ||
805 | vrh->lookup_request = NULL; | ||
806 | |||
807 | if (0 == vrh->cred_chain_size) | ||
808 | { | ||
809 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
810 | "No credentials found\n"); | ||
811 | send_lookup_response (vrh); | ||
812 | return; | ||
813 | } | ||
814 | |||
815 | for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next) | ||
816 | { | ||
817 | if (0 != memcmp (&cr_entry->credential->issuer_key, | ||
818 | &vrh->issuer_key, | ||
819 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
820 | continue; | ||
821 | if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute)) | ||
822 | continue; | ||
823 | cr_entry->refcount++; | ||
824 | //Found match prematurely | ||
825 | send_lookup_response (vrh); | ||
826 | return; | ||
827 | |||
828 | } | ||
829 | |||
830 | /** | ||
831 | * Check for attributes from the issuer and follow the chain | ||
832 | * till you get the required subject's attributes | ||
833 | */ | ||
834 | char issuer_attribute_name[strlen (vrh->issuer_attribute)]; | ||
835 | strcpy (issuer_attribute_name, | ||
836 | vrh->issuer_attribute); | ||
837 | strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute), | ||
838 | ".gnu"); | ||
839 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
840 | "Looking up %s\n", issuer_attribute_name); | ||
841 | ds_entry = GNUNET_new (struct DelegationSetQueueEntry); | ||
842 | ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
843 | memcpy (ds_entry->issuer_key, | ||
844 | &vrh->issuer_key, | ||
845 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
846 | ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute); | ||
847 | ds_entry->handle = vrh; | ||
848 | ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute); | ||
849 | vrh->root_set = ds_entry; | ||
850 | vrh->pending_lookups = 1; | ||
851 | //Start with backward resolution | ||
852 | ds_entry->lookup_request = GNUNET_GNS_lookup (gns, | ||
853 | issuer_attribute_name, | ||
854 | &vrh->issuer_key, //issuer_key, | ||
855 | GNUNET_GNSRECORD_TYPE_ATTRIBUTE, | ||
856 | GNUNET_GNS_LO_DEFAULT, | ||
857 | &backward_resolution, | ||
858 | ds_entry); | ||
859 | } | ||
860 | |||
861 | /** | ||
862 | * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message | ||
863 | * | ||
864 | * @param cls client sending the message | ||
865 | * @param v_msg message of type `struct VerifyMessage` | ||
866 | * @return #GNUNET_OK if @a v_msg is well-formed | ||
867 | */ | ||
868 | static int | ||
869 | check_verify (void *cls, | ||
870 | const struct VerifyMessage *v_msg) | ||
871 | { | ||
872 | size_t msg_size; | ||
873 | const char* attr; | ||
874 | |||
875 | msg_size = ntohs (v_msg->header.size); | ||
876 | if (msg_size < sizeof (struct VerifyMessage)) | ||
877 | { | ||
878 | GNUNET_break (0); | ||
879 | return GNUNET_SYSERR; | ||
880 | } | ||
881 | if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) | ||
882 | { | ||
883 | GNUNET_break (0); | ||
884 | return GNUNET_SYSERR; | ||
885 | } | ||
886 | attr = (const char *) &v_msg[1]; | ||
887 | |||
888 | if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) | ||
889 | { | ||
890 | GNUNET_break (0); | ||
891 | return GNUNET_SYSERR; | ||
892 | } | ||
893 | return GNUNET_OK; | ||
894 | } | ||
895 | |||
896 | /** | ||
897 | * Handle Credential verification requests from client | ||
898 | * | ||
899 | * @param cls the closure | ||
900 | * @param client the client | ||
901 | * @param message the message | ||
902 | */ | ||
903 | static void | ||
904 | handle_verify (void *cls, | ||
905 | const struct VerifyMessage *v_msg) | ||
906 | { | ||
907 | struct VerifyRequestHandle *vrh; | ||
908 | struct GNUNET_SERVICE_Client *client = cls; | ||
909 | struct CredentialRecordEntry *cr_entry; | ||
910 | uint32_t credentials_count; | ||
911 | uint32_t credential_data_size; | ||
912 | int i; | ||
913 | char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; | ||
914 | char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; | ||
915 | char *attrptr = attr; | ||
916 | char *credential_data; | ||
917 | const char *utf_in; | ||
918 | |||
919 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
920 | "Received VERIFY message\n"); | ||
921 | utf_in = (const char *) &v_msg[1]; | ||
922 | GNUNET_STRINGS_utf8_tolower (utf_in, attrptr); | ||
923 | GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len)); | ||
924 | issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0'; | ||
925 | vrh = GNUNET_new (struct VerifyRequestHandle); | ||
926 | GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh); | ||
927 | vrh->client = client; | ||
928 | vrh->request_id = v_msg->id; | ||
929 | vrh->issuer_key = v_msg->issuer_key; | ||
930 | vrh->subject_key = v_msg->subject_key; | ||
931 | vrh->issuer_attribute = GNUNET_strdup (issuer_attribute); | ||
932 | if (NULL == issuer_attribute) | ||
933 | { | ||
934 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
935 | "No issuer attribute provided!\n"); | ||
936 | send_lookup_response (vrh); | ||
937 | return; | ||
938 | } | ||
939 | /** | ||
940 | * First, collect credentials | ||
941 | * TODO: cleanup! | ||
942 | */ | ||
943 | credentials_count = ntohl(v_msg->c_count); | ||
944 | credential_data_size = ntohs (v_msg->header.size) | ||
945 | - sizeof (struct VerifyMessage) | ||
946 | - ntohs (v_msg->issuer_attribute_len) | ||
947 | - 1; | ||
948 | struct GNUNET_CREDENTIAL_Credential credentials[credentials_count]; | ||
949 | credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1; | ||
950 | if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size, | ||
951 | credential_data, | ||
952 | credentials_count, | ||
953 | credentials)) | ||
954 | { | ||
955 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
956 | "Cannot deserialize credentials!\n"); | ||
957 | send_lookup_response (vrh); | ||
958 | return; | ||
959 | } | ||
960 | |||
961 | for (i=0;i<credentials_count;i++) { | ||
962 | cr_entry = GNUNET_new (struct CredentialRecordEntry); | ||
963 | cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + | ||
964 | credentials[i].issuer_attribute_len); | ||
965 | GNUNET_memcpy (cr_entry->credential, | ||
966 | &credentials[i], | ||
967 | sizeof (struct GNUNET_CREDENTIAL_Credential)); | ||
968 | GNUNET_memcpy (&cr_entry->credential[1], | ||
969 | credentials[i].issuer_attribute, | ||
970 | credentials[i].issuer_attribute_len); | ||
971 | cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1]; | ||
972 | GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head, | ||
973 | vrh->cred_chain_tail, | ||
974 | cr_entry); | ||
975 | vrh->cred_chain_size++; | ||
976 | } | ||
977 | |||
978 | delegation_chain_resolution_start (vrh); | ||
979 | |||
980 | } | ||
981 | |||
982 | /** | ||
983 | * We encountered an error while collecting | ||
984 | */ | ||
985 | static void | ||
986 | handle_cred_collection_error_cb (void *cls) | ||
987 | { | ||
988 | struct VerifyRequestHandle *vrh = cls; | ||
989 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
990 | "Got disconnected from namestore database.\n"); | ||
991 | vrh->cred_collection_iter = NULL; | ||
992 | send_lookup_response (vrh); | ||
993 | } | ||
994 | |||
995 | static void | ||
996 | collect_next (void *cls) | ||
997 | { | ||
998 | struct VerifyRequestHandle *vrh = cls; | ||
999 | vrh->collect_next_task = NULL; | ||
1000 | GNUNET_assert (NULL != vrh->cred_collection_iter); | ||
1001 | GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter); | ||
1002 | } | ||
1003 | |||
1004 | /** | ||
1005 | * Store credential | ||
1006 | */ | ||
1007 | static void | ||
1008 | handle_cred_collection_cb (void *cls, | ||
1009 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | ||
1010 | const char *label, | ||
1011 | unsigned int rd_count, | ||
1012 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1013 | { | ||
1014 | struct VerifyRequestHandle *vrh = cls; | ||
1015 | struct GNUNET_CREDENTIAL_Credential *crd; | ||
1016 | struct CredentialRecordEntry *cr_entry; | ||
1017 | int cred_record_count; | ||
1018 | int i; | ||
1019 | |||
1020 | cred_record_count = 0; | ||
1021 | for (i=0; i < rd_count; i++) | ||
1022 | { | ||
1023 | if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type) | ||
1024 | continue; | ||
1025 | cred_record_count++; | ||
1026 | crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data, | ||
1027 | rd[i].data_size); | ||
1028 | if (NULL == crd) | ||
1029 | { | ||
1030 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1031 | "Invalid credential found\n"); | ||
1032 | continue; | ||
1033 | } | ||
1034 | cr_entry = GNUNET_new (struct CredentialRecordEntry); | ||
1035 | cr_entry->credential = crd; | ||
1036 | GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head, | ||
1037 | vrh->cred_chain_tail, | ||
1038 | cr_entry); | ||
1039 | vrh->cred_chain_size++; | ||
1040 | } | ||
1041 | vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next, | ||
1042 | vrh); | ||
1043 | } | ||
1044 | |||
1045 | /** | ||
1046 | * We encountered an error while collecting | ||
1047 | */ | ||
1048 | static void | ||
1049 | handle_cred_collection_finished_cb (void *cls) | ||
1050 | { | ||
1051 | struct VerifyRequestHandle *vrh = cls; | ||
1052 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1053 | "Done collecting credentials.\n"); | ||
1054 | vrh->cred_collection_iter = NULL; | ||
1055 | delegation_chain_resolution_start (vrh); | ||
1056 | } | ||
1057 | |||
1058 | /** | ||
1059 | * Handle Credential collection requests from client | ||
1060 | * | ||
1061 | * @param cls the closure | ||
1062 | * @param client the client | ||
1063 | * @param message the message | ||
1064 | */ | ||
1065 | static void | ||
1066 | handle_collect (void *cls, | ||
1067 | const struct CollectMessage *c_msg) | ||
1068 | { | ||
1069 | char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; | ||
1070 | char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; | ||
1071 | struct VerifyRequestHandle *vrh; | ||
1072 | struct GNUNET_SERVICE_Client *client = cls; | ||
1073 | char *attrptr = attr; | ||
1074 | const char *utf_in; | ||
1075 | |||
1076 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1077 | "Received COLLECT message\n"); | ||
1078 | |||
1079 | utf_in = (const char *) &c_msg[1]; | ||
1080 | GNUNET_STRINGS_utf8_tolower (utf_in, attrptr); | ||
1081 | |||
1082 | GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len)); | ||
1083 | issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0'; | ||
1084 | vrh = GNUNET_new (struct VerifyRequestHandle); | ||
1085 | GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh); | ||
1086 | vrh->client = client; | ||
1087 | vrh->request_id = c_msg->id; | ||
1088 | vrh->issuer_key = c_msg->issuer_key; | ||
1089 | GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key, | ||
1090 | &vrh->subject_key); | ||
1091 | vrh->issuer_attribute = GNUNET_strdup (issuer_attribute); | ||
1092 | |||
1093 | if (NULL == issuer_attribute) | ||
1094 | { | ||
1095 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1096 | "No issuer attribute provided!\n"); | ||
1097 | send_lookup_response (vrh); | ||
1098 | return; | ||
1099 | } | ||
1100 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1101 | "Getting credentials for subject\n"); | ||
1102 | /** | ||
1103 | * First, get attribute from subject | ||
1104 | */ | ||
1105 | vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore, | ||
1106 | &c_msg->subject_key, | ||
1107 | &handle_cred_collection_error_cb, | ||
1108 | vrh, | ||
1109 | &handle_cred_collection_cb, | ||
1110 | vrh, | ||
1111 | &handle_cred_collection_finished_cb, | ||
1112 | vrh); | ||
1113 | } | ||
1114 | |||
1115 | |||
1116 | /** | ||
1117 | * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT message | ||
1118 | * | ||
1119 | * @param cls client sending the message | ||
1120 | * @param v_msg message of type `struct CollectMessage` | ||
1121 | * @return #GNUNET_OK if @a v_msg is well-formed | ||
1122 | */ | ||
1123 | static int | ||
1124 | check_collect (void *cls, | ||
1125 | const struct CollectMessage *c_msg) | ||
1126 | { | ||
1127 | size_t msg_size; | ||
1128 | const char* attr; | ||
1129 | |||
1130 | msg_size = ntohs (c_msg->header.size); | ||
1131 | if (msg_size < sizeof (struct CollectMessage)) | ||
1132 | { | ||
1133 | GNUNET_break (0); | ||
1134 | return GNUNET_SYSERR; | ||
1135 | } | ||
1136 | if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) | ||
1137 | { | ||
1138 | GNUNET_break (0); | ||
1139 | return GNUNET_SYSERR; | ||
1140 | } | ||
1141 | attr = (const char *) &c_msg[1]; | ||
1142 | |||
1143 | if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) || | ||
1144 | (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) ) | ||
1145 | { | ||
1146 | GNUNET_break (0); | ||
1147 | return GNUNET_SYSERR; | ||
1148 | } | ||
1149 | return GNUNET_OK; | ||
1150 | } | ||
1151 | |||
1152 | /** | ||
1153 | * One of our clients disconnected, clean up after it. | ||
1154 | * | ||
1155 | * @param cls NULL | ||
1156 | * @param client the client that disconnected | ||
1157 | */ | ||
1158 | static void | ||
1159 | client_disconnect_cb (void *cls, | ||
1160 | struct GNUNET_SERVICE_Client *client, | ||
1161 | void *app_ctx) | ||
1162 | { | ||
1163 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1164 | "Client %p disconnected\n", | ||
1165 | client); | ||
1166 | } | ||
1167 | |||
1168 | /** | ||
1169 | * Add a client to our list of active clients. | ||
1170 | * | ||
1171 | * @param cls NULL | ||
1172 | * @param client client to add | ||
1173 | * @param mq message queue for @a client | ||
1174 | * @return this client | ||
1175 | */ | ||
1176 | static void * | ||
1177 | client_connect_cb (void *cls, | ||
1178 | struct GNUNET_SERVICE_Client *client, | ||
1179 | struct GNUNET_MQ_Handle *mq) | ||
1180 | { | ||
1181 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1182 | "Client %p connected\n", | ||
1183 | client); | ||
1184 | return client; | ||
1185 | } | ||
1186 | |||
1187 | /** | ||
1188 | * Process Credential requests. | ||
1189 | * | ||
1190 | * @param cls closure | ||
1191 | * @param server the initialized server | ||
1192 | * @param c configuration to use | ||
1193 | */ | ||
1194 | static void | ||
1195 | run (void *cls, | ||
1196 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1197 | struct GNUNET_SERVICE_Handle *handle) | ||
1198 | { | ||
1199 | |||
1200 | gns = GNUNET_GNS_connect (c); | ||
1201 | if (NULL == gns) | ||
1202 | { | ||
1203 | fprintf (stderr, | ||
1204 | _("Failed to connect to GNS\n")); | ||
1205 | } | ||
1206 | namestore = GNUNET_NAMESTORE_connect (c); | ||
1207 | if (NULL == namestore) | ||
1208 | { | ||
1209 | fprintf (stderr, | ||
1210 | _("Failed to connect to namestore\n")); | ||
1211 | } | ||
1212 | |||
1213 | statistics = GNUNET_STATISTICS_create ("credential", c); | ||
1214 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
1215 | } | ||
1216 | |||
1217 | |||
1218 | /** | ||
1219 | * Define "main" method using service macro | ||
1220 | */ | ||
1221 | GNUNET_SERVICE_MAIN | ||
1222 | ("credential", | ||
1223 | GNUNET_SERVICE_OPTION_NONE, | ||
1224 | &run, | ||
1225 | &client_connect_cb, | ||
1226 | &client_disconnect_cb, | ||
1227 | NULL, | ||
1228 | GNUNET_MQ_hd_var_size (verify, | ||
1229 | GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY, | ||
1230 | struct VerifyMessage, | ||
1231 | NULL), | ||
1232 | GNUNET_MQ_hd_var_size (collect, | ||
1233 | GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT, | ||
1234 | struct CollectMessage, | ||
1235 | NULL), | ||
1236 | GNUNET_MQ_handler_end()); | ||
1237 | |||
1238 | /* end of gnunet-service-credential.c */ | ||
diff --git a/src/credential/plugin_gnsrecord_credential.c b/src/credential/plugin_gnsrecord_credential.c new file mode 100644 index 000000000..72d6b53f5 --- /dev/null +++ b/src/credential/plugin_gnsrecord_credential.c | |||
@@ -0,0 +1,353 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file credential/plugin_gnsrecord_credential.c | ||
23 | * @brief gnsrecord plugin to provide the API for CREDENTIAL records | ||
24 | * @author Adnan Husain | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_gnsrecord_lib.h" | ||
30 | #include "gnunet_credential_service.h" | ||
31 | #include "gnunet_gnsrecord_plugin.h" | ||
32 | #include "gnunet_signatures.h" | ||
33 | #include "credential_serialization.h" | ||
34 | #include "credential_misc.h" | ||
35 | |||
36 | /** | ||
37 | * Convert the 'value' of a record to a string. | ||
38 | * | ||
39 | * @param cls closure, unused | ||
40 | * @param type type of the record | ||
41 | * @param data value in binary encoding | ||
42 | * @param data_size number of bytes in @a data | ||
43 | * @return NULL on error, otherwise human-readable representation of the value | ||
44 | */ | ||
45 | static char * | ||
46 | credential_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 | */ | ||
149 | static int | ||
150 | credential_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 | */ | ||
265 | static 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 | */ | ||
283 | static uint32_t | ||
284 | credential_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 | */ | ||
304 | static const char * | ||
305 | credential_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 | */ | ||
324 | void * | ||
325 | libgnunet_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 | */ | ||
344 | void * | ||
345 | libgnunet_plugin_gnsrecord_credential_done (void *cls) | ||
346 | { | ||
347 | struct GNUNET_GNSRECORD_PluginFunctions *api = cls; | ||
348 | |||
349 | GNUNET_free (api); | ||
350 | return NULL; | ||
351 | } | ||
352 | |||
353 | /* end of plugin_gnsrecord_credential.c */ | ||
diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c new file mode 100644 index 000000000..48d48fba0 --- /dev/null +++ b/src/credential/plugin_rest_credential.c | |||
@@ -0,0 +1,1179 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @author Martin Schanzenbach | ||
22 | * @file gns/plugin_rest_credential.c | ||
23 | * @brief GNUnet CREDENTIAL REST plugin | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_rest_plugin.h" | ||
29 | #include <gnunet_identity_service.h> | ||
30 | #include <gnunet_gnsrecord_lib.h> | ||
31 | #include <gnunet_namestore_service.h> | ||
32 | #include <gnunet_credential_service.h> | ||
33 | #include <gnunet_rest_lib.h> | ||
34 | #include <gnunet_jsonapi_lib.h> | ||
35 | #include <gnunet_jsonapi_util.h> | ||
36 | #include <jansson.h> | ||
37 | |||
38 | #define GNUNET_REST_API_NS_CREDENTIAL "/credential" | ||
39 | |||
40 | #define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue" | ||
41 | |||
42 | #define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify" | ||
43 | |||
44 | #define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect" | ||
45 | |||
46 | #define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration" | ||
47 | |||
48 | #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key" | ||
49 | |||
50 | #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject" | ||
51 | |||
52 | #define GNUNET_REST_JSONAPI_CREDENTIAL "credential" | ||
53 | |||
54 | #define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential" | ||
55 | |||
56 | #define GNUNET_REST_JSONAPI_DELEGATIONS "delegations" | ||
57 | |||
58 | #define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute" | ||
59 | |||
60 | #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential" | ||
61 | |||
62 | /** | ||
63 | * @brief struct returned by the initialization function of the plugin | ||
64 | */ | ||
65 | struct Plugin | ||
66 | { | ||
67 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
68 | }; | ||
69 | |||
70 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
71 | |||
72 | struct 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 | */ | ||
167 | static void | ||
168 | cleanup_handle (struct RequestHandle *handle) | ||
169 | { | ||
170 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
171 | "Cleaning up\n"); | ||
172 | if (NULL != handle->json_root) | ||
173 | json_decref (handle->json_root); | ||
174 | |||
175 | if (NULL != handle->issuer_attr) | ||
176 | GNUNET_free (handle->issuer_attr); | ||
177 | if (NULL != handle->subject_attr) | ||
178 | GNUNET_free (handle->subject_attr); | ||
179 | if (NULL != handle->verify_request) | ||
180 | GNUNET_CREDENTIAL_request_cancel (handle->verify_request); | ||
181 | if (NULL != handle->credential) | ||
182 | GNUNET_CREDENTIAL_disconnect (handle->credential); | ||
183 | if (NULL != handle->id_op) | ||
184 | GNUNET_IDENTITY_cancel (handle->id_op); | ||
185 | if (NULL != handle->ego_lookup) | ||
186 | GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup); | ||
187 | if (NULL != handle->identity) | ||
188 | GNUNET_IDENTITY_disconnect (handle->identity); | ||
189 | if (NULL != handle->timeout_task) | ||
190 | { | ||
191 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
192 | } | ||
193 | GNUNET_free (handle); | ||
194 | } | ||
195 | |||
196 | |||
197 | /** | ||
198 | * Task run on shutdown. Cleans up everything. | ||
199 | * | ||
200 | * @param cls unused | ||
201 | * @param tc scheduler context | ||
202 | */ | ||
203 | static void | ||
204 | do_error (void *cls) | ||
205 | { | ||
206 | struct RequestHandle *handle = cls; | ||
207 | struct MHD_Response *resp; | ||
208 | |||
209 | resp = GNUNET_REST_create_response (NULL); | ||
210 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
211 | cleanup_handle (handle); | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * Attribute delegation to JSON | ||
216 | * @param attr the attribute | ||
217 | * @return JSON, NULL if failed | ||
218 | */ | ||
219 | static json_t* | ||
220 | attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry) | ||
221 | { | ||
222 | char *subject; | ||
223 | char *issuer; | ||
224 | json_t *attr_obj; | ||
225 | |||
226 | issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key); | ||
227 | if (NULL == issuer) | ||
228 | { | ||
229 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
230 | "Issuer in delegation malformed\n"); | ||
231 | return NULL; | ||
232 | } | ||
233 | subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key); | ||
234 | if (NULL == subject) | ||
235 | { | ||
236 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
237 | "Subject in credential malformed\n"); | ||
238 | GNUNET_free (issuer); | ||
239 | return NULL; | ||
240 | } | ||
241 | attr_obj = json_object (); | ||
242 | |||
243 | json_object_set_new (attr_obj, "issuer", json_string (issuer)); | ||
244 | json_object_set_new (attr_obj, "issuer_attribute", | ||
245 | json_string (delegation_chain_entry->issuer_attribute)); | ||
246 | |||
247 | json_object_set_new (attr_obj, "subject", json_string (subject)); | ||
248 | if (0 < delegation_chain_entry->subject_attribute_len) | ||
249 | { | ||
250 | json_object_set_new (attr_obj, "subject_attribute", | ||
251 | json_string (delegation_chain_entry->subject_attribute)); | ||
252 | } | ||
253 | GNUNET_free (issuer); | ||
254 | GNUNET_free (subject); | ||
255 | return attr_obj; | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * JSONAPI resource to Credential | ||
260 | * @param res the JSONAPI resource | ||
261 | * @return the resulting credential, NULL if failed | ||
262 | */ | ||
263 | static struct GNUNET_CREDENTIAL_Credential* | ||
264 | json_to_credential (json_t *res) | ||
265 | { | ||
266 | struct GNUNET_CREDENTIAL_Credential *cred; | ||
267 | json_t *tmp; | ||
268 | const char *attribute; | ||
269 | const char *signature; | ||
270 | char *sig; | ||
271 | |||
272 | tmp = json_object_get (res, "attribute"); | ||
273 | if (0 == json_is_string (tmp)) | ||
274 | { | ||
275 | return NULL; | ||
276 | } | ||
277 | attribute = json_string_value (tmp); | ||
278 | cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) | ||
279 | + strlen (attribute)); | ||
280 | cred->issuer_attribute = attribute; | ||
281 | cred->issuer_attribute_len = strlen (attribute); | ||
282 | tmp = json_object_get (res, "issuer"); | ||
283 | if (0 == json_is_string (tmp)) | ||
284 | { | ||
285 | GNUNET_free (cred); | ||
286 | return NULL; | ||
287 | } | ||
288 | |||
289 | GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp), | ||
290 | strlen (json_string_value(tmp)), | ||
291 | &cred->issuer_key); | ||
292 | tmp = json_object_get (res, "subject"); | ||
293 | if (0 == json_is_string (tmp)) | ||
294 | { | ||
295 | GNUNET_free (cred); | ||
296 | return NULL; | ||
297 | } | ||
298 | GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp), | ||
299 | strlen (json_string_value(tmp)), | ||
300 | &cred->subject_key); | ||
301 | |||
302 | tmp = json_object_get (res, "signature"); | ||
303 | if (0 == json_is_string (tmp)) | ||
304 | { | ||
305 | GNUNET_free (cred); | ||
306 | return NULL; | ||
307 | } | ||
308 | signature = json_string_value (tmp); | ||
309 | GNUNET_STRINGS_base64_decode (signature, | ||
310 | strlen (signature), | ||
311 | (char**)&sig); | ||
312 | GNUNET_memcpy (&cred->signature, | ||
313 | sig, | ||
314 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); | ||
315 | GNUNET_free (sig); | ||
316 | |||
317 | tmp = json_object_get (res, "expiration"); | ||
318 | if (0 == json_is_integer (tmp)) | ||
319 | { | ||
320 | GNUNET_free (cred); | ||
321 | return NULL; | ||
322 | } | ||
323 | cred->expiration.abs_value_us = json_integer_value (tmp); | ||
324 | return cred; | ||
325 | } | ||
326 | |||
327 | |||
328 | /** | ||
329 | * Credential to JSON | ||
330 | * @param cred the credential | ||
331 | * @return the resulting json, NULL if failed | ||
332 | */ | ||
333 | static json_t* | ||
334 | credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred) | ||
335 | { | ||
336 | char *issuer; | ||
337 | char *subject; | ||
338 | char *signature; | ||
339 | char attribute[cred->issuer_attribute_len + 1]; | ||
340 | json_t *cred_obj; | ||
341 | |||
342 | issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key); | ||
343 | if (NULL == issuer) | ||
344 | { | ||
345 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
346 | "Issuer in credential malformed\n"); | ||
347 | return NULL; | ||
348 | } | ||
349 | subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key); | ||
350 | if (NULL == subject) | ||
351 | { | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
353 | "Subject in credential malformed\n"); | ||
354 | GNUNET_free (issuer); | ||
355 | return NULL; | ||
356 | } | ||
357 | GNUNET_STRINGS_base64_encode ((char*)&cred->signature, | ||
358 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature), | ||
359 | &signature); | ||
360 | memcpy (attribute, | ||
361 | cred->issuer_attribute, | ||
362 | cred->issuer_attribute_len); | ||
363 | attribute[cred->issuer_attribute_len] = '\0'; | ||
364 | cred_obj = json_object (); | ||
365 | json_object_set_new (cred_obj, "issuer", json_string (issuer)); | ||
366 | json_object_set_new (cred_obj, "subject", json_string (subject)); | ||
367 | json_object_set_new (cred_obj, "attribute", json_string (attribute)); | ||
368 | json_object_set_new (cred_obj, "signature", json_string (signature)); | ||
369 | json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us)); | ||
370 | GNUNET_free (issuer); | ||
371 | GNUNET_free (subject); | ||
372 | GNUNET_free (signature); | ||
373 | return cred_obj; | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * Function called with the result of a Credential lookup. | ||
378 | * | ||
379 | * @param cls the 'const char *' name that was resolved | ||
380 | * @param cd_count number of records returned | ||
381 | * @param cd array of @a cd_count records with the results | ||
382 | */ | ||
383 | static void | ||
384 | handle_collect_response (void *cls, | ||
385 | unsigned int d_count, | ||
386 | struct GNUNET_CREDENTIAL_Delegation *delegation_chain, | ||
387 | unsigned int c_count, | ||
388 | struct GNUNET_CREDENTIAL_Credential *cred) | ||
389 | { | ||
390 | struct RequestHandle *handle = cls; | ||
391 | struct MHD_Response *resp; | ||
392 | struct GNUNET_JSONAPI_Document *json_document; | ||
393 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
394 | json_t *cred_obj; | ||
395 | json_t *cred_array; | ||
396 | char *result; | ||
397 | char *issuer; | ||
398 | char *id; | ||
399 | uint32_t i; | ||
400 | |||
401 | handle->verify_request = NULL; | ||
402 | if (NULL == cred) { | ||
403 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
404 | "Verify failed.\n"); | ||
405 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
406 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
407 | return; | ||
408 | } | ||
409 | issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key); | ||
410 | if (NULL == issuer) | ||
411 | { | ||
412 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
413 | "Issuer in delegation malformed\n"); | ||
414 | return; | ||
415 | } | ||
416 | GNUNET_asprintf (&id, | ||
417 | "%s.%s", | ||
418 | issuer, | ||
419 | handle->issuer_attr); | ||
420 | GNUNET_free (issuer); | ||
421 | json_document = GNUNET_JSONAPI_document_new (); | ||
422 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO, | ||
423 | id); | ||
424 | GNUNET_free (id); | ||
425 | cred_array = json_array (); | ||
426 | for (i=0;i<c_count;i++) | ||
427 | { | ||
428 | cred_obj = credential_to_json (&cred[i]); | ||
429 | json_array_append_new (cred_array, cred_obj); | ||
430 | } | ||
431 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
432 | GNUNET_REST_JSONAPI_CREDENTIAL, | ||
433 | cred_array); | ||
434 | GNUNET_JSONAPI_document_resource_add (json_document, json_resource); | ||
435 | GNUNET_JSONAPI_document_serialize (json_document, &result); | ||
436 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
437 | "Result %s\n", | ||
438 | result); | ||
439 | json_decref (cred_array); | ||
440 | GNUNET_JSONAPI_document_delete (json_document); | ||
441 | resp = GNUNET_REST_create_response (result); | ||
442 | GNUNET_free(result); | ||
443 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
444 | cleanup_handle (handle); | ||
445 | } | ||
446 | |||
447 | static void | ||
448 | subject_ego_lookup (void *cls, | ||
449 | const struct GNUNET_IDENTITY_Ego *ego) | ||
450 | { | ||
451 | struct RequestHandle *handle = cls; | ||
452 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key; | ||
453 | handle->ego_lookup = NULL; | ||
454 | |||
455 | if (NULL == ego) | ||
456 | { | ||
457 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
458 | "Subject not found\n"); | ||
459 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
460 | return; | ||
461 | } | ||
462 | sub_key = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
463 | handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential, | ||
464 | &handle->issuer_key, | ||
465 | handle->issuer_attr, | ||
466 | sub_key, | ||
467 | &handle_collect_response, | ||
468 | handle); | ||
469 | } | ||
470 | |||
471 | |||
472 | |||
473 | /** | ||
474 | * Function called with the result of a Credential lookup. | ||
475 | * | ||
476 | * @param cls the 'const char *' name that was resolved | ||
477 | * @param cd_count number of records returned | ||
478 | * @param cd array of @a cd_count records with the results | ||
479 | */ | ||
480 | static void | ||
481 | handle_verify_response (void *cls, | ||
482 | unsigned int d_count, | ||
483 | struct GNUNET_CREDENTIAL_Delegation *delegation_chain, | ||
484 | unsigned int c_count, | ||
485 | struct GNUNET_CREDENTIAL_Credential *cred) | ||
486 | { | ||
487 | |||
488 | struct RequestHandle *handle = cls; | ||
489 | struct MHD_Response *resp; | ||
490 | struct GNUNET_JSONAPI_Document *json_document; | ||
491 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
492 | json_t *cred_obj; | ||
493 | json_t *attr_obj; | ||
494 | json_t *cred_array; | ||
495 | json_t *attr_array; | ||
496 | char *result; | ||
497 | char *issuer; | ||
498 | char *id; | ||
499 | uint32_t i; | ||
500 | |||
501 | handle->verify_request = NULL; | ||
502 | if (NULL == cred) { | ||
503 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
504 | "Verify failed.\n"); | ||
505 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
506 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
507 | return; | ||
508 | } | ||
509 | issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key); | ||
510 | if (NULL == issuer) | ||
511 | { | ||
512 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
513 | "Issuer in delegation malformed\n"); | ||
514 | return; | ||
515 | } | ||
516 | GNUNET_asprintf (&id, | ||
517 | "%s.%s", | ||
518 | issuer, | ||
519 | handle->issuer_attr); | ||
520 | GNUNET_free (issuer); | ||
521 | json_document = GNUNET_JSONAPI_document_new (); | ||
522 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO, | ||
523 | id); | ||
524 | GNUNET_free (id); | ||
525 | attr_array = json_array (); | ||
526 | for (i = 0; i < d_count; i++) | ||
527 | { | ||
528 | attr_obj = attribute_delegation_to_json (&delegation_chain[i]); | ||
529 | json_array_append_new (attr_array, attr_obj); | ||
530 | } | ||
531 | cred_array = json_array (); | ||
532 | for (i=0;i<c_count;i++) | ||
533 | { | ||
534 | cred_obj = credential_to_json (&cred[i]); | ||
535 | json_array_append_new (cred_array, cred_obj); | ||
536 | } | ||
537 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
538 | GNUNET_REST_JSONAPI_CREDENTIAL, | ||
539 | cred_array); | ||
540 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
541 | GNUNET_REST_JSONAPI_DELEGATIONS, | ||
542 | attr_array); | ||
543 | GNUNET_JSONAPI_document_resource_add (json_document, json_resource); | ||
544 | GNUNET_JSONAPI_document_serialize (json_document, &result); | ||
545 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
546 | "Result %s\n", | ||
547 | result); | ||
548 | json_decref (attr_array); | ||
549 | json_decref (cred_array); | ||
550 | GNUNET_JSONAPI_document_delete (json_document); | ||
551 | resp = GNUNET_REST_create_response (result); | ||
552 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
553 | GNUNET_free (result); | ||
554 | cleanup_handle (handle); | ||
555 | } | ||
556 | |||
557 | static void | ||
558 | collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, | ||
559 | const char* url, | ||
560 | void *cls) | ||
561 | { | ||
562 | struct RequestHandle *handle = cls; | ||
563 | struct GNUNET_HashCode key; | ||
564 | char *tmp; | ||
565 | char *entity_attr; | ||
566 | |||
567 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
568 | "Connecting...\n"); | ||
569 | handle->credential = GNUNET_CREDENTIAL_connect (cfg); | ||
570 | handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
571 | &do_error, handle); | ||
572 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
573 | "Connected\n"); | ||
574 | if (NULL == handle->credential) | ||
575 | { | ||
576 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
577 | "Connecting to CREDENTIAL failed\n"); | ||
578 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
579 | return; | ||
580 | } | ||
581 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR, | ||
582 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR), | ||
583 | &key); | ||
584 | if ( GNUNET_NO == | ||
585 | GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, | ||
586 | &key) ) | ||
587 | { | ||
588 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
589 | "Missing issuer attribute\n"); | ||
590 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
591 | return; | ||
592 | } | ||
593 | tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, | ||
594 | &key); | ||
595 | entity_attr = GNUNET_strdup (tmp); | ||
596 | tmp = strtok(entity_attr, "."); | ||
597 | if (NULL == tmp) | ||
598 | { | ||
599 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
600 | "Malformed issuer or attribute\n"); | ||
601 | GNUNET_free (entity_attr); | ||
602 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
603 | return; | ||
604 | } | ||
605 | if (GNUNET_OK != | ||
606 | GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, | ||
607 | strlen (tmp), | ||
608 | &handle->issuer_key)) | ||
609 | { | ||
610 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
611 | "Malformed issuer key\n"); | ||
612 | GNUNET_free (entity_attr); | ||
613 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
614 | return; | ||
615 | } | ||
616 | tmp = strtok (NULL, "."); //Issuer attribute | ||
617 | if (NULL == tmp) | ||
618 | { | ||
619 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
620 | "Malformed attribute\n"); | ||
621 | GNUNET_free (entity_attr); | ||
622 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
623 | return; | ||
624 | } | ||
625 | handle->issuer_attr = GNUNET_strdup (tmp); | ||
626 | GNUNET_free (entity_attr); | ||
627 | |||
628 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO, | ||
629 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO), | ||
630 | &key); | ||
631 | if ( GNUNET_NO == | ||
632 | GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, | ||
633 | &key) ) | ||
634 | { | ||
635 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
636 | "Missing subject\n"); | ||
637 | GNUNET_free (entity_attr); | ||
638 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
639 | return; | ||
640 | } | ||
641 | tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, | ||
642 | &key); | ||
643 | if (NULL == tmp) | ||
644 | { | ||
645 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
646 | "Malformed subject\n"); | ||
647 | GNUNET_free (entity_attr); | ||
648 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
649 | return; | ||
650 | } | ||
651 | handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg, | ||
652 | tmp, | ||
653 | &subject_ego_lookup, | ||
654 | handle); | ||
655 | } | ||
656 | |||
657 | |||
658 | |||
659 | static void | ||
660 | verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, | ||
661 | const char* url, | ||
662 | void *cls) | ||
663 | { | ||
664 | struct RequestHandle *handle = cls; | ||
665 | struct GNUNET_HashCode key; | ||
666 | struct GNUNET_JSONAPI_Document *json_obj; | ||
667 | struct GNUNET_JSONAPI_Resource *res; | ||
668 | struct GNUNET_CREDENTIAL_Credential *cred; | ||
669 | char *tmp; | ||
670 | char *entity_attr; | ||
671 | int i; | ||
672 | uint32_t credential_count; | ||
673 | uint32_t resource_count; | ||
674 | json_t *cred_json; | ||
675 | json_t *data_js; | ||
676 | json_error_t err; | ||
677 | |||
678 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
679 | "Connecting...\n"); | ||
680 | handle->credential = GNUNET_CREDENTIAL_connect (cfg); | ||
681 | handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
682 | &do_error, handle); | ||
683 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
684 | "Connected\n"); | ||
685 | if (NULL == handle->credential) | ||
686 | { | ||
687 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
688 | "Connecting to CREDENTIAL failed\n"); | ||
689 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
690 | return; | ||
691 | } | ||
692 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR, | ||
693 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR), | ||
694 | &key); | ||
695 | if ( GNUNET_NO == | ||
696 | GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, | ||
697 | &key) ) | ||
698 | { | ||
699 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
700 | "Missing issuer attribute\n"); | ||
701 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
702 | return; | ||
703 | } | ||
704 | tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, | ||
705 | &key); | ||
706 | entity_attr = GNUNET_strdup (tmp); | ||
707 | tmp = strtok(entity_attr, "."); | ||
708 | if (NULL == tmp) | ||
709 | { | ||
710 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
711 | "Malformed issuer or attribute\n"); | ||
712 | GNUNET_free (entity_attr); | ||
713 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
714 | return; | ||
715 | } | ||
716 | if (GNUNET_OK != | ||
717 | GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, | ||
718 | strlen (tmp), | ||
719 | &handle->issuer_key)) | ||
720 | { | ||
721 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
722 | "Malformed issuer key\n"); | ||
723 | GNUNET_free (entity_attr); | ||
724 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
725 | return; | ||
726 | } | ||
727 | tmp = strtok (NULL, "."); //Issuer attribute | ||
728 | if (NULL == tmp) | ||
729 | { | ||
730 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
731 | "Malformed attribute\n"); | ||
732 | GNUNET_free (entity_attr); | ||
733 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
734 | return; | ||
735 | } | ||
736 | handle->issuer_attr = GNUNET_strdup (tmp); | ||
737 | GNUNET_free (entity_attr); | ||
738 | |||
739 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY, | ||
740 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY), | ||
741 | &key); | ||
742 | if ( GNUNET_NO == | ||
743 | GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, | ||
744 | &key) ) | ||
745 | { | ||
746 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
747 | "Missing subject key\n"); | ||
748 | GNUNET_free (entity_attr); | ||
749 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
750 | return; | ||
751 | } | ||
752 | tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, | ||
753 | &key); | ||
754 | if (NULL == tmp) | ||
755 | { | ||
756 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
757 | "Malformed subject\n"); | ||
758 | GNUNET_free (entity_attr); | ||
759 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
760 | return; | ||
761 | } | ||
762 | if (GNUNET_OK != | ||
763 | GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, | ||
764 | strlen (tmp), | ||
765 | &handle->subject_key)) { | ||
766 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
767 | "Malformed subject key\n"); | ||
768 | GNUNET_free (entity_attr); | ||
769 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
770 | return; | ||
771 | } | ||
772 | |||
773 | if (0 >= handle->rest_handle->data_size) | ||
774 | { | ||
775 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
776 | "Missing credentials\n"); | ||
777 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
778 | return; | ||
779 | } | ||
780 | |||
781 | struct GNUNET_JSON_Specification docspec[] = { | ||
782 | GNUNET_JSON_spec_jsonapi_document (&json_obj), | ||
783 | GNUNET_JSON_spec_end() | ||
784 | }; | ||
785 | char term_data[handle->rest_handle->data_size+1]; | ||
786 | term_data[handle->rest_handle->data_size] = '\0'; | ||
787 | credential_count = 0; | ||
788 | GNUNET_memcpy (term_data, | ||
789 | handle->rest_handle->data, | ||
790 | handle->rest_handle->data_size); | ||
791 | data_js = json_loads (term_data, | ||
792 | JSON_DECODE_ANY, | ||
793 | &err); | ||
794 | GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec, | ||
795 | NULL, NULL)); | ||
796 | json_decref (data_js); | ||
797 | if (NULL == json_obj) | ||
798 | { | ||
799 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
800 | "Unable to parse JSONAPI Object from %s\n", | ||
801 | term_data); | ||
802 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
803 | return; | ||
804 | } | ||
805 | |||
806 | resource_count = GNUNET_JSONAPI_document_resource_count(json_obj); | ||
807 | GNUNET_assert (1 == resource_count); | ||
808 | res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0)); | ||
809 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res, | ||
810 | GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO)) | ||
811 | { | ||
812 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
813 | "Resource not a credential!\n"); | ||
814 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
815 | "Unable to parse JSONAPI Object from %s\n", | ||
816 | term_data); | ||
817 | GNUNET_JSONAPI_document_delete (json_obj); | ||
818 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
819 | return; | ||
820 | } | ||
821 | cred_json = GNUNET_JSONAPI_resource_read_attr (res, | ||
822 | GNUNET_REST_JSONAPI_CREDENTIAL); | ||
823 | |||
824 | GNUNET_assert (json_is_array (cred_json)); | ||
825 | |||
826 | credential_count = json_array_size(cred_json); | ||
827 | |||
828 | struct GNUNET_CREDENTIAL_Credential credentials[credential_count]; | ||
829 | for (i=0;i<credential_count;i++) | ||
830 | { | ||
831 | cred = json_to_credential (json_array_get (cred_json, i)); | ||
832 | if (NULL == cred) | ||
833 | { | ||
834 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
835 | "Unable to parse credential!\n"); | ||
836 | continue; | ||
837 | } | ||
838 | GNUNET_memcpy (&credentials[i], | ||
839 | cred, | ||
840 | sizeof (struct GNUNET_CREDENTIAL_Credential)); | ||
841 | credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute); | ||
842 | GNUNET_free (cred); | ||
843 | } | ||
844 | GNUNET_JSONAPI_document_delete(json_obj); | ||
845 | handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential, | ||
846 | &handle->issuer_key, | ||
847 | handle->issuer_attr, | ||
848 | &handle->subject_key, | ||
849 | credential_count, | ||
850 | credentials, | ||
851 | &handle_verify_response, | ||
852 | handle); | ||
853 | for (i=0;i<credential_count;i++) | ||
854 | GNUNET_free ((char*)credentials[i].issuer_attribute); | ||
855 | |||
856 | } | ||
857 | |||
858 | void | ||
859 | send_cred_response (struct RequestHandle *handle, | ||
860 | struct GNUNET_CREDENTIAL_Credential *cred) | ||
861 | { | ||
862 | struct MHD_Response *resp; | ||
863 | struct GNUNET_JSONAPI_Document *json_document; | ||
864 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
865 | json_t *cred_obj; | ||
866 | char *result; | ||
867 | char *issuer; | ||
868 | char *subject; | ||
869 | char *signature; | ||
870 | char *id; | ||
871 | |||
872 | GNUNET_assert (NULL != cred); | ||
873 | issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key); | ||
874 | if (NULL == issuer) | ||
875 | { | ||
876 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
877 | "Subject malformed\n"); | ||
878 | return; | ||
879 | } | ||
880 | GNUNET_asprintf (&id, | ||
881 | "%s.%s", | ||
882 | issuer, | ||
883 | (char*)&cred[1]); | ||
884 | subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key); | ||
885 | if (NULL == subject) | ||
886 | { | ||
887 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
888 | "Subject malformed\n"); | ||
889 | return; | ||
890 | } | ||
891 | GNUNET_STRINGS_base64_encode ((char*)&cred->signature, | ||
892 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature), | ||
893 | &signature); | ||
894 | json_document = GNUNET_JSONAPI_document_new (); | ||
895 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO, | ||
896 | id); | ||
897 | GNUNET_free (id); | ||
898 | cred_obj = json_object(); | ||
899 | json_object_set_new (cred_obj, "issuer", json_string (issuer)); | ||
900 | json_object_set_new (cred_obj, "subject", json_string (subject)); | ||
901 | json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us)); | ||
902 | json_object_set_new (cred_obj, "signature", json_string (signature)); | ||
903 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
904 | GNUNET_REST_JSONAPI_CREDENTIAL, | ||
905 | cred_obj); | ||
906 | GNUNET_JSONAPI_document_resource_add (json_document, json_resource); | ||
907 | GNUNET_JSONAPI_document_serialize (json_document, &result); | ||
908 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
909 | "Result %s\n", | ||
910 | result); | ||
911 | json_decref (cred_obj); | ||
912 | GNUNET_JSONAPI_document_delete (json_document); | ||
913 | resp = GNUNET_REST_create_response (result); | ||
914 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
915 | GNUNET_free (result); | ||
916 | GNUNET_free (signature); | ||
917 | GNUNET_free (issuer); | ||
918 | GNUNET_free (subject); | ||
919 | cleanup_handle (handle); | ||
920 | } | ||
921 | |||
922 | void | ||
923 | get_cred_issuer_cb (void *cls, | ||
924 | struct GNUNET_IDENTITY_Ego *ego, | ||
925 | void **ctx, | ||
926 | const char *name) | ||
927 | { | ||
928 | struct RequestHandle *handle = cls; | ||
929 | struct GNUNET_TIME_Absolute etime_abs; | ||
930 | struct GNUNET_TIME_Relative etime_rel; | ||
931 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key; | ||
932 | struct GNUNET_HashCode key; | ||
933 | struct GNUNET_CREDENTIAL_Credential *cred; | ||
934 | char* expiration_str; | ||
935 | char* tmp; | ||
936 | |||
937 | handle->id_op = NULL; | ||
938 | |||
939 | if (NULL == name) | ||
940 | { | ||
941 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
942 | "Issuer not configured!\n"); | ||
943 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
944 | return; | ||
945 | } | ||
946 | |||
947 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
948 | "Connecting to credential service...\n"); | ||
949 | handle->credential = GNUNET_CREDENTIAL_connect (cfg); | ||
950 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
951 | "Connected\n"); | ||
952 | if (NULL == handle->credential) | ||
953 | { | ||
954 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
955 | "Connecting to CREDENTIAL failed\n"); | ||
956 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
957 | return; | ||
958 | } | ||
959 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION, | ||
960 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION), | ||
961 | &key); | ||
962 | if ( GNUNET_NO == | ||
963 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
964 | &key) ) | ||
965 | { | ||
966 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
967 | "Missing expiration\n"); | ||
968 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
969 | return; | ||
970 | } | ||
971 | expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | ||
972 | &key); | ||
973 | if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str, | ||
974 | &etime_rel)) | ||
975 | { | ||
976 | etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel); | ||
977 | } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str, | ||
978 | &etime_abs)) | ||
979 | { | ||
980 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
981 | "Malformed expiration: %s\n", expiration_str); | ||
982 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
983 | return; | ||
984 | } | ||
985 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR, | ||
986 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR), | ||
987 | &key); | ||
988 | if ( GNUNET_NO == | ||
989 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
990 | &key) ) | ||
991 | { | ||
992 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
993 | "Missing issuer attribute\n"); | ||
994 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
995 | return; | ||
996 | } | ||
997 | handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get | ||
998 | (handle->rest_handle->url_param_map, | ||
999 | &key)); | ||
1000 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY, | ||
1001 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY), | ||
1002 | &key); | ||
1003 | if ( GNUNET_NO == | ||
1004 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1005 | &key) ) | ||
1006 | { | ||
1007 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1008 | "Missing subject\n"); | ||
1009 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1010 | return; | ||
1011 | } | ||
1012 | tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | ||
1013 | &key); | ||
1014 | if (NULL == tmp) | ||
1015 | { | ||
1016 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1017 | "Malformed subject\n"); | ||
1018 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1019 | return; | ||
1020 | } | ||
1021 | if (GNUNET_OK != | ||
1022 | GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, | ||
1023 | strlen (tmp), | ||
1024 | &handle->subject_key)) { | ||
1025 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1026 | "Malformed subject key\n"); | ||
1027 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1028 | return; | ||
1029 | } | ||
1030 | issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
1031 | cred = GNUNET_CREDENTIAL_credential_issue (issuer_key, | ||
1032 | &handle->subject_key, | ||
1033 | handle->issuer_attr, | ||
1034 | &etime_abs); | ||
1035 | if (NULL == cred) | ||
1036 | { | ||
1037 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1038 | "Failed to create credential\n"); | ||
1039 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1040 | return; | ||
1041 | } | ||
1042 | send_cred_response (handle, cred); | ||
1043 | } | ||
1044 | |||
1045 | |||
1046 | static void | ||
1047 | issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, | ||
1048 | const char* url, | ||
1049 | void *cls) | ||
1050 | { | ||
1051 | struct RequestHandle *handle = cls; | ||
1052 | |||
1053 | handle->identity = GNUNET_IDENTITY_connect (cfg, | ||
1054 | NULL, | ||
1055 | NULL); | ||
1056 | handle->id_op = GNUNET_IDENTITY_get(handle->identity, | ||
1057 | "credential-issuer", | ||
1058 | &get_cred_issuer_cb, | ||
1059 | handle); | ||
1060 | handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
1061 | &do_error, | ||
1062 | handle); | ||
1063 | } | ||
1064 | |||
1065 | /** | ||
1066 | * Handle rest request | ||
1067 | * | ||
1068 | * @param handle the lookup handle | ||
1069 | */ | ||
1070 | static void | ||
1071 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
1072 | const char* url, | ||
1073 | void *cls) | ||
1074 | { | ||
1075 | struct MHD_Response *resp; | ||
1076 | struct RequestHandle *handle = cls; | ||
1077 | |||
1078 | //For GNS, independent of path return all options | ||
1079 | resp = GNUNET_REST_create_response (NULL); | ||
1080 | MHD_add_response_header (resp, | ||
1081 | "Access-Control-Allow-Methods", | ||
1082 | MHD_HTTP_METHOD_GET); | ||
1083 | handle->proc (handle->proc_cls, | ||
1084 | resp, | ||
1085 | MHD_HTTP_OK); | ||
1086 | cleanup_handle (handle); | ||
1087 | } | ||
1088 | |||
1089 | |||
1090 | /** | ||
1091 | * Function processing the REST call | ||
1092 | * | ||
1093 | * @param method HTTP method | ||
1094 | * @param url URL of the HTTP request | ||
1095 | * @param data body of the HTTP request (optional) | ||
1096 | * @param data_size length of the body | ||
1097 | * @param proc callback function for the result | ||
1098 | * @param proc_cls closure for callback function | ||
1099 | * @return GNUNET_OK if request accepted | ||
1100 | */ | ||
1101 | static void | ||
1102 | rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, | ||
1103 | GNUNET_REST_ResultProcessor proc, | ||
1104 | void *proc_cls) | ||
1105 | { | ||
1106 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
1107 | struct GNUNET_REST_RequestHandlerError err; | ||
1108 | |||
1109 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
1110 | handle->proc_cls = proc_cls; | ||
1111 | handle->proc = proc; | ||
1112 | handle->rest_handle = conndata_handle; | ||
1113 | |||
1114 | static const struct GNUNET_REST_RequestHandler handlers[] = { | ||
1115 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont}, | ||
1116 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont}, | ||
1117 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont}, | ||
1118 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont}, | ||
1119 | GNUNET_REST_HANDLER_END | ||
1120 | }; | ||
1121 | |||
1122 | if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle, | ||
1123 | handlers, | ||
1124 | &err, | ||
1125 | handle)) | ||
1126 | { | ||
1127 | handle->response_code = err.error_code; | ||
1128 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1132 | |||
1133 | /** | ||
1134 | * Entry point for the plugin. | ||
1135 | * | ||
1136 | * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" | ||
1137 | * @return NULL on error, otherwise the plugin context | ||
1138 | */ | ||
1139 | void * | ||
1140 | libgnunet_plugin_rest_credential_init (void *cls) | ||
1141 | { | ||
1142 | static struct Plugin plugin; | ||
1143 | cfg = cls; | ||
1144 | struct GNUNET_REST_Plugin *api; | ||
1145 | |||
1146 | if (NULL != plugin.cfg) | ||
1147 | return NULL; /* can only initialize once! */ | ||
1148 | memset (&plugin, 0, sizeof (struct Plugin)); | ||
1149 | plugin.cfg = cfg; | ||
1150 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
1151 | api->cls = &plugin; | ||
1152 | api->name = GNUNET_REST_API_NS_CREDENTIAL; | ||
1153 | api->process_request = &rest_credential_process_request; | ||
1154 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1155 | _("GNS REST API initialized\n")); | ||
1156 | return api; | ||
1157 | } | ||
1158 | |||
1159 | |||
1160 | /** | ||
1161 | * Exit point from the plugin. | ||
1162 | * | ||
1163 | * @param cls the plugin context (as returned by "init") | ||
1164 | * @return always NULL | ||
1165 | */ | ||
1166 | void * | ||
1167 | libgnunet_plugin_rest_credential_done (void *cls) | ||
1168 | { | ||
1169 | struct GNUNET_REST_Plugin *api = cls; | ||
1170 | struct Plugin *plugin = api->cls; | ||
1171 | |||
1172 | plugin->cfg = NULL; | ||
1173 | GNUNET_free (api); | ||
1174 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1175 | "GNS REST plugin is finished\n"); | ||
1176 | return NULL; | ||
1177 | } | ||
1178 | |||
1179 | /* end of plugin_rest_gns.c */ | ||
diff --git a/src/credential/test_credential_collect.sh b/src/credential/test_credential_collect.sh new file mode 100755 index 000000000..6c713063f --- /dev/null +++ b/src/credential/test_credential_collect.sh | |||
@@ -0,0 +1,47 @@ | |||
1 | #!/bin/bash | ||
2 | trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | TEST_ATTR2="test2" | ||
27 | gnunet-arm -s -c test_credential_lookup.conf | ||
28 | gnunet-identity -C testissuer -c test_credential_lookup.conf | ||
29 | gnunet-identity -C testsubject -c test_credential_lookup.conf | ||
30 | SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}') | ||
31 | ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}') | ||
32 | #TODO1 Get credential and store it with subject (3) | ||
33 | CRED=`$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 | ||
35 | CRED=`$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 | ||
37 | CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste -d, -s` | ||
38 | echo $CREDS | ||
39 | RES=$? | ||
40 | gnunet-arm -e -c test_credential_lookup.conf | ||
41 | |||
42 | if test $? != 0 | ||
43 | then | ||
44 | echo "Error collecting..." | ||
45 | exit 1 | ||
46 | fi | ||
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 | ||
2 | trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
25 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
26 | gnunet-arm -s -c test_credential_lookup.conf | ||
27 | gnunet-identity -C service -c test_credential_lookup.conf | ||
28 | gnunet-identity -C alice -c test_credential_lookup.conf | ||
29 | gnunet-identity -C gnu -c test_credential_lookup.conf | ||
30 | gnunet-identity -C gnunet -c test_credential_lookup.conf | ||
31 | |||
32 | GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}') | ||
33 | ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}') | ||
34 | GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}') | ||
35 | SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}') | ||
36 | |||
37 | USER_ATTR="user" | ||
38 | GNU_PROJECT_ATTR="project" | ||
39 | MEMBER_ATTR="member" | ||
40 | DEVELOPER_ATTR="developer" | ||
41 | DEV_ATTR="developer" | ||
42 | TEST_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 | ||
45 | gnunet-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 | ||
48 | gnunet-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" | ||
51 | gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf | ||
52 | gnunet-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" | ||
55 | CRED=`$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" | ||
58 | gnunet-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" | ||
61 | CRED=`$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" | ||
64 | gnunet-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 | |||
69 | gnunet-arm -i rest -c test_credential_lookup.conf | ||
70 | |||
71 | sleep 5 | ||
72 | |||
73 | curl -v "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice" | ||
74 | |||
75 | #TODO cleanup properly | ||
76 | gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf | ||
77 | gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf | ||
78 | gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf | ||
79 | gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf | ||
80 | echo "Stopping arm..." | ||
81 | gnunet-arm -e -c test_credential_lookup.conf | ||
82 | echo "Done" | ||
83 | if [ "$RES_CRED" != "Failed." ] | ||
84 | then | ||
85 | echo -e "${RES_CRED}" | ||
86 | exit 0 | ||
87 | else | ||
88 | echo "FAIL: Failed to verify credential $RES_CRED." | ||
89 | exit 1 | ||
90 | fi | ||
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] | ||
4 | GNUNET_TEST_HOME = /tmp/test-gnunet-credential-testing/ | ||
5 | |||
6 | [namestore-sqlite] | ||
7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | ||
8 | |||
9 | [namecache-sqlite] | ||
10 | FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db | ||
11 | |||
12 | [identity] | ||
13 | # Directory where we store information about our egos | ||
14 | EGODIR = $GNUNET_TEST_HOME/identity/egos/ | ||
15 | |||
16 | [dhtcache] | ||
17 | DATABASE = heap | ||
18 | |||
19 | [transport] | ||
20 | PLUGINS = tcp | ||
21 | |||
22 | [transport-tcp] | ||
23 | BINDTO = 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 | ||
2 | trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_credential_lookup.conf | ||
27 | gnunet-identity -C testissuer -c test_credential_lookup.conf | ||
28 | gnunet-identity -C testsubject -c test_credential_lookup.conf | ||
29 | SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}') | ||
30 | ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}') | ||
31 | #TODO1 Get credential and store it with subject (3) | ||
32 | CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf` | ||
33 | STATUS=$? | ||
34 | |||
35 | if test $? != 0 | ||
36 | then | ||
37 | echo "Error issuing..." | ||
38 | exit 1 | ||
39 | fi | ||
40 | #Try import | ||
41 | $DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf | ||
42 | RES=$? | ||
43 | gnunet-arm -e -c test_credential_lookup.conf | ||
44 | exit $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 | ||
2 | trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_credential_lookup.conf | ||
27 | gnunet-arm -i gns | ||
28 | gnunet-arm -i credential | ||
29 | gnunet-arm -i identity | ||
30 | gnunet-arm -i rest -c test_credential_lookup.conf | ||
31 | |||
32 | gnunet-arm -I -c test_credential_lookup.conf | ||
33 | gnunet-identity -C testissuer -c test_credential_lookup.conf | ||
34 | gnunet-identity -C testsubject -c test_credential_lookup.conf | ||
35 | gnunet-identity -s credential-issuer -e testissuer | ||
36 | SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}') | ||
37 | ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}') | ||
38 | #TODO1 Get credential and store it with subject (3) | ||
39 | sleep 5 | ||
40 | curl "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` | ||
42 | STATUS=$? | ||
43 | |||
44 | if test $? != 0 | ||
45 | then | ||
46 | echo "Error issuing..." | ||
47 | exit 1 | ||
48 | fi | ||
49 | #Try import | ||
50 | #$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf | ||
51 | RES=$? | ||
52 | gnunet-arm -e -c test_credential_lookup.conf | ||
53 | exit $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] | ||
4 | GNUNET_TEST_HOME = /tmp/test-gnunet-credential-peer-1/ | ||
5 | |||
6 | [dht] | ||
7 | AUTOSTART = YES | ||
8 | |||
9 | [transport] | ||
10 | PLUGINS = | ||
11 | |||
12 | [credential] | ||
13 | AUTOSTART = YES | ||
14 | PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog | ||
15 | |||
16 | [rest] | ||
17 | PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog | ||
18 | |||
19 | [gns] | ||
20 | #PREFIX = valgrind --leak-check=full --track-origins=yes | ||
21 | AUTOSTART = YES | ||
22 | AUTO_IMPORT_PKEY = YES | ||
23 | MAX_PARALLEL_BACKGROUND_QUERIES = 10 | ||
24 | DEFAULT_LOOKUP_TIMEOUT = 15 s | ||
25 | RECORD_PUT_INTERVAL = 1 h | ||
26 | ZONE_PUBLISH_TIME_WINDOW = 1 h | ||
27 | DNS_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 | ||
2 | trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
25 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
26 | gnunet-arm -s -c test_credential_lookup.conf | ||
27 | gnunet-identity -C service -c test_credential_lookup.conf | ||
28 | gnunet-identity -C alice -c test_credential_lookup.conf | ||
29 | gnunet-identity -C gnu -c test_credential_lookup.conf | ||
30 | gnunet-identity -C gnunet -c test_credential_lookup.conf | ||
31 | |||
32 | GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}') | ||
33 | ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}') | ||
34 | GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}') | ||
35 | SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}') | ||
36 | |||
37 | USER_ATTR="user" | ||
38 | GNU_PROJECT_ATTR="project" | ||
39 | MEMBER_ATTR="member" | ||
40 | DEVELOPER_ATTR="developer" | ||
41 | DEV_ATTR="developer" | ||
42 | TEST_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 | ||
45 | gnunet-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 | ||
48 | gnunet-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" | ||
51 | gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf | ||
52 | gnunet-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" | ||
55 | CRED=`$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" | ||
58 | gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf | ||
59 | |||
60 | CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s` | ||
61 | |||
62 | echo 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 | ||
64 | 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 | ||
68 | gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf | ||
69 | gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf | ||
70 | gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf | ||
71 | gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf | ||
72 | gnunet-arm -e -c test_credential_lookup.conf | ||
73 | |||
74 | if [ "$RES_CRED" != "Failed." ] | ||
75 | then | ||
76 | echo -e "${RES_CRED}" | ||
77 | exit 0 | ||
78 | else | ||
79 | echo "FAIL: Failed to verify credential $RES_CRED." | ||
80 | exit 1 | ||
81 | fi | ||
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 | ||
2 | trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
25 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
26 | gnunet-arm -s -c test_credential_lookup.conf | ||
27 | gnunet-identity -C service -c test_credential_lookup.conf | ||
28 | gnunet-identity -C alice -c test_credential_lookup.conf | ||
29 | gnunet-identity -C gnu -c test_credential_lookup.conf | ||
30 | gnunet-identity -C gnunet -c test_credential_lookup.conf | ||
31 | |||
32 | GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}') | ||
33 | ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}') | ||
34 | GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}') | ||
35 | SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}') | ||
36 | |||
37 | USER_ATTR="user" | ||
38 | GNU_PROJECT_ATTR="project" | ||
39 | MEMBER_ATTR="member" | ||
40 | DEVELOPER_ATTR="developer" | ||
41 | DEV_ATTR="developer" | ||
42 | TEST_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 | ||
45 | gnunet-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 | ||
48 | gnunet-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" | ||
51 | gnunet-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" | ||
54 | CRED1=`$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" | ||
56 | CRED2=`$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" | ||
58 | gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED1" -e 5m -c test_credential_lookup.conf | ||
59 | gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m -c test_credential_lookup.conf | ||
60 | |||
61 | CREDS=`$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 | ||
64 | RES_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 | ||
68 | gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf | ||
69 | gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf | ||
70 | gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf | ||
71 | gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf | ||
72 | gnunet-arm -e -c test_credential_lookup.conf | ||
73 | |||
74 | if [ "$RES_CRED" != "Failed." ] | ||
75 | then | ||
76 | echo -e "${RES_CRED}" | ||
77 | exit 0 | ||
78 | else | ||
79 | echo "FAIL: Failed to verify credential $RES_CRED." | ||
80 | exit 1 | ||
81 | fi | ||
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 | ||
2 | trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
25 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
26 | gnunet-arm -s -c test_credential_lookup.conf | ||
27 | gnunet-identity -C service -c test_credential_lookup.conf | ||
28 | gnunet-identity -C alice -c test_credential_lookup.conf | ||
29 | gnunet-identity -C gnu -c test_credential_lookup.conf | ||
30 | gnunet-identity -C gnunet -c test_credential_lookup.conf | ||
31 | |||
32 | GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}') | ||
33 | ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}') | ||
34 | GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}') | ||
35 | SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}') | ||
36 | |||
37 | USER_ATTR="user" | ||
38 | GNU_PROJECT_ATTR="project" | ||
39 | MEMBER_ATTR="member" | ||
40 | DEVELOPER_ATTR="developer" | ||
41 | DEV_ATTR="developer" | ||
42 | TEST_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 | ||
45 | gnunet-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 | ||
48 | gnunet-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" | ||
51 | gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf | ||
52 | gnunet-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" | ||
55 | CRED=`$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" | ||
58 | gnunet-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 | |||
63 | gnunet-arm -i rest -c test_credential_lookup.conf | ||
64 | |||
65 | sleep 5 | ||
66 | |||
67 | CREDS=`curl "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"` | ||
68 | |||
69 | echo $CREDS | ||
70 | |||
71 | curl -v "localhost:7776/credential/verify?attribute=$SERVICE_KEY.$USER_ATTR&subject_key=$ALICE_KEY" --data "$CREDS" | ||
72 | |||
73 | #TODO cleanup properly | ||
74 | gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf | ||
75 | gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf | ||
76 | gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf | ||
77 | gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf | ||
78 | gnunet-arm -e -c test_credential_lookup.conf | ||
79 | |||
80 | if [ "$RES_CRED" != "Failed." ] | ||
81 | then | ||
82 | echo -e "${RES_CRED}" | ||
83 | exit 0 | ||
84 | else | ||
85 | echo "FAIL: Failed to verify credential $RES_CRED." | ||
86 | exit 1 | ||
87 | fi | ||
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 | ||
2 | trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f` | ||
17 | |||
18 | # (3) Isser.user -> Subject | ||
19 | |||
20 | |||
21 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
22 | gnunet-arm -s -c test_credential_lookup.conf | ||
23 | gnunet-identity -C testissuer -c test_credential_lookup.conf | ||
24 | gnunet-identity -C testsubject -c test_credential_lookup.conf | ||
25 | |||
26 | TEST_ATTR="user" | ||
27 | SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}') | ||
28 | ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}') | ||
29 | CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf` | ||
30 | |||
31 | TEST_CREDENTIAL="t1" | ||
32 | gnunet-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` | ||
36 | RES_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 | ||
39 | gnunet-namestore -z testsubject -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf | ||
40 | gnunet-identity -D testsubject -c test_credential_lookup.conf | ||
41 | gnunet-arm -e -c test_credential_lookup.conf | ||
42 | echo $RES_CRED | ||
43 | #TODO3 proper test | ||
44 | if [ "$RES_CRED" == "Successful." ] | ||
45 | then | ||
46 | exit 0 | ||
47 | else | ||
48 | echo "FAIL: Failed to verify credential." | ||
49 | exit 1 | ||
50 | fi | ||
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 | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | plugindir = $(libdir)/gnunet | ||
5 | |||
6 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
7 | |||
8 | libexecdir= $(pkglibdir)/libexec/ | ||
9 | |||
10 | if MINGW | ||
11 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
12 | endif | ||
13 | |||
14 | if USE_COVERAGE | ||
15 | AM_CFLAGS = --coverage -O0 | ||
16 | XLIBS = -lgcov | ||
17 | endif | ||
18 | |||
19 | lib_LTLIBRARIES = \ | ||
20 | libgnunetidentityattribute.la | ||
21 | |||
22 | libgnunetidentityattribute_la_SOURCES = \ | ||
23 | identity_attribute.c | ||
24 | libgnunetidentityattribute_la_LIBADD = \ | ||
25 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
26 | $(GN_LIBINTL) | ||
27 | libgnunetidentityattribute_la_LDFLAGS = \ | ||
28 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
29 | -version-info 0:0:0 | ||
30 | |||
31 | |||
32 | plugin_LTLIBRARIES = \ | ||
33 | libgnunet_plugin_identity_attribute_gnuid.la | ||
34 | |||
35 | |||
36 | libgnunet_plugin_identity_attribute_gnuid_la_SOURCES = \ | ||
37 | plugin_identity_attribute_gnuid.c | ||
38 | libgnunet_plugin_identity_attribute_gnuid_la_LIBADD = \ | ||
39 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
40 | $(LTLIBINTL) | ||
41 | libgnunet_plugin_identity_attribute_gnuid_la_LDFLAGS = \ | ||
42 | $(GN_PLUGIN_LDFLAGS) | ||
43 | |||
44 | |||
diff --git a/src/identity-attribute/identity_attribute.c b/src/identity-attribute/identity_attribute.c new file mode 100644 index 000000000..a8aae6ced --- /dev/null +++ b/src/identity-attribute/identity_attribute.c | |||
@@ -0,0 +1,421 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2010-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file identity-provider/identity_attribute.c | ||
23 | * @brief helper library to manage identity attributes | ||
24 | * @author Martin Schanzenbach | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "identity_attribute.h" | ||
29 | #include "gnunet_identity_attribute_plugin.h" | ||
30 | |||
31 | /** | ||
32 | * Handle for a plugin | ||
33 | */ | ||
34 | struct 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 | */ | ||
50 | static struct Plugin **attr_plugins; | ||
51 | |||
52 | /** | ||
53 | * Number of plugins | ||
54 | */ | ||
55 | static unsigned int num_plugins; | ||
56 | |||
57 | /** | ||
58 | * Init canary | ||
59 | */ | ||
60 | static int initialized; | ||
61 | |||
62 | /** | ||
63 | * Add a plugin | ||
64 | */ | ||
65 | static void | ||
66 | add_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 | */ | ||
85 | static void | ||
86 | init() | ||
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 | */ | ||
101 | uint32_t | ||
102 | GNUNET_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 | */ | ||
125 | const char* | ||
126 | GNUNET_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 | */ | ||
153 | int | ||
154 | GNUNET_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 | */ | ||
184 | char * | ||
185 | GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type, | ||
186 | const void* data, | ||
187 | size_t data_size) | ||
188 | { | ||
189 | unsigned int i; | ||
190 | struct Plugin *plugin; | ||
191 | char *ret; | ||
192 | |||
193 | init(); | ||
194 | for (i = 0; i < num_plugins; i++) | ||
195 | { | ||
196 | plugin = attr_plugins[i]; | ||
197 | if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls, | ||
198 | type, | ||
199 | data, | ||
200 | data_size))) | ||
201 | return ret; | ||
202 | } | ||
203 | return NULL; | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * Create a new attribute. | ||
208 | * | ||
209 | * @param name the attribute name | ||
210 | * @param type the attribute type | ||
211 | * @param data the attribute value | ||
212 | * @param data_size the attribute value size | ||
213 | * @return the new attribute | ||
214 | */ | ||
215 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim * | ||
216 | GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name, | ||
217 | uint32_t attr_type, | ||
218 | const void* data, | ||
219 | size_t data_size) | ||
220 | { | ||
221 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr; | ||
222 | char *write_ptr; | ||
223 | |||
224 | attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) + | ||
225 | strlen (attr_name) + 1 + | ||
226 | data_size); | ||
227 | attr->type = attr_type; | ||
228 | attr->data_size = data_size; | ||
229 | attr->version = 0; | ||
230 | write_ptr = (char*)&attr[1]; | ||
231 | GNUNET_memcpy (write_ptr, | ||
232 | attr_name, | ||
233 | strlen (attr_name) + 1); | ||
234 | attr->name = write_ptr; | ||
235 | write_ptr += strlen (attr->name) + 1; | ||
236 | GNUNET_memcpy (write_ptr, | ||
237 | data, | ||
238 | data_size); | ||
239 | attr->data = write_ptr; | ||
240 | return attr; | ||
241 | } | ||
242 | |||
243 | size_t | ||
244 | GNUNET_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 | |||
253 | size_t | ||
254 | GNUNET_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 | |||
274 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList * | ||
275 | GNUNET_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 | |||
305 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList* | ||
306 | GNUNET_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 | |||
331 | void | ||
332 | GNUNET_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 | |||
348 | size_t | ||
349 | GNUNET_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 | |||
356 | size_t | ||
357 | GNUNET_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 | |||
383 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim * | ||
384 | GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data, | ||
385 | size_t data_size) | ||
386 | { | ||
387 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr; | ||
388 | struct Attribute *attr_ser; | ||
389 | size_t data_len; | ||
390 | size_t name_len; | ||
391 | char* write_ptr; | ||
392 | |||
393 | if (data_size < sizeof (struct Attribute)) | ||
394 | return NULL; | ||
395 | |||
396 | attr_ser = (struct Attribute*)data; | ||
397 | data_len = ntohs (attr_ser->data_size); | ||
398 | name_len = ntohs (attr_ser->name_len); | ||
399 | attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) | ||
400 | + data_len + name_len + 1); | ||
401 | attr->type = ntohs (attr_ser->attribute_type); | ||
402 | attr->version = ntohl (attr_ser->attribute_version); | ||
403 | attr->data_size = ntohs (attr_ser->data_size); | ||
404 | |||
405 | write_ptr = (char*)&attr[1]; | ||
406 | GNUNET_memcpy (write_ptr, | ||
407 | &attr_ser[1], | ||
408 | name_len); | ||
409 | write_ptr[name_len] = '\0'; | ||
410 | attr->name = write_ptr; | ||
411 | |||
412 | write_ptr += name_len + 1; | ||
413 | GNUNET_memcpy (write_ptr, | ||
414 | (char*)&attr_ser[1] + name_len, | ||
415 | attr->data_size); | ||
416 | attr->data = write_ptr; | ||
417 | return attr; | ||
418 | |||
419 | } | ||
420 | |||
421 | /* end of identity_attribute.c */ | ||
diff --git a/src/identity-attribute/identity_attribute.h b/src/identity-attribute/identity_attribute.h new file mode 100644 index 000000000..046321807 --- /dev/null +++ b/src/identity-attribute/identity_attribute.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @author Martin Schanzenbach | ||
22 | * @file identity-provider/identity_attribute.h | ||
23 | * @brief GNUnet Identity Provider library | ||
24 | * | ||
25 | */ | ||
26 | #ifndef IDENTITY_ATTRIBUTE_H | ||
27 | #define IDENTITY_ATTRIBUTE_H | ||
28 | |||
29 | #include "gnunet_identity_provider_service.h" | ||
30 | |||
31 | struct Attribute | ||
32 | { | ||
33 | /** | ||
34 | * Attribute type | ||
35 | */ | ||
36 | uint32_t attribute_type; | ||
37 | |||
38 | /** | ||
39 | * Attribute version | ||
40 | */ | ||
41 | uint32_t attribute_version; | ||
42 | |||
43 | /** | ||
44 | * Name length | ||
45 | */ | ||
46 | uint32_t name_len; | ||
47 | |||
48 | /** | ||
49 | * Data size | ||
50 | */ | ||
51 | uint32_t data_size; | ||
52 | |||
53 | //followed by data_size Attribute value data | ||
54 | }; | ||
55 | |||
56 | #endif | ||
diff --git a/src/identity-attribute/plugin_identity_attribute_gnuid.c b/src/identity-attribute/plugin_identity_attribute_gnuid.c new file mode 100644 index 000000000..0ff44d199 --- /dev/null +++ b/src/identity-attribute/plugin_identity_attribute_gnuid.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2013, 2014, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file identity-provider/plugin_identity_attribute_gnuid.c | ||
23 | * @brief identity attribute plugin to provide the API for fundamental | ||
24 | * attribute types. | ||
25 | * | ||
26 | * @author Martin Schanzenbach | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_identity_attribute_plugin.h" | ||
31 | #include <inttypes.h> | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Convert the 'value' of an attribute to a string. | ||
36 | * | ||
37 | * @param cls closure, unused | ||
38 | * @param type type of the attribute | ||
39 | * @param data value in binary encoding | ||
40 | * @param data_size number of bytes in @a data | ||
41 | * @return NULL on error, otherwise human-readable representation of the value | ||
42 | */ | ||
43 | static char * | ||
44 | gnuid_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 | */ | ||
71 | static int | ||
72 | gnuid_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 | */ | ||
97 | static 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 | */ | ||
113 | static uint32_t | ||
114 | gnuid_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 | */ | ||
135 | static const char * | ||
136 | gnuid_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 | */ | ||
155 | void * | ||
156 | libgnunet_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 | */ | ||
175 | void * | ||
176 | libgnunet_plugin_identity_attribute_gnuid_done (void *cls) | ||
177 | { | ||
178 | struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = cls; | ||
179 | |||
180 | GNUNET_free (api); | ||
181 | return NULL; | ||
182 | } | ||
183 | |||
184 | /* end of plugin_identity_attribute_type_gnuid.c */ | ||
diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am index 0d8752c4c..5c5ddaa57 100644 --- a/src/identity-provider/Makefile.am +++ b/src/identity-provider/Makefile.am | |||
@@ -12,6 +12,15 @@ if USE_COVERAGE | |||
12 | XLIB = -lgcov | 12 | XLIB = -lgcov |
13 | endif | 13 | endif |
14 | 14 | ||
15 | if HAVE_SQLITE | ||
16 | SQLITE_PLUGIN = libgnunet_plugin_identity_provider_sqlite.la | ||
17 | endif | ||
18 | |||
19 | EXTRA_DIST = \ | ||
20 | test_idp_defaults.conf \ | ||
21 | test_idp.conf \ | ||
22 | $(check_SCRIPTS) | ||
23 | |||
15 | pkgcfgdir= $(pkgdatadir)/config.d/ | 24 | pkgcfgdir= $(pkgdatadir)/config.d/ |
16 | 25 | ||
17 | libexecdir= $(pkglibdir)/libexec/ | 26 | libexecdir= $(pkglibdir)/libexec/ |
@@ -22,29 +31,50 @@ pkgcfg_DATA = \ | |||
22 | lib_LTLIBRARIES = \ | 31 | lib_LTLIBRARIES = \ |
23 | libgnunetidentityprovider.la | 32 | libgnunetidentityprovider.la |
24 | plugin_LTLIBRARIES = \ | 33 | plugin_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 | ||
27 | bin_PROGRAMS = \ | 38 | bin_PROGRAMS = \ |
28 | gnunet-identity-token | 39 | gnunet-idp |
29 | 40 | ||
30 | libexec_PROGRAMS = \ | 41 | libexec_PROGRAMS = \ |
31 | gnunet-service-identity-provider | 42 | gnunet-service-identity-provider |
32 | 43 | ||
33 | EXTRA_DIST = \ | 44 | libgnunet_plugin_gnsrecord_identity_provider_la_SOURCES = \ |
34 | $(pkgcfg_DATA) | 45 | plugin_gnsrecord_identity_provider.c |
46 | libgnunet_plugin_gnsrecord_identity_provider_la_LIBADD = \ | ||
47 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
48 | $(LTLIBINTL) | ||
49 | libgnunet_plugin_gnsrecord_identity_provider_la_LDFLAGS = \ | ||
50 | $(GN_PLUGIN_LDFLAGS) | ||
51 | |||
52 | libgnunet_plugin_identity_provider_sqlite_la_SOURCES = \ | ||
53 | plugin_identity_provider_sqlite.c | ||
54 | libgnunet_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) | ||
60 | libgnunet_plugin_identity_provider_sqlite_la_LDFLAGS = \ | ||
61 | $(GN_PLUGIN_LDFLAGS) | ||
62 | |||
63 | |||
35 | 64 | ||
36 | gnunet_service_identity_provider_SOURCES = \ | 65 | gnunet_service_identity_provider_SOURCES = \ |
37 | gnunet-service-identity-provider.c \ | 66 | gnunet-service-identity-provider.c |
38 | identity_token.c identity_token.h | ||
39 | gnunet_service_identity_provider_LDADD = \ | 67 | gnunet_service_identity_provider_LDADD = \ |
40 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 68 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
41 | $(top_builddir)/src/util/libgnunetutil.la \ | 69 | $(top_builddir)/src/util/libgnunetutil.la \ |
42 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | 70 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ |
43 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 71 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
44 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 72 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
73 | $(top_builddir)/src/credential/libgnunetcredential.la \ | ||
74 | $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \ | ||
75 | libgnunetidentityprovider.la \ | ||
45 | $(top_builddir)/src/gns/libgnunetgns.la \ | 76 | $(top_builddir)/src/gns/libgnunetgns.la \ |
46 | $(GN_LIBINTL) \ | 77 | $(GN_LIBINTL) |
47 | -ljansson | ||
48 | 78 | ||
49 | libgnunetidentityprovider_la_SOURCES = \ | 79 | libgnunetidentityprovider_la_SOURCES = \ |
50 | identity_provider_api.c \ | 80 | identity_provider_api.c \ |
@@ -57,22 +87,37 @@ libgnunetidentityprovider_la_LDFLAGS = \ | |||
57 | -version-info 0:0:0 | 87 | -version-info 0:0:0 |
58 | 88 | ||
59 | libgnunet_plugin_rest_identity_provider_la_SOURCES = \ | 89 | libgnunet_plugin_rest_identity_provider_la_SOURCES = \ |
60 | plugin_rest_identity_provider.c | 90 | plugin_rest_identity_provider.c \ |
91 | jwt.c | ||
61 | libgnunet_plugin_rest_identity_provider_la_LIBADD = \ | 92 | libgnunet_plugin_rest_identity_provider_la_LIBADD = \ |
62 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 93 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
63 | libgnunetidentityprovider.la \ | 94 | libgnunetidentityprovider.la \ |
64 | $(top_builddir)/src/rest/libgnunetrest.la \ | 95 | $(top_builddir)/src/rest/libgnunetrest.la \ |
65 | $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ | 96 | $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ |
97 | $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \ | ||
66 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | 98 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ |
67 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | 99 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ |
68 | $(LTLIBINTL) -ljansson -lmicrohttpd | 100 | $(LTLIBINTL) -ljansson -lmicrohttpd |
69 | libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \ | 101 | libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \ |
70 | $(GN_PLUGIN_LDFLAGS) | 102 | $(GN_PLUGIN_LDFLAGS) |
71 | 103 | ||
72 | 104 | gnunet_idp_SOURCES = \ | |
73 | gnunet_identity_token_SOURCES = \ | 105 | gnunet-idp.c |
74 | gnunet-identity-token.c | 106 | gnunet_idp_LDADD = \ |
75 | gnunet_identity_token_LDADD = \ | ||
76 | $(top_builddir)/src/util/libgnunetutil.la \ | 107 | $(top_builddir)/src/util/libgnunetutil.la \ |
77 | -ljansson -lmicrohttpd \ | 108 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ |
109 | libgnunetidentityprovider.la \ | ||
110 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
111 | $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \ | ||
78 | $(GN_LIBINTL) | 112 | $(GN_LIBINTL) |
113 | |||
114 | check_SCRIPTS = \ | ||
115 | test_idp_attribute.sh \ | ||
116 | test_idp_issue.sh \ | ||
117 | test_idp_consume.sh \ | ||
118 | test_idp_revoke.sh | ||
119 | |||
120 | if ENABLE_TEST_RUN | ||
121 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
122 | TESTS = $(check_SCRIPTS) | ||
123 | endif | ||
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 | */ | ||
35 | static char* token; | ||
36 | |||
37 | /** | ||
38 | * Weather to print the token | ||
39 | */ | ||
40 | static int print_token; | ||
41 | |||
42 | static void | ||
43 | run (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 | |||
158 | int | ||
159 | main(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 | */ | ||
37 | static int ret; | ||
38 | |||
39 | /** | ||
40 | * List attribute flag | ||
41 | */ | ||
42 | static int list; | ||
43 | |||
44 | /** | ||
45 | * Relying party | ||
46 | */ | ||
47 | static char* rp; | ||
48 | |||
49 | /** | ||
50 | * The attribute | ||
51 | */ | ||
52 | static char* attr_name; | ||
53 | |||
54 | /** | ||
55 | * Attribute value | ||
56 | */ | ||
57 | static char* attr_value; | ||
58 | |||
59 | /** | ||
60 | * Attributes to issue | ||
61 | */ | ||
62 | static char* issue_attrs; | ||
63 | |||
64 | /** | ||
65 | * Ticket to consume | ||
66 | */ | ||
67 | static char* consume_ticket; | ||
68 | |||
69 | /** | ||
70 | * Attribute type | ||
71 | */ | ||
72 | static char* type_str; | ||
73 | |||
74 | /** | ||
75 | * Ticket to revoke | ||
76 | */ | ||
77 | static char* revoke_ticket; | ||
78 | |||
79 | /** | ||
80 | * Ego name | ||
81 | */ | ||
82 | static char* ego_name; | ||
83 | |||
84 | /** | ||
85 | * Identity handle | ||
86 | */ | ||
87 | static struct GNUNET_IDENTITY_Handle *identity_handle; | ||
88 | |||
89 | /** | ||
90 | * IdP handle | ||
91 | */ | ||
92 | static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle; | ||
93 | |||
94 | /** | ||
95 | * IdP operation | ||
96 | */ | ||
97 | static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; | ||
98 | |||
99 | /** | ||
100 | * Attribute iterator | ||
101 | */ | ||
102 | static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator; | ||
103 | |||
104 | /** | ||
105 | * Master ABE key | ||
106 | */ | ||
107 | static struct GNUNET_CRYPTO_AbeMasterKey *abe_key; | ||
108 | |||
109 | /** | ||
110 | * ego private key | ||
111 | */ | ||
112 | static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey; | ||
113 | |||
114 | /** | ||
115 | * rp public key | ||
116 | */ | ||
117 | static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key; | ||
118 | |||
119 | /** | ||
120 | * Ticket to consume | ||
121 | */ | ||
122 | static struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
123 | |||
124 | /** | ||
125 | * Attribute list | ||
126 | */ | ||
127 | static struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list; | ||
128 | |||
129 | static void | ||
130 | do_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 | |||
144 | static void | ||
145 | ticket_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 | |||
159 | static void | ||
160 | store_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 | |||
171 | static void | ||
172 | process_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 | |||
195 | static void | ||
196 | iter_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 | |||
204 | static void | ||
205 | process_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 | |||
216 | static void | ||
217 | iter_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 | |||
281 | static void | ||
282 | iter_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 | |||
317 | static void | ||
318 | ego_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 | |||
359 | static void | ||
360 | run (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 | |||
383 | int | ||
384 | main(int argc, char *const argv[]) | ||
385 | { | ||
386 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
387 | |||
388 | GNUNET_GETOPT_option_string ('a', | ||
389 | "add", | ||
390 | NULL, | ||
391 | gettext_noop ("Add attribute"), | ||
392 | &attr_name), | ||
393 | |||
394 | GNUNET_GETOPT_option_string ('V', | ||
395 | "value", | ||
396 | NULL, | ||
397 | gettext_noop ("Attribute value"), | ||
398 | &attr_value), | ||
399 | GNUNET_GETOPT_option_string ('e', | ||
400 | "ego", | ||
401 | NULL, | ||
402 | gettext_noop ("Ego"), | ||
403 | &ego_name), | ||
404 | GNUNET_GETOPT_option_string ('r', | ||
405 | "rp", | ||
406 | NULL, | ||
407 | gettext_noop ("Audience (relying party)"), | ||
408 | &rp), | ||
409 | GNUNET_GETOPT_option_flag ('D', | ||
410 | "dump", | ||
411 | gettext_noop ("List attributes for Ego"), | ||
412 | &list), | ||
413 | GNUNET_GETOPT_option_string ('i', | ||
414 | "issue", | ||
415 | NULL, | ||
416 | gettext_noop ("Issue a ticket"), | ||
417 | &issue_attrs), | ||
418 | GNUNET_GETOPT_option_string ('C', | ||
419 | "consume", | ||
420 | NULL, | ||
421 | gettext_noop ("Consume a ticket"), | ||
422 | &consume_ticket), | ||
423 | GNUNET_GETOPT_option_string ('R', | ||
424 | "revoke", | ||
425 | NULL, | ||
426 | gettext_noop ("Revoke a ticket"), | ||
427 | &revoke_ticket), | ||
428 | GNUNET_GETOPT_option_string ('t', | ||
429 | "type", | ||
430 | NULL, | ||
431 | gettext_noop ("Type of attribute"), | ||
432 | &type_str), | ||
433 | GNUNET_GETOPT_OPTION_END | ||
434 | }; | ||
435 | GNUNET_PROGRAM_run (argc, argv, "ct", | ||
436 | "ct", options, | ||
437 | &run, NULL); | ||
438 | return ret; | ||
439 | } | ||
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index 53fd02c9f..a5c178aa5 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c | |||
@@ -30,12 +30,13 @@ | |||
30 | #include "gnunet_identity_service.h" | 30 | #include "gnunet_identity_service.h" |
31 | #include "gnunet_gnsrecord_lib.h" | 31 | #include "gnunet_gnsrecord_lib.h" |
32 | #include "gnunet_namestore_service.h" | 32 | #include "gnunet_namestore_service.h" |
33 | #include "gnunet_credential_service.h" | ||
33 | #include "gnunet_statistics_service.h" | 34 | #include "gnunet_statistics_service.h" |
34 | #include "gnunet_gns_service.h" | 35 | #include "gnunet_gns_service.h" |
36 | #include "gnunet_identity_provider_plugin.h" | ||
37 | #include "gnunet_identity_attribute_lib.h" | ||
35 | #include "gnunet_signatures.h" | 38 | #include "gnunet_signatures.h" |
36 | #include "identity_provider.h" | 39 | #include "identity_provider.h" |
37 | #include "identity_token.h" | ||
38 | #include <inttypes.h> | ||
39 | 40 | ||
40 | /** | 41 | /** |
41 | * First pass state | 42 | * First pass state |
@@ -58,24 +59,19 @@ | |||
58 | #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS | 59 | #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS |
59 | 60 | ||
60 | /** | 61 | /** |
61 | * Service state (to detect initial update pass) | 62 | * Identity handle |
62 | */ | ||
63 | static int state; | ||
64 | |||
65 | /** | ||
66 | * Head of ego entry DLL | ||
67 | */ | 63 | */ |
68 | static struct EgoEntry *ego_head; | 64 | static struct GNUNET_IDENTITY_Handle *identity_handle; |
69 | 65 | ||
70 | /** | 66 | /** |
71 | * Tail of ego entry DLL | 67 | * Database handle |
72 | */ | 68 | */ |
73 | static struct EgoEntry *ego_tail; | 69 | static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database; |
74 | 70 | ||
75 | /** | 71 | /** |
76 | * Identity handle | 72 | * Name of DB plugin |
77 | */ | 73 | */ |
78 | static struct GNUNET_IDENTITY_Handle *identity_handle; | 74 | static char *db_lib_name; |
79 | 75 | ||
80 | /** | 76 | /** |
81 | * Token expiration interval | 77 | * Token expiration interval |
@@ -93,6 +89,16 @@ static struct GNUNET_NAMESTORE_Handle *ns_handle; | |||
93 | static struct GNUNET_GNS_Handle *gns_handle; | 89 | static struct GNUNET_GNS_Handle *gns_handle; |
94 | 90 | ||
95 | /** | 91 | /** |
92 | * Credential handle | ||
93 | */ | ||
94 | static struct GNUNET_CREDENTIAL_Handle *credential_handle; | ||
95 | |||
96 | /** | ||
97 | * Stats handle | ||
98 | */ | ||
99 | static struct GNUNET_STATISTICS_Handle *stats_handle; | ||
100 | |||
101 | /** | ||
96 | * Namestore qe | 102 | * Namestore qe |
97 | */ | 103 | */ |
98 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | 104 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; |
@@ -112,11 +118,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task; | |||
112 | */ | 118 | */ |
113 | static struct GNUNET_SCHEDULER_Task *update_task; | 119 | static struct GNUNET_SCHEDULER_Task *update_task; |
114 | 120 | ||
115 | /** | ||
116 | * Timeout for next update pass | ||
117 | */ | ||
118 | static struct GNUNET_TIME_Relative min_rel_exp; | ||
119 | |||
120 | 121 | ||
121 | /** | 122 | /** |
122 | * Currently processed token | 123 | * Currently processed token |
@@ -134,43 +135,260 @@ static char* label; | |||
134 | static char* scopes; | 135 | static char* scopes; |
135 | 136 | ||
136 | /** | 137 | /** |
137 | * Expiration for processed token | 138 | * Handle to the statistics service. |
138 | */ | 139 | */ |
139 | static uint64_t rd_exp; | 140 | static struct GNUNET_STATISTICS_Handle *stats; |
140 | 141 | ||
141 | /** | 142 | /** |
142 | * ECDHE Privkey for processed token metadata | 143 | * Our configuration. |
143 | */ | 144 | */ |
144 | static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey; | 145 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
145 | 146 | ||
146 | /** | 147 | /** |
147 | * Handle to the statistics service. | 148 | * An idp client |
148 | */ | 149 | */ |
149 | static struct GNUNET_STATISTICS_Handle *stats; | 150 | struct IdpClient; |
150 | 151 | ||
151 | /** | 152 | /** |
152 | * Our configuration. | 153 | * A ticket iteration operation. |
153 | */ | 154 | */ |
154 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 155 | struct TicketIteration |
156 | { | ||
157 | /** | ||
158 | * DLL | ||
159 | */ | ||
160 | struct TicketIteration *next; | ||
161 | |||
162 | /** | ||
163 | * DLL | ||
164 | */ | ||
165 | struct TicketIteration *prev; | ||
166 | |||
167 | /** | ||
168 | * Client which intiated this zone iteration | ||
169 | */ | ||
170 | struct IdpClient *client; | ||
171 | |||
172 | /** | ||
173 | * Key of the identity we are iterating over. | ||
174 | */ | ||
175 | struct GNUNET_CRYPTO_EcdsaPublicKey identity; | ||
176 | |||
177 | /** | ||
178 | * Identity is audience | ||
179 | */ | ||
180 | uint32_t is_audience; | ||
181 | |||
182 | /** | ||
183 | * The operation id fot the iteration in the response for the client | ||
184 | */ | ||
185 | uint32_t r_id; | ||
186 | |||
187 | /** | ||
188 | * Offset of the iteration used to address next result of the | ||
189 | * iteration in the store | ||
190 | * | ||
191 | * Initialy set to 0 in handle_iteration_start | ||
192 | * Incremented with by every call to handle_iteration_next | ||
193 | */ | ||
194 | uint32_t offset; | ||
195 | |||
196 | }; | ||
197 | |||
198 | |||
199 | |||
200 | /** | ||
201 | * Callback after an ABE bootstrap | ||
202 | * | ||
203 | * @param cls closure | ||
204 | * @param abe_key the ABE key that exists or was created | ||
205 | */ | ||
206 | typedef void | ||
207 | (*AbeBootstrapResult) (void *cls, | ||
208 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key); | ||
155 | 209 | ||
156 | 210 | ||
157 | struct ExchangeHandle | 211 | struct AbeBootstrapHandle |
158 | { | 212 | { |
213 | /** | ||
214 | * Function to call when finished | ||
215 | */ | ||
216 | AbeBootstrapResult proc; | ||
159 | 217 | ||
160 | /** | 218 | /** |
161 | * Client connection | 219 | * Callback closure |
220 | */ | ||
221 | char *proc_cls; | ||
222 | |||
223 | /** | ||
224 | * Key of the zone we are iterating over. | ||
225 | */ | ||
226 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
227 | |||
228 | /** | ||
229 | * Namestore Queue Entry | ||
230 | */ | ||
231 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
232 | |||
233 | /** | ||
234 | * The issuer egos ABE master key | ||
235 | */ | ||
236 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key; | ||
237 | }; | ||
238 | |||
239 | /** | ||
240 | * An attribute iteration operation. | ||
241 | */ | ||
242 | struct AttributeIterator | ||
243 | { | ||
244 | /** | ||
245 | * Next element in the DLL | ||
246 | */ | ||
247 | struct AttributeIterator *next; | ||
248 | |||
249 | /** | ||
250 | * Previous element in the DLL | ||
251 | */ | ||
252 | struct AttributeIterator *prev; | ||
253 | |||
254 | /** | ||
255 | * IDP client which intiated this zone iteration | ||
256 | */ | ||
257 | struct IdpClient *client; | ||
258 | |||
259 | /** | ||
260 | * Key of the zone we are iterating over. | ||
261 | */ | ||
262 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
263 | |||
264 | /** | ||
265 | * The issuer egos ABE master key | ||
266 | */ | ||
267 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key; | ||
268 | |||
269 | /** | ||
270 | * Namestore iterator | ||
271 | */ | ||
272 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
273 | |||
274 | /** | ||
275 | * The operation id fot the zone iteration in the response for the client | ||
276 | */ | ||
277 | uint32_t request_id; | ||
278 | |||
279 | }; | ||
280 | |||
281 | |||
282 | |||
283 | /** | ||
284 | * An idp client | ||
285 | */ | ||
286 | struct IdpClient | ||
287 | { | ||
288 | |||
289 | /** | ||
290 | * The client | ||
162 | */ | 291 | */ |
163 | struct GNUNET_SERVICE_Client *client; | 292 | struct GNUNET_SERVICE_Client *client; |
164 | 293 | ||
165 | /** | 294 | /** |
166 | * Ticket | 295 | * Message queue for transmission to @e client |
296 | */ | ||
297 | struct GNUNET_MQ_Handle *mq; | ||
298 | |||
299 | /** | ||
300 | * Head of the DLL of | ||
301 | * Attribute iteration operations in | ||
302 | * progress initiated by this client | ||
303 | */ | ||
304 | struct AttributeIterator *op_head; | ||
305 | |||
306 | /** | ||
307 | * Tail of the DLL of | ||
308 | * Attribute iteration operations | ||
309 | * in progress initiated by this client | ||
310 | */ | ||
311 | struct AttributeIterator *op_tail; | ||
312 | |||
313 | /** | ||
314 | * Head of DLL of ticket iteration ops | ||
315 | */ | ||
316 | struct TicketIteration *ticket_iter_head; | ||
317 | |||
318 | /** | ||
319 | * Tail of DLL of ticket iteration ops | ||
320 | */ | ||
321 | struct TicketIteration *ticket_iter_tail; | ||
322 | |||
323 | |||
324 | /** | ||
325 | * Head of DLL of ticket revocation ops | ||
326 | */ | ||
327 | struct TicketRevocationHandle *revocation_list_head; | ||
328 | |||
329 | /** | ||
330 | * Tail of DLL of ticket revocation ops | ||
331 | */ | ||
332 | struct TicketRevocationHandle *revocation_list_tail; | ||
333 | }; | ||
334 | |||
335 | |||
336 | |||
337 | struct AttributeStoreHandle | ||
338 | { | ||
339 | |||
340 | /** | ||
341 | * Client connection | ||
342 | */ | ||
343 | struct IdpClient *client; | ||
344 | |||
345 | /** | ||
346 | * Identity | ||
347 | */ | ||
348 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
349 | |||
350 | /** | ||
351 | * Identity pubkey | ||
352 | */ | ||
353 | struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey; | ||
354 | |||
355 | /** | ||
356 | * The issuer egos ABE master key | ||
357 | */ | ||
358 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key; | ||
359 | |||
360 | /** | ||
361 | * QueueEntry | ||
362 | */ | ||
363 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
364 | |||
365 | /** | ||
366 | * The attribute to store | ||
367 | */ | ||
368 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim; | ||
369 | |||
370 | /** | ||
371 | * request id | ||
372 | */ | ||
373 | uint32_t r_id; | ||
374 | }; | ||
375 | |||
376 | |||
377 | /* Prototype */ | ||
378 | struct ParallelLookup; | ||
379 | |||
380 | struct ConsumeTicketHandle | ||
381 | { | ||
382 | |||
383 | /** | ||
384 | * Client connection | ||
167 | */ | 385 | */ |
168 | struct TokenTicket *ticket; | 386 | struct IdpClient *client; |
169 | 387 | ||
170 | /** | 388 | /** |
171 | * Token returned | 389 | * Ticket |
172 | */ | 390 | */ |
173 | struct IdentityToken *token; | 391 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; |
174 | 392 | ||
175 | /** | 393 | /** |
176 | * LookupRequest | 394 | * LookupRequest |
@@ -180,86 +398,173 @@ struct ExchangeHandle | |||
180 | /** | 398 | /** |
181 | * Audience Key | 399 | * Audience Key |
182 | */ | 400 | */ |
183 | struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey; | 401 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; |
402 | |||
403 | /** | ||
404 | * Audience Key | ||
405 | */ | ||
406 | struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub; | ||
184 | 407 | ||
185 | /** | 408 | /** |
186 | * Label to return | 409 | * Lookup DLL |
187 | */ | 410 | */ |
188 | char *label; | 411 | struct ParallelLookup *parallel_lookups_head; |
412 | |||
413 | /** | ||
414 | * Lookup DLL | ||
415 | */ | ||
416 | struct ParallelLookup *parallel_lookups_tail; | ||
417 | |||
418 | /** | ||
419 | * Kill task | ||
420 | */ | ||
421 | struct GNUNET_SCHEDULER_Task *kill_task; | ||
189 | 422 | ||
190 | /** | 423 | /** |
424 | * The ABE key | ||
425 | */ | ||
426 | struct GNUNET_CRYPTO_AbeKey *key; | ||
427 | |||
428 | /** | ||
429 | * Attributes | ||
430 | */ | ||
431 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
432 | |||
433 | /** | ||
434 | * Lookup time | ||
435 | */ | ||
436 | struct GNUNET_TIME_Absolute lookup_start_time; | ||
437 | |||
438 | /** | ||
191 | * request id | 439 | * request id |
192 | */ | 440 | */ |
193 | uint32_t r_id; | 441 | uint32_t r_id; |
194 | }; | 442 | }; |
195 | 443 | ||
196 | struct IssueHandle | 444 | /** |
445 | * Handle for a parallel GNS lookup job | ||
446 | */ | ||
447 | struct ParallelLookup | ||
448 | { | ||
449 | /* DLL */ | ||
450 | struct ParallelLookup *next; | ||
451 | |||
452 | /* DLL */ | ||
453 | struct ParallelLookup *prev; | ||
454 | |||
455 | /* The GNS request */ | ||
456 | struct GNUNET_GNS_LookupRequest *lookup_request; | ||
457 | |||
458 | /* The handle the return to */ | ||
459 | struct ConsumeTicketHandle *handle; | ||
460 | |||
461 | /** | ||
462 | * Lookup time | ||
463 | */ | ||
464 | struct GNUNET_TIME_Absolute lookup_start_time; | ||
465 | |||
466 | /* The label to look up */ | ||
467 | char *label; | ||
468 | }; | ||
469 | |||
470 | /** | ||
471 | * Ticket revocation request handle | ||
472 | */ | ||
473 | struct TicketRevocationHandle | ||
197 | { | 474 | { |
475 | /** | ||
476 | * DLL | ||
477 | */ | ||
478 | struct TicketRevocationHandle *next; | ||
479 | |||
480 | /** | ||
481 | * DLL | ||
482 | */ | ||
483 | struct TicketRevocationHandle *prev; | ||
198 | 484 | ||
199 | /** | 485 | /** |
200 | * Client connection | 486 | * Client connection |
201 | */ | 487 | */ |
202 | struct GNUNET_SERVICE_Client *client; | 488 | struct IdpClient *client; |
489 | |||
490 | /** | ||
491 | * Attributes to reissue | ||
492 | */ | ||
493 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
494 | |||
495 | /** | ||
496 | * Attributes to revoke | ||
497 | */ | ||
498 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs; | ||
203 | 499 | ||
204 | /** | 500 | /** |
205 | * Issuer Key | 501 | * Issuer Key |
206 | */ | 502 | */ |
207 | struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key; | 503 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; |
208 | 504 | ||
209 | /** | 505 | /** |
210 | * Issue pubkey | 506 | * Ticket to issue |
211 | */ | 507 | */ |
212 | struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey; | 508 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; |
213 | 509 | ||
214 | /** | 510 | /** |
215 | * Audience Key | 511 | * QueueEntry |
216 | */ | 512 | */ |
217 | struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; | 513 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; |
218 | 514 | ||
219 | /** | 515 | /** |
220 | * Expiration | 516 | * Namestore iterator |
221 | */ | 517 | */ |
222 | struct GNUNET_TIME_Absolute expiration; | 518 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; |
223 | 519 | ||
224 | /** | 520 | /** |
225 | * Scopes | 521 | * The ABE master key |
226 | */ | 522 | */ |
227 | char *scopes; | 523 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key; |
228 | 524 | ||
229 | /** | 525 | /** |
230 | * nonce | 526 | * Offset |
231 | */ | 527 | */ |
232 | uint64_t nonce; | 528 | uint32_t offset; |
233 | 529 | ||
234 | /** | 530 | /** |
235 | * NS iterator | 531 | * request id |
236 | */ | 532 | */ |
237 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | 533 | uint32_t r_id; |
534 | }; | ||
535 | |||
536 | |||
537 | |||
538 | /** | ||
539 | * Ticket issue request handle | ||
540 | */ | ||
541 | struct TicketIssueHandle | ||
542 | { | ||
238 | 543 | ||
239 | /** | 544 | /** |
240 | * Attribute map | 545 | * Client connection |
241 | */ | 546 | */ |
242 | struct GNUNET_CONTAINER_MultiHashMap *attr_map; | 547 | struct IdpClient *client; |
243 | 548 | ||
244 | /** | 549 | /** |
245 | * Token | 550 | * Attributes to issue |
246 | */ | 551 | */ |
247 | struct IdentityToken *token; | 552 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; |
248 | 553 | ||
249 | /** | 554 | /** |
250 | * Ticket | 555 | * Issuer Key |
251 | */ | 556 | */ |
252 | struct TokenTicket *ticket; | 557 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; |
253 | 558 | ||
254 | /** | 559 | /** |
255 | * QueueEntry | 560 | * Ticket to issue |
256 | */ | 561 | */ |
257 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | 562 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; |
258 | 563 | ||
259 | /** | 564 | /** |
260 | * The label the token is stored under | 565 | * QueueEntry |
261 | */ | 566 | */ |
262 | char *label; | 567 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; |
263 | 568 | ||
264 | /** | 569 | /** |
265 | * request id | 570 | * request id |
@@ -267,6 +572,7 @@ struct IssueHandle | |||
267 | uint32_t r_id; | 572 | uint32_t r_id; |
268 | }; | 573 | }; |
269 | 574 | ||
575 | |||
270 | /** | 576 | /** |
271 | * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format | 577 | * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format |
272 | * | 578 | * |
@@ -293,988 +599,1362 @@ struct EgoEntry | |||
293 | */ | 599 | */ |
294 | struct GNUNET_CONTAINER_MultiHashMap *attr_map; | 600 | struct GNUNET_CONTAINER_MultiHashMap *attr_map; |
295 | 601 | ||
296 | /** | ||
297 | * Attributes are old and should be updated if GNUNET_YES | ||
298 | */ | ||
299 | int attributes_dirty; | ||
300 | }; | 602 | }; |
301 | 603 | ||
302 | /** | 604 | /** |
303 | * Continuation for token store call | 605 | * Cleanup task |
606 | */ | ||
607 | static void | ||
608 | cleanup() | ||
609 | { | ||
610 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
611 | "Cleaning up\n"); | ||
612 | if (NULL != stats) | ||
613 | { | ||
614 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
615 | stats = NULL; | ||
616 | } | ||
617 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, | ||
618 | TKT_database)); | ||
619 | GNUNET_free (db_lib_name); | ||
620 | db_lib_name = NULL; | ||
621 | if (NULL != timeout_task) | ||
622 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
623 | if (NULL != update_task) | ||
624 | GNUNET_SCHEDULER_cancel (update_task); | ||
625 | if (NULL != identity_handle) | ||
626 | GNUNET_IDENTITY_disconnect (identity_handle); | ||
627 | if (NULL != gns_handle) | ||
628 | GNUNET_GNS_disconnect (gns_handle); | ||
629 | if (NULL != credential_handle) | ||
630 | GNUNET_CREDENTIAL_disconnect (credential_handle); | ||
631 | if (NULL != ns_it) | ||
632 | GNUNET_NAMESTORE_zone_iteration_stop (ns_it); | ||
633 | if (NULL != ns_qe) | ||
634 | GNUNET_NAMESTORE_cancel (ns_qe); | ||
635 | if (NULL != ns_handle) | ||
636 | GNUNET_NAMESTORE_disconnect (ns_handle); | ||
637 | if (NULL != stats_handle) | ||
638 | GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO); | ||
639 | if (NULL != token) | ||
640 | GNUNET_free (token); | ||
641 | if (NULL != label) | ||
642 | GNUNET_free (label); | ||
643 | |||
644 | } | ||
645 | |||
646 | /** | ||
647 | * Shutdown task | ||
304 | * | 648 | * |
305 | * @param cls NULL | 649 | * @param cls NULL |
306 | * @param success error code | 650 | * @param tc task context |
307 | * @param emsg error message | 651 | */ |
652 | static void | ||
653 | do_shutdown (void *cls) | ||
654 | { | ||
655 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
656 | "Shutting down...\n"); | ||
657 | cleanup(); | ||
658 | } | ||
659 | |||
660 | /** | ||
661 | * Finished storing newly bootstrapped ABE key | ||
308 | */ | 662 | */ |
309 | static void | 663 | static void |
310 | store_token_cont (void *cls, | 664 | bootstrap_store_cont (void *cls, |
311 | int32_t success, | 665 | int32_t success, |
312 | const char *emsg) | 666 | const char *emsg) |
313 | { | 667 | { |
314 | ns_qe = NULL; | 668 | struct AbeBootstrapHandle *abh = cls; |
315 | if (GNUNET_SYSERR == success) | 669 | if (GNUNET_SYSERR == success) |
316 | { | 670 | { |
317 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 671 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
318 | "Failed to update token: %s\n", | 672 | "Failed to bootstrap ABE master %s\n", |
319 | emsg); | 673 | emsg); |
674 | abh->proc (abh->proc_cls, NULL); | ||
675 | GNUNET_free (abh->abe_key); | ||
676 | GNUNET_free (abh); | ||
320 | return; | 677 | return; |
321 | } | 678 | } |
322 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | 679 | abh->proc (abh->proc_cls, abh->abe_key); |
680 | GNUNET_free (abh); | ||
323 | } | 681 | } |
324 | 682 | ||
683 | /** | ||
684 | * Generates and stores a new ABE key | ||
685 | */ | ||
686 | static void | ||
687 | bootstrap_store_task (void *cls) | ||
688 | { | ||
689 | struct AbeBootstrapHandle *abh = cls; | ||
690 | struct GNUNET_GNSRECORD_Data rd[1]; | ||
691 | char *key; | ||
692 | |||
693 | rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key, | ||
694 | (void**)&key); | ||
695 | rd[0].data = key; | ||
696 | rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER; | ||
697 | rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE; | ||
698 | rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane? | ||
699 | abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
700 | &abh->identity, | ||
701 | "+", | ||
702 | 1, | ||
703 | rd, | ||
704 | &bootstrap_store_cont, | ||
705 | abh); | ||
706 | GNUNET_free (key); | ||
707 | } | ||
325 | 708 | ||
326 | /** | 709 | /** |
327 | * This function updates the old token with new attributes, | 710 | * Error checking for ABE master |
328 | * removes deleted attributes and expiration times. | ||
329 | * | ||
330 | * @param cls the ego entry | ||
331 | */ | 711 | */ |
332 | static void | 712 | static void |
333 | handle_token_update (void *cls) | 713 | bootstrap_abe_error (void *cls) |
334 | { | 714 | { |
335 | char *token_metadata; | 715 | struct AbeBootstrapHandle *abh = cls; |
336 | char *write_ptr; | 716 | GNUNET_free (abh); |
337 | char *enc_token_str; | 717 | abh->proc (abh->proc_cls, NULL); |
338 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | 718 | GNUNET_free (abh); |
339 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | 719 | } |
340 | struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey; | ||
341 | struct EgoEntry *ego_entry = cls; | ||
342 | struct GNUNET_GNSRECORD_Data token_record[2]; | ||
343 | struct GNUNET_HashCode key_hash; | ||
344 | struct GNUNET_TIME_Relative token_rel_exp; | ||
345 | struct GNUNET_TIME_Relative token_ttl; | ||
346 | struct GNUNET_TIME_Absolute token_exp; | ||
347 | struct GNUNET_TIME_Absolute token_nbf; | ||
348 | struct GNUNET_TIME_Absolute new_exp; | ||
349 | struct GNUNET_TIME_Absolute new_iat; | ||
350 | struct GNUNET_TIME_Absolute new_nbf; | ||
351 | struct IdentityToken *new_token; | ||
352 | struct TokenAttr *cur_value; | ||
353 | struct TokenAttr *attr; | ||
354 | size_t token_metadata_len; | ||
355 | |||
356 | priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
357 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, | ||
358 | &pub_key); | ||
359 | |||
360 | //Note: We need the token expiration time here. Not the record expiration | ||
361 | //time. | ||
362 | //There are two types of tokens: Token that expire on GNS level with | ||
363 | //an absolute expiration time. Those are basically tokens that will | ||
364 | //be automatically revoked on (record)expiration. | ||
365 | //Tokens stored with relative expiration times will expire on the token level (token expiration) | ||
366 | //but this service will reissue new tokens that can be retrieved from GNS | ||
367 | //automatically. | ||
368 | |||
369 | for (attr = token->attr_head; NULL != attr; attr = attr->next) | ||
370 | { | ||
371 | if (0 == strcmp (attr->name, "exp")) | ||
372 | { | ||
373 | GNUNET_assert (1 == sscanf (attr->val_head->value, | ||
374 | "%"SCNu64, | ||
375 | &token_exp.abs_value_us)); | ||
376 | } else if (0 == strcmp (attr->name, "nbf")) { | ||
377 | GNUNET_assert (1 == sscanf (attr->val_head->value, | ||
378 | "%"SCNu64, | ||
379 | &token_nbf.abs_value_us)); | ||
380 | } | ||
381 | } | ||
382 | token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp); | ||
383 | 720 | ||
384 | token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp); | 721 | |
385 | if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us) | 722 | /** |
386 | { | 723 | * Handle ABE lookup in namestore |
387 | //This token is not yet expired! Save and skip | 724 | */ |
388 | if (min_rel_exp.rel_value_us > token_ttl.rel_value_us) | 725 | static void |
389 | { | 726 | bootstrap_abe_result (void *cls, |
390 | min_rel_exp = token_ttl; | 727 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, |
391 | } | 728 | const char *label, |
392 | GNUNET_free (token); | 729 | unsigned int rd_count, |
393 | token = NULL; | 730 | const struct GNUNET_GNSRECORD_Data *rd) |
394 | GNUNET_free (label); | 731 | { |
395 | label = NULL; | 732 | struct AbeBootstrapHandle *abh = cls; |
396 | GNUNET_free (scopes); | 733 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key; |
397 | scopes = NULL; | 734 | int i; |
398 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | 735 | |
736 | for (i=0;i<rd_count;i++) { | ||
737 | if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type) | ||
738 | continue; | ||
739 | abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key (rd[i].data, | ||
740 | rd[i].data_size); | ||
741 | abh->proc (abh->proc_cls, abe_key); | ||
742 | GNUNET_free (abh); | ||
399 | return; | 743 | return; |
400 | } | 744 | } |
401 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 745 | |
402 | "Token is expired. Create a new one\n"); | 746 | //No ABE master found, bootstrapping... |
403 | new_token = token_create (&pub_key, | 747 | abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key (); |
404 | &token->aud_key); | 748 | GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh); |
405 | new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp); | 749 | } |
406 | new_nbf = GNUNET_TIME_absolute_get (); | 750 | |
407 | new_iat = new_nbf; | 751 | /** |
408 | for (attr = token->attr_head; NULL != attr; attr = attr->next) | 752 | * Bootstrap ABE master if it does not yet exists. |
753 | * Will call the AbeBootstrapResult processor when done. | ||
754 | * will always recreate the ABE key of GNUNET_YES == recreate | ||
755 | */ | ||
756 | static void | ||
757 | bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
758 | AbeBootstrapResult proc, | ||
759 | void* cls, | ||
760 | int recreate) | ||
761 | { | ||
762 | struct AbeBootstrapHandle *abh; | ||
763 | |||
764 | abh = GNUNET_new (struct AbeBootstrapHandle); | ||
765 | abh->proc = proc; | ||
766 | abh->proc_cls = cls; | ||
767 | abh->identity = *identity; | ||
768 | if (GNUNET_YES == recreate) | ||
409 | { | 769 | { |
410 | if (0 == strcmp (attr->name, "exp")) | 770 | abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key (); |
411 | { | 771 | GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh); |
412 | token_add_attr_int (new_token, attr->name, new_exp.abs_value_us); | 772 | } else { |
413 | } | 773 | abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, |
414 | else if (0 == strcmp (attr->name, "nbf")) | 774 | identity, |
415 | { | 775 | "+", |
416 | token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us); | 776 | &bootstrap_abe_error, |
417 | } | 777 | abh, |
418 | else if (0 == strcmp (attr->name, "iat")) | 778 | &bootstrap_abe_result, |
419 | { | 779 | abh); |
420 | token_add_attr_int (new_token, attr->name, new_iat.abs_value_us); | ||
421 | } | ||
422 | else if ((0 == strcmp (attr->name, "iss")) | ||
423 | || (0 == strcmp (attr->name, "aud"))) | ||
424 | { | ||
425 | //Omit | ||
426 | } | ||
427 | else if (0 == strcmp (attr->name, "sub")) | ||
428 | { | ||
429 | token_add_attr (new_token, | ||
430 | attr->name, | ||
431 | attr->val_head->value); | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | GNUNET_CRYPTO_hash (attr->name, | ||
436 | strlen (attr->name), | ||
437 | &key_hash); | ||
438 | //Check if attr still exists. omit of not | ||
439 | if (GNUNET_NO != | ||
440 | GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map, | ||
441 | &key_hash)) | ||
442 | { | ||
443 | cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map, | ||
444 | &key_hash); | ||
445 | GNUNET_assert (NULL != cur_value); | ||
446 | GNUNET_CONTAINER_DLL_insert (new_token->attr_head, | ||
447 | new_token->attr_tail, | ||
448 | cur_value); | ||
449 | } | ||
450 | } | ||
451 | } | 780 | } |
452 | |||
453 | // reassemble and set | ||
454 | GNUNET_assert (token_serialize (new_token, | ||
455 | priv_key, | ||
456 | &new_ecdhe_privkey, | ||
457 | &enc_token_str)); | ||
458 | |||
459 | token_record[0].data = enc_token_str; | ||
460 | token_record[0].data_size = strlen (enc_token_str) + 1; | ||
461 | token_record[0].expiration_time = rd_exp; //Old expiration time | ||
462 | token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; | ||
463 | token_record[0].flags = GNUNET_GNSRECORD_RF_NONE; | ||
464 | |||
465 | //Meta | ||
466 | token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) | ||
467 | + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) | ||
468 | + strlen (scopes) + 1; //With 0-Terminator | ||
469 | token_metadata = GNUNET_malloc (token_metadata_len); | ||
470 | write_ptr = token_metadata; | ||
471 | GNUNET_memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); | ||
472 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); | ||
473 | GNUNET_memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
474 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
475 | GNUNET_memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator; | ||
476 | |||
477 | token_record[1].data = token_metadata; | ||
478 | token_record[1].data_size = token_metadata_len; | ||
479 | token_record[1].expiration_time = rd_exp; | ||
480 | token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA; | ||
481 | token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; | ||
482 | |||
483 | ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
484 | priv_key, | ||
485 | label, | ||
486 | 2, | ||
487 | token_record, | ||
488 | &store_token_cont, | ||
489 | ego_entry); | ||
490 | token_destroy (new_token); | ||
491 | token_destroy (token); | ||
492 | GNUNET_free (new_ecdhe_privkey); | ||
493 | GNUNET_free (enc_token_str); | ||
494 | token = NULL; | ||
495 | GNUNET_free (label); | ||
496 | label = NULL; | ||
497 | GNUNET_free (scopes); | ||
498 | scopes = NULL; | ||
499 | } | 781 | } |
500 | 782 | ||
501 | 783 | ||
784 | |||
785 | static int | ||
786 | create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash, | ||
787 | struct GNUNET_CRYPTO_SymmetricSessionKey *skey, | ||
788 | struct GNUNET_CRYPTO_SymmetricInitializationVector *iv) | ||
789 | { | ||
790 | struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str; | ||
791 | |||
792 | GNUNET_CRYPTO_hash_to_enc (new_key_hash, | ||
793 | &new_key_hash_str); | ||
794 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str); | ||
795 | static const char ctx_key[] = "gnuid-aes-ctx-key"; | ||
796 | GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), | ||
797 | new_key_hash, sizeof (struct GNUNET_HashCode), | ||
798 | ctx_key, strlen (ctx_key), | ||
799 | NULL, 0); | ||
800 | static const char ctx_iv[] = "gnuid-aes-ctx-iv"; | ||
801 | GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), | ||
802 | new_key_hash, sizeof (struct GNUNET_HashCode), | ||
803 | ctx_iv, strlen (ctx_iv), | ||
804 | NULL, 0); | ||
805 | return GNUNET_OK; | ||
806 | } | ||
807 | |||
502 | static void | 808 | static void |
503 | update_identities(void *cls); | 809 | cleanup_ticket_issue_handle (struct TicketIssueHandle *handle) |
810 | { | ||
811 | if (NULL != handle->attrs) | ||
812 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs); | ||
813 | if (NULL != handle->ns_qe) | ||
814 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
815 | GNUNET_free (handle); | ||
816 | } | ||
504 | 817 | ||
505 | 818 | ||
506 | /** | 819 | static void |
507 | * | 820 | send_ticket_result (struct IdpClient *client, |
508 | * Cleanup attr_map | 821 | uint32_t r_id, |
509 | * | 822 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, |
510 | * @param cls NULL | 823 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) |
511 | * @param key the key | 824 | { |
512 | * @param value the json_t attribute value | 825 | struct TicketResultMessage *irm; |
513 | * @return #GNUNET_YES | 826 | struct GNUNET_MQ_Envelope *env; |
514 | */ | 827 | struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf; |
515 | static int | 828 | |
516 | clear_ego_attrs (void *cls, | 829 | /* store ticket in DB */ |
517 | const struct GNUNET_HashCode *key, | 830 | if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls, |
518 | void *value) | 831 | ticket, |
519 | { | 832 | attrs)) |
520 | struct TokenAttr *attr = value; | ||
521 | struct TokenAttrValue *val; | ||
522 | struct TokenAttrValue *tmp_val; | ||
523 | for (val = attr->val_head; NULL != val;) | ||
524 | { | 833 | { |
525 | tmp_val = val->next; | 834 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
526 | GNUNET_CONTAINER_DLL_remove (attr->val_head, | 835 | "Unable to store ticket after issue\n"); |
527 | attr->val_tail, | 836 | GNUNET_break (0); |
528 | val); | ||
529 | GNUNET_free (val->value); | ||
530 | GNUNET_free (val); | ||
531 | val = tmp_val; | ||
532 | } | 837 | } |
533 | GNUNET_free (attr->name); | ||
534 | GNUNET_free (attr); | ||
535 | 838 | ||
536 | return GNUNET_YES; | 839 | env = GNUNET_MQ_msg_extra (irm, |
840 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket), | ||
841 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT); | ||
842 | ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1]; | ||
843 | *ticket_buf = *ticket; | ||
844 | irm->id = htonl (r_id); | ||
845 | GNUNET_MQ_send (client->mq, | ||
846 | env); | ||
537 | } | 847 | } |
538 | 848 | ||
539 | |||
540 | static void | 849 | static void |
541 | token_collect_error_cb (void *cls) | 850 | store_ticket_issue_cont (void *cls, |
851 | int32_t success, | ||
852 | const char *emsg) | ||
542 | { | 853 | { |
543 | struct EgoEntry *ego_entry = cls; | 854 | struct TicketIssueHandle *handle = cls; |
855 | |||
856 | handle->ns_qe = NULL; | ||
857 | if (GNUNET_SYSERR == success) | ||
858 | { | ||
859 | cleanup_ticket_issue_handle (handle); | ||
860 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", | ||
861 | "Unknown Error\n"); | ||
862 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
863 | return; | ||
864 | } | ||
865 | send_ticket_result (handle->client, | ||
866 | handle->r_id, | ||
867 | &handle->ticket, | ||
868 | handle->attrs); | ||
869 | cleanup_ticket_issue_handle (handle); | ||
870 | } | ||
871 | |||
872 | |||
873 | |||
874 | int | ||
875 | serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
876 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
877 | const struct GNUNET_CRYPTO_AbeKey *rp_key, | ||
878 | struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey, | ||
879 | char **result) | ||
880 | { | ||
881 | struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey; | ||
882 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
883 | char *enc_keyinfo; | ||
884 | char *serialized_key; | ||
885 | char *buf; | ||
886 | char *write_ptr; | ||
887 | char attrs_str_len; | ||
888 | ssize_t size; | ||
889 | |||
890 | struct GNUNET_CRYPTO_SymmetricSessionKey skey; | ||
891 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
892 | struct GNUNET_HashCode new_key_hash; | ||
893 | ssize_t enc_size; | ||
894 | |||
895 | size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key, | ||
896 | (void**)&serialized_key); | ||
897 | attrs_str_len = 0; | ||
898 | for (le = attrs->list_head; NULL != le; le = le->next) { | ||
899 | attrs_str_len += strlen (le->claim->name) + 1; | ||
900 | } | ||
901 | buf = GNUNET_malloc (attrs_str_len + size); | ||
902 | write_ptr = buf; | ||
903 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
904 | "Writing attributes\n"); | ||
905 | for (le = attrs->list_head; NULL != le; le = le->next) { | ||
906 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
907 | "%s\n", le->claim->name); | ||
544 | 908 | ||
545 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
546 | ">>> Updating Ego failed!\n"); | ||
547 | //Clear attribute map for ego | ||
548 | GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, | ||
549 | &clear_ego_attrs, | ||
550 | ego_entry); | ||
551 | GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); | ||
552 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | ||
553 | ego_entry->next); | ||
554 | 909 | ||
910 | GNUNET_memcpy (write_ptr, | ||
911 | le->claim->name, | ||
912 | strlen (le->claim->name)); | ||
913 | write_ptr[strlen (le->claim->name)] = ','; | ||
914 | write_ptr += strlen (le->claim->name) + 1; | ||
915 | } | ||
916 | write_ptr--; | ||
917 | write_ptr[0] = '\0'; //replace last , with a 0-terminator | ||
918 | write_ptr++; | ||
919 | GNUNET_memcpy (write_ptr, | ||
920 | serialized_key, | ||
921 | size); | ||
922 | GNUNET_free (serialized_key); | ||
923 | // ECDH keypair E = eG | ||
924 | *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create(); | ||
925 | GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey, | ||
926 | &ecdh_pubkey); | ||
927 | enc_keyinfo = GNUNET_malloc (size + attrs_str_len); | ||
928 | // Derived key K = H(eB) | ||
929 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey, | ||
930 | &ticket->audience, | ||
931 | &new_key_hash)); | ||
932 | create_sym_key_from_ecdh(&new_key_hash, &skey, &iv); | ||
933 | enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf, | ||
934 | size + attrs_str_len, | ||
935 | &skey, &iv, | ||
936 | enc_keyinfo); | ||
937 | *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+ | ||
938 | enc_size); | ||
939 | GNUNET_memcpy (*result, | ||
940 | &ecdh_pubkey, | ||
941 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); | ||
942 | GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey), | ||
943 | enc_keyinfo, | ||
944 | enc_size); | ||
945 | GNUNET_free (enc_keyinfo); | ||
946 | GNUNET_free (buf); | ||
947 | return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size; | ||
555 | } | 948 | } |
556 | 949 | ||
557 | 950 | ||
951 | |||
558 | static void | 952 | static void |
559 | token_collect_finished_cb (void *cls) | 953 | issue_ticket_after_abe_bootstrap (void *cls, |
954 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key) | ||
560 | { | 955 | { |
561 | struct EgoEntry *ego_entry = cls; | 956 | struct TicketIssueHandle *ih = cls; |
957 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
958 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; | ||
959 | struct GNUNET_GNSRECORD_Data code_record[1]; | ||
960 | struct GNUNET_CRYPTO_AbeKey *rp_key; | ||
961 | char *code_record_data; | ||
962 | char **attrs; | ||
963 | char *label; | ||
964 | char *policy; | ||
965 | int attrs_len; | ||
966 | int i; | ||
967 | size_t code_record_len; | ||
562 | 968 | ||
563 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 969 | //Create new ABE key for RP |
564 | ">>> Updating Ego finished\n"); | 970 | attrs_len = 0; |
565 | //Clear attribute map for ego | 971 | for (le = ih->attrs->list_head; NULL != le; le = le->next) |
566 | GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, | 972 | attrs_len++; |
567 | &clear_ego_attrs, | 973 | attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*)); |
568 | ego_entry); | 974 | i = 0; |
569 | GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); | 975 | for (le = ih->attrs->list_head; NULL != le; le = le->next) { |
570 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | 976 | GNUNET_asprintf (&policy, "%s_%lu", |
571 | ego_entry->next); | 977 | le->claim->name, |
978 | le->claim->version); | ||
979 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
980 | "Adding attribute to key: %s\n", | ||
981 | policy); | ||
982 | attrs[i] = policy; | ||
983 | i++; | ||
984 | } | ||
985 | attrs[i] = NULL; | ||
986 | rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key, | ||
987 | attrs); | ||
988 | |||
989 | //TODO review this wireformat | ||
990 | code_record_len = serialize_abe_keyinfo2 (&ih->ticket, | ||
991 | ih->attrs, | ||
992 | rp_key, | ||
993 | &ecdhe_privkey, | ||
994 | &code_record_data); | ||
995 | code_record[0].data = code_record_data; | ||
996 | code_record[0].data_size = code_record_len; | ||
997 | code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us; | ||
998 | code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY; | ||
999 | code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1000 | |||
1001 | label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd, | ||
1002 | sizeof (uint64_t)); | ||
1003 | //Publish record | ||
1004 | ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1005 | &ih->identity, | ||
1006 | label, | ||
1007 | 1, | ||
1008 | code_record, | ||
1009 | &store_ticket_issue_cont, | ||
1010 | ih); | ||
1011 | //for (; i > 0; i--) | ||
1012 | // GNUNET_free (attrs[i-1]); | ||
1013 | GNUNET_free (ecdhe_privkey); | ||
1014 | GNUNET_free (label); | ||
1015 | GNUNET_free (attrs); | ||
1016 | GNUNET_free (code_record_data); | ||
1017 | GNUNET_CRYPTO_cpabe_delete_key (rp_key, | ||
1018 | GNUNET_YES); | ||
1019 | GNUNET_CRYPTO_cpabe_delete_master_key (abe_key); | ||
572 | } | 1020 | } |
573 | 1021 | ||
574 | 1022 | ||
575 | /** | 1023 | /** |
1024 | * Checks a ticket issue message | ||
576 | * | 1025 | * |
577 | * Update all ID_TOKEN records for an identity and store them | 1026 | * @param cls client sending the message |
578 | * | 1027 | * @param im message of type `struct TicketIssueMessage` |
579 | * @param cls the identity entry | 1028 | * @return #GNUNET_OK if @a im is well-formed |
580 | * @param zone the identity | ||
581 | * @param lbl the name of the record | ||
582 | * @param rd_count number of records | ||
583 | * @param rd record data | ||
584 | */ | 1029 | */ |
585 | static void | 1030 | static int |
586 | token_collect (void *cls, | 1031 | check_issue_ticket_message(void *cls, |
587 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 1032 | const struct IssueTicketMessage *im) |
588 | const char *lbl, | 1033 | { |
589 | unsigned int rd_count, | 1034 | uint16_t size; |
590 | const struct GNUNET_GNSRECORD_Data *rd) | ||
591 | { | ||
592 | struct EgoEntry *ego_entry = cls; | ||
593 | const struct GNUNET_GNSRECORD_Data *token_record; | ||
594 | const struct GNUNET_GNSRECORD_Data *token_metadata_record; | ||
595 | struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key; | ||
596 | struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key; | ||
597 | |||
598 | //There should be only a single record for a token under a label | ||
599 | if (2 != rd_count) | ||
600 | { | ||
601 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
602 | return; | ||
603 | } | ||
604 | 1035 | ||
605 | if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) | 1036 | size = ntohs (im->header.size); |
606 | { | 1037 | if (size <= sizeof (struct IssueTicketMessage)) |
607 | token_metadata_record = &rd[0]; | ||
608 | token_record = &rd[1]; | ||
609 | } | ||
610 | else | ||
611 | { | ||
612 | token_record = &rd[0]; | ||
613 | token_metadata_record = &rd[1]; | ||
614 | } | ||
615 | if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) | ||
616 | { | ||
617 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
618 | return; | ||
619 | } | ||
620 | if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN) | ||
621 | { | 1038 | { |
622 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | 1039 | GNUNET_break (0); |
623 | return; | 1040 | return GNUNET_SYSERR; |
624 | } | 1041 | } |
1042 | return GNUNET_OK; | ||
1043 | } | ||
1044 | |||
625 | 1045 | ||
626 | //Get metadata and decrypt token | 1046 | /** |
627 | priv_key = (struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data; | 1047 | * |
628 | ecdhe_privkey = *priv_key; | 1048 | * Handler for ticket issue message |
629 | aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&priv_key[1]; | 1049 | * |
630 | scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | 1050 | * @param cls unused |
1051 | * @param client who sent the message | ||
1052 | * @param message the message | ||
1053 | */ | ||
1054 | static void | ||
1055 | handle_issue_ticket_message (void *cls, | ||
1056 | const struct IssueTicketMessage *im) | ||
1057 | { | ||
1058 | struct TicketIssueHandle *ih; | ||
1059 | struct IdpClient *idp = cls; | ||
1060 | size_t attrs_len; | ||
1061 | |||
1062 | ih = GNUNET_new (struct TicketIssueHandle); | ||
1063 | attrs_len = ntohs (im->attr_len); | ||
1064 | ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len); | ||
1065 | ih->r_id = ntohl (im->id); | ||
1066 | ih->client = idp; | ||
1067 | ih->identity = im->identity; | ||
1068 | GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity, | ||
1069 | &ih->ticket.identity); | ||
1070 | ih->ticket.audience = im->rp; | ||
1071 | ih->ticket.rnd = | ||
1072 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, | ||
1073 | UINT64_MAX); | ||
1074 | bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO); | ||
1075 | GNUNET_SERVICE_client_continue (idp->client); | ||
631 | 1076 | ||
632 | token_parse2 (token_record->data, | 1077 | } |
633 | &ecdhe_privkey, | ||
634 | aud_key, | ||
635 | &token); | ||
636 | 1078 | ||
637 | label = GNUNET_strdup (lbl); | 1079 | /********************************************************** |
638 | rd_exp = token_record->expiration_time; | 1080 | * Revocation |
1081 | **********************************************************/ | ||
639 | 1082 | ||
640 | GNUNET_SCHEDULER_add_now (&handle_token_update, | 1083 | /** |
641 | ego_entry); | 1084 | * Cleanup revoke handle |
1085 | */ | ||
1086 | static void | ||
1087 | cleanup_revoke_ticket_handle (struct TicketRevocationHandle *handle) | ||
1088 | { | ||
1089 | if (NULL != handle->attrs) | ||
1090 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs); | ||
1091 | if (NULL != handle->rvk_attrs) | ||
1092 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->rvk_attrs); | ||
1093 | if (NULL != handle->abe_key) | ||
1094 | GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key); | ||
1095 | if (NULL != handle->ns_qe) | ||
1096 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
1097 | if (NULL != handle->ns_it) | ||
1098 | GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it); | ||
1099 | GNUNET_free (handle); | ||
642 | } | 1100 | } |
643 | 1101 | ||
644 | 1102 | ||
1103 | /** | ||
1104 | * Send revocation result | ||
1105 | */ | ||
645 | static void | 1106 | static void |
646 | attribute_collect_error_cb (void *cls) | 1107 | send_revocation_finished (struct TicketRevocationHandle *rh, |
1108 | uint32_t success) | ||
647 | { | 1109 | { |
648 | struct EgoEntry *ego_entry = cls; | 1110 | struct GNUNET_MQ_Envelope *env; |
1111 | struct RevokeTicketResultMessage *trm; | ||
649 | 1112 | ||
650 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1113 | env = GNUNET_MQ_msg (trm, |
651 | ">>> Updating Attributes failed!\n"); | 1114 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT); |
652 | ego_entry->attributes_dirty = GNUNET_NO; | 1115 | trm->id = htonl (rh->r_id); |
653 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | 1116 | trm->success = htonl (success); |
654 | ego_entry); | 1117 | GNUNET_MQ_send (rh->client->mq, |
1118 | env); | ||
1119 | GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head, | ||
1120 | rh->client->revocation_list_tail, | ||
1121 | rh); | ||
655 | } | 1122 | } |
656 | 1123 | ||
657 | 1124 | ||
1125 | /** | ||
1126 | * Process ticket from database | ||
1127 | * | ||
1128 | * @param cls struct TicketIterationProcResult | ||
1129 | * @param ticket the ticket | ||
1130 | * @param attrs the attributes | ||
1131 | */ | ||
1132 | static void | ||
1133 | ticket_reissue_proc (void *cls, | ||
1134 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1135 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); | ||
1136 | |||
658 | static void | 1137 | static void |
659 | attribute_collect_finished_cb (void *cls) | 1138 | revocation_reissue_tickets (struct TicketRevocationHandle *rh); |
1139 | |||
1140 | |||
1141 | static void reissue_next (void *cls) | ||
660 | { | 1142 | { |
661 | struct EgoEntry *ego_entry = cls; | 1143 | struct TicketRevocationHandle *rh = cls; |
1144 | revocation_reissue_tickets (rh); | ||
1145 | } | ||
662 | 1146 | ||
663 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1147 | |
664 | ">>> Updating Attributes finished\n"); | 1148 | static void |
665 | ego_entry->attributes_dirty = GNUNET_NO; | 1149 | reissue_ticket_cont (void *cls, |
666 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | 1150 | int32_t success, |
667 | ego_entry); | 1151 | const char *emsg) |
1152 | { | ||
1153 | struct TicketRevocationHandle *rh = cls; | ||
1154 | |||
1155 | rh->ns_qe = NULL; | ||
1156 | if (GNUNET_SYSERR == success) | ||
1157 | { | ||
1158 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", | ||
1159 | "Unknown Error\n"); | ||
1160 | send_revocation_finished (rh, GNUNET_SYSERR); | ||
1161 | cleanup_revoke_ticket_handle (rh); | ||
1162 | return; | ||
1163 | } | ||
1164 | rh->offset++; | ||
1165 | GNUNET_SCHEDULER_add_now (&reissue_next, rh); | ||
668 | } | 1166 | } |
669 | 1167 | ||
670 | 1168 | ||
671 | /** | 1169 | /** |
1170 | * Process ticket from database | ||
672 | * | 1171 | * |
673 | * Collect all ID_ATTR records for an identity and store them | 1172 | * @param cls struct TicketIterationProcResult |
674 | * | 1173 | * @param ticket the ticket |
675 | * @param cls the identity entry | 1174 | * @param attrs the attributes |
676 | * @param zone the identity | ||
677 | * @param lbl the name of the record | ||
678 | * @param rd_count number of records | ||
679 | * @param rd record data | ||
680 | * | ||
681 | */ | 1175 | */ |
682 | static void | 1176 | static void |
683 | attribute_collect (void *cls, | 1177 | ticket_reissue_proc (void *cls, |
684 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 1178 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, |
685 | const char *lbl, | 1179 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) |
686 | unsigned int rd_count, | 1180 | { |
687 | const struct GNUNET_GNSRECORD_Data *rd) | 1181 | struct TicketRevocationHandle *rh = cls; |
688 | { | 1182 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; |
689 | struct EgoEntry *ego_entry = cls; | 1183 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover; |
690 | struct GNUNET_HashCode key; | 1184 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; |
691 | struct TokenAttr *attr; | 1185 | struct GNUNET_GNSRECORD_Data code_record[1]; |
692 | struct TokenAttrValue *val; | 1186 | struct GNUNET_CRYPTO_AbeKey *rp_key; |
693 | char *val_str; | 1187 | char *code_record_data; |
1188 | char **attr_arr; | ||
1189 | char *label; | ||
1190 | char *policy; | ||
1191 | int attrs_len; | ||
694 | int i; | 1192 | int i; |
1193 | int reissue_ticket; | ||
1194 | size_t code_record_len; | ||
1195 | |||
695 | 1196 | ||
696 | if (0 == rd_count) | 1197 | if (NULL == ticket) |
697 | { | 1198 | { |
698 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | 1199 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1200 | "Iteration done\n"); | ||
699 | return; | 1201 | return; |
700 | } | 1202 | } |
701 | GNUNET_CRYPTO_hash (lbl, | 1203 | |
702 | strlen (lbl), | 1204 | if (0 == memcmp (&ticket->audience, |
703 | &key); | 1205 | &rh->ticket.audience, |
704 | if (1 == rd_count) | 1206 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) |
705 | { | 1207 | { |
706 | if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | 1208 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
707 | { | 1209 | "Do not reissue for this identity.!\n"); |
708 | val_str = GNUNET_GNSRECORD_value_to_string (rd->record_type, | ||
709 | rd->data, | ||
710 | rd->data_size); | ||
711 | attr = GNUNET_malloc (sizeof (struct TokenAttr)); | ||
712 | attr->name = GNUNET_strdup (lbl); | ||
713 | val = GNUNET_malloc (sizeof (struct TokenAttrValue)); | ||
714 | val->value = val_str; | ||
715 | GNUNET_CONTAINER_DLL_insert (attr->val_head, | ||
716 | attr->val_tail, | ||
717 | val); | ||
718 | GNUNET_assert (GNUNET_OK == | ||
719 | GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map, | ||
720 | &key, | ||
721 | attr, | ||
722 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
723 | } | ||
724 | 1210 | ||
725 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | 1211 | rh->offset++; |
1212 | GNUNET_SCHEDULER_add_now (&reissue_next, rh); | ||
726 | return; | 1213 | return; |
727 | } | 1214 | } |
728 | 1215 | ||
729 | attr = GNUNET_malloc (sizeof (struct TokenAttr)); | 1216 | /* |
730 | attr->name = GNUNET_strdup (lbl); | 1217 | * Check if any attribute of this ticket intersects with a rollover attribute |
731 | for (i = 0; i < rd_count; i++) | 1218 | */ |
1219 | reissue_ticket = GNUNET_NO; | ||
1220 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
732 | { | 1221 | { |
733 | if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | 1222 | for (le_rollover = rh->rvk_attrs->list_head; |
1223 | NULL != le_rollover; | ||
1224 | le_rollover = le_rollover->next) | ||
734 | { | 1225 | { |
735 | val_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | 1226 | if (0 == strcmp (le_rollover->claim->name, |
736 | rd[i].data, | 1227 | le->claim->name)) |
737 | rd[i].data_size); | 1228 | { |
738 | val = GNUNET_malloc (sizeof (struct TokenAttrValue)); | 1229 | reissue_ticket = GNUNET_YES; |
739 | val->value = val_str; | 1230 | le->claim->version = le_rollover->claim->version; |
740 | GNUNET_CONTAINER_DLL_insert (attr->val_head, | 1231 | } |
741 | attr->val_tail, | ||
742 | val); | ||
743 | } | 1232 | } |
744 | } | 1233 | } |
745 | GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map, | ||
746 | &key, | ||
747 | attr, | ||
748 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
749 | GNUNET_NAMESTORE_zone_iterator_next (ns_it); | ||
750 | } | ||
751 | |||
752 | /** | ||
753 | * | ||
754 | * Update identity information for ego. If attribute map is | ||
755 | * dirty, first update the attributes. | ||
756 | * | ||
757 | * @param cls the ego to update | ||
758 | */ | ||
759 | static void | ||
760 | update_identities(void *cls) | ||
761 | { | ||
762 | struct EgoEntry *next_ego = cls; | ||
763 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
764 | 1234 | ||
765 | update_task = NULL; | 1235 | if (GNUNET_NO == reissue_ticket) |
766 | if (NULL == next_ego) | ||
767 | { | 1236 | { |
768 | if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us) | ||
769 | min_rel_exp = MIN_WAIT_TIME; | ||
770 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1237 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
771 | ">>> Finished. Rescheduling in %"SCNu64"\n", | 1238 | "Skipping ticket.\n"); |
772 | min_rel_exp.rel_value_us); | 1239 | |
773 | ns_it = NULL; | 1240 | rh->offset++; |
774 | //finished -> reschedule | 1241 | GNUNET_SCHEDULER_add_now (&reissue_next, rh); |
775 | update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, | 1242 | |
776 | &update_identities, | 1243 | |
777 | ego_head); | ||
778 | min_rel_exp.rel_value_us = 0; | ||
779 | return; | 1244 | return; |
780 | } | 1245 | } |
781 | priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego); | ||
782 | if (GNUNET_YES == next_ego->attributes_dirty) | ||
783 | { | ||
784 | //Starting over. We must update the Attributes for they might have changed. | ||
785 | ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
786 | priv_key, | ||
787 | &attribute_collect_error_cb, | ||
788 | next_ego, | ||
789 | &attribute_collect, | ||
790 | next_ego, | ||
791 | &attribute_collect_finished_cb, | ||
792 | next_ego); | ||
793 | 1246 | ||
1247 | //Create new ABE key for RP | ||
1248 | attrs_len = 0; | ||
1249 | |||
1250 | /* If this is the RP we want to revoke attributes of, the do so */ | ||
1251 | |||
1252 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
1253 | attrs_len++; | ||
1254 | attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*)); | ||
1255 | i = 0; | ||
1256 | for (le = attrs->list_head; NULL != le; le = le->next) { | ||
1257 | GNUNET_asprintf (&policy, "%s_%lu", | ||
1258 | le->claim->name, | ||
1259 | le->claim->version); | ||
1260 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1261 | "Recreating key with %s\n", policy); | ||
1262 | attr_arr[i] = policy; | ||
1263 | i++; | ||
1264 | } | ||
1265 | attr_arr[i] = NULL; | ||
1266 | rp_key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key, | ||
1267 | attr_arr); | ||
1268 | |||
1269 | //TODO review this wireformat | ||
1270 | code_record_len = serialize_abe_keyinfo2 (ticket, | ||
1271 | attrs, | ||
1272 | rp_key, | ||
1273 | &ecdhe_privkey, | ||
1274 | &code_record_data); | ||
1275 | code_record[0].data = code_record_data; | ||
1276 | code_record[0].data_size = code_record_len; | ||
1277 | code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us; | ||
1278 | code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY; | ||
1279 | code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1280 | |||
1281 | label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, | ||
1282 | sizeof (uint64_t)); | ||
1283 | //Publish record | ||
1284 | rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1285 | &rh->identity, | ||
1286 | label, | ||
1287 | 1, | ||
1288 | code_record, | ||
1289 | &reissue_ticket_cont, | ||
1290 | rh); | ||
1291 | //for (; i > 0; i--) | ||
1292 | // GNUNET_free (attr_arr[i-1]); | ||
1293 | GNUNET_free (ecdhe_privkey); | ||
1294 | GNUNET_free (label); | ||
1295 | GNUNET_free (attr_arr); | ||
1296 | GNUNET_free (code_record_data); | ||
1297 | GNUNET_CRYPTO_cpabe_delete_key (rp_key, GNUNET_YES); | ||
1298 | } | ||
1299 | |||
1300 | |||
1301 | /* Prototype for below function */ | ||
1302 | static void | ||
1303 | attr_reenc_cont (void *cls, | ||
1304 | int32_t success, | ||
1305 | const char *emsg); | ||
1306 | |||
1307 | static void | ||
1308 | revocation_reissue_tickets (struct TicketRevocationHandle *rh) | ||
1309 | { | ||
1310 | int ret; | ||
1311 | /* Done, issue new keys */ | ||
1312 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1313 | "Revocation Phase III: Reissuing Tickets\n"); | ||
1314 | if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls, | ||
1315 | &rh->ticket.identity, | ||
1316 | GNUNET_NO, | ||
1317 | rh->offset, | ||
1318 | &ticket_reissue_proc, | ||
1319 | rh))) | ||
1320 | { | ||
1321 | GNUNET_break (0); | ||
794 | } | 1322 | } |
795 | else | 1323 | if (GNUNET_NO == ret) |
796 | { | 1324 | { |
797 | //Ego will be dirty next time | 1325 | send_revocation_finished (rh, GNUNET_OK); |
798 | next_ego->attributes_dirty = GNUNET_YES; | 1326 | cleanup_revoke_ticket_handle (rh); |
799 | ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | 1327 | return; |
800 | priv_key, | ||
801 | &token_collect_error_cb, | ||
802 | next_ego, | ||
803 | &token_collect, | ||
804 | next_ego, | ||
805 | &token_collect_finished_cb, | ||
806 | next_ego); | ||
807 | } | 1328 | } |
808 | } | 1329 | } |
809 | 1330 | ||
810 | |||
811 | /** | 1331 | /** |
812 | * Function called initially to start update task | 1332 | * Revoke next attribte by reencryption with |
1333 | * new ABE master | ||
813 | */ | 1334 | */ |
814 | static void | 1335 | static void |
815 | init_cont () | 1336 | reenc_next_attribute (struct TicketRevocationHandle *rh) |
816 | { | 1337 | { |
817 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n"); | 1338 | struct GNUNET_GNSRECORD_Data rd[1]; |
818 | //Initially iterate all itenties and refresh all tokens | 1339 | char* buf; |
819 | update_task = GNUNET_SCHEDULER_add_now (&update_identities, | 1340 | char* enc_buf; |
820 | ego_head); | 1341 | size_t enc_size; |
1342 | char* rd_buf; | ||
1343 | size_t buf_size; | ||
1344 | char* policy; | ||
1345 | uint32_t attr_ver; | ||
1346 | |||
1347 | if (NULL == rh->attrs->list_head) | ||
1348 | { | ||
1349 | revocation_reissue_tickets (rh); | ||
1350 | return; | ||
1351 | } | ||
1352 | buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim); | ||
1353 | buf = GNUNET_malloc (buf_size); | ||
1354 | GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim, | ||
1355 | buf); | ||
1356 | rh->attrs->list_head->claim->version++; | ||
1357 | GNUNET_asprintf (&policy, "%s_%lu", | ||
1358 | rh->attrs->list_head->claim->name, | ||
1359 | rh->attrs->list_head->claim->version); | ||
1360 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1361 | "Encrypting with policy %s\n", policy); | ||
1362 | /** | ||
1363 | * Encrypt the attribute value and store in namestore | ||
1364 | */ | ||
1365 | enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf, | ||
1366 | buf_size, | ||
1367 | policy, //Policy | ||
1368 | rh->abe_key, | ||
1369 | (void**)&enc_buf); | ||
1370 | GNUNET_free (buf); | ||
1371 | GNUNET_free (policy); | ||
1372 | rd[0].data_size = enc_size + sizeof (uint32_t); | ||
1373 | rd_buf = GNUNET_malloc (rd[0].data_size); | ||
1374 | attr_ver = htonl (rh->attrs->list_head->claim->version); | ||
1375 | GNUNET_memcpy (rd_buf, | ||
1376 | &attr_ver, | ||
1377 | sizeof (uint32_t)); | ||
1378 | GNUNET_memcpy (rd_buf+sizeof (uint32_t), | ||
1379 | enc_buf, | ||
1380 | enc_size); | ||
1381 | rd[0].data = rd_buf; | ||
1382 | rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR; | ||
1383 | rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1384 | rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane? | ||
1385 | rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1386 | &rh->identity, | ||
1387 | rh->attrs->list_head->claim->name, | ||
1388 | 1, | ||
1389 | rd, | ||
1390 | &attr_reenc_cont, | ||
1391 | rh); | ||
1392 | GNUNET_free (enc_buf); | ||
1393 | GNUNET_free (rd_buf); | ||
821 | } | 1394 | } |
822 | 1395 | ||
823 | |||
824 | /** | 1396 | /** |
825 | * Initial ego collection function. | 1397 | * Namestore callback after revoked attribute |
826 | * | 1398 | * is stored |
827 | * @param cls NULL | ||
828 | * @param ego ego | ||
829 | * @param ctx context | ||
830 | * @param identifier ego name | ||
831 | */ | 1399 | */ |
832 | static void | 1400 | static void |
833 | list_ego (void *cls, | 1401 | attr_reenc_cont (void *cls, |
834 | struct GNUNET_IDENTITY_Ego *ego, | 1402 | int32_t success, |
835 | void **ctx, | 1403 | const char *emsg) |
836 | const char *identifier) | ||
837 | { | 1404 | { |
838 | struct EgoEntry *new_entry; | 1405 | struct TicketRevocationHandle *rh = cls; |
839 | if ((NULL == ego) && (STATE_INIT == state)) | 1406 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; |
1407 | |||
1408 | if (GNUNET_SYSERR == success) | ||
840 | { | 1409 | { |
841 | state = STATE_POST_INIT; | 1410 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
842 | init_cont (); | 1411 | "Failed to reencrypt attribute %s\n", |
1412 | emsg); | ||
1413 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
843 | return; | 1414 | return; |
844 | } | 1415 | } |
845 | if (STATE_INIT == state) { | 1416 | if (NULL == rh->attrs->list_head) |
846 | new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); | 1417 | { |
847 | new_entry->ego = ego; | 1418 | revocation_reissue_tickets (rh); |
848 | new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5, | 1419 | return; |
849 | GNUNET_NO); | ||
850 | new_entry->attributes_dirty = GNUNET_YES; | ||
851 | GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry); | ||
852 | } | 1420 | } |
1421 | le = rh->attrs->list_head; | ||
1422 | GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head, | ||
1423 | rh->attrs->list_tail, | ||
1424 | le); | ||
1425 | GNUNET_assert (NULL != rh->rvk_attrs); | ||
1426 | GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head, | ||
1427 | rh->rvk_attrs->list_tail, | ||
1428 | le); | ||
1429 | |||
1430 | |||
1431 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1432 | "Re-encrypting next attribute\n"); | ||
1433 | reenc_next_attribute (rh); | ||
853 | } | 1434 | } |
854 | 1435 | ||
855 | /** | 1436 | |
856 | * Cleanup task | ||
857 | */ | ||
858 | static void | 1437 | static void |
859 | cleanup() | 1438 | process_attributes_to_update (void *cls, |
1439 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1440 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) | ||
860 | { | 1441 | { |
861 | struct EgoEntry *ego_entry; | 1442 | struct TicketRevocationHandle *rh = cls; |
862 | struct EgoEntry *ego_tmp; | ||
863 | 1443 | ||
1444 | rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs); | ||
864 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1445 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
865 | "Cleaning up\n"); | 1446 | "Revocation Phase I: Collecting attributes\n"); |
866 | if (NULL != stats) | 1447 | /* Reencrypt all attributes with new key */ |
1448 | if (NULL == rh->attrs->list_head) | ||
867 | { | 1449 | { |
868 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | 1450 | /* No attributes to reencrypt */ |
869 | stats = NULL; | 1451 | send_revocation_finished (rh, GNUNET_OK); |
1452 | cleanup_revoke_ticket_handle (rh); | ||
1453 | return; | ||
1454 | } else { | ||
1455 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1456 | "Revocation Phase II: Re-encrypting attributes\n"); | ||
1457 | reenc_next_attribute (rh); | ||
870 | } | 1458 | } |
871 | 1459 | ||
872 | if (NULL != timeout_task) | 1460 | } |
873 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
874 | if (NULL != update_task) | ||
875 | GNUNET_SCHEDULER_cancel (update_task); | ||
876 | if (NULL != identity_handle) | ||
877 | GNUNET_IDENTITY_disconnect (identity_handle); | ||
878 | if (NULL != gns_handle) | ||
879 | GNUNET_GNS_disconnect (gns_handle); | ||
880 | if (NULL != ns_it) | ||
881 | GNUNET_NAMESTORE_zone_iteration_stop (ns_it); | ||
882 | if (NULL != ns_qe) | ||
883 | GNUNET_NAMESTORE_cancel (ns_qe); | ||
884 | if (NULL != ns_handle) | ||
885 | GNUNET_NAMESTORE_disconnect (ns_handle); | ||
886 | if (NULL != token) | ||
887 | GNUNET_free (token); | ||
888 | if (NULL != label) | ||
889 | GNUNET_free (label); | ||
890 | 1461 | ||
891 | for (ego_entry = ego_head; | ||
892 | NULL != ego_entry;) | ||
893 | { | ||
894 | ego_tmp = ego_entry; | ||
895 | if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map)) | ||
896 | { | ||
897 | GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map, | ||
898 | &clear_ego_attrs, | ||
899 | ego_tmp); | ||
900 | 1462 | ||
901 | } | 1463 | |
902 | GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map); | 1464 | static void |
903 | ego_entry = ego_entry->next; | 1465 | get_ticket_after_abe_bootstrap (void *cls, |
904 | GNUNET_free (ego_tmp); | 1466 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key) |
905 | } | 1467 | { |
1468 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1469 | "Finished ABE bootstrap\n"); | ||
1470 | struct TicketRevocationHandle *rh = cls; | ||
1471 | rh->abe_key = abe_key; | ||
1472 | TKT_database->get_ticket_attributes (TKT_database->cls, | ||
1473 | &rh->ticket, | ||
1474 | &process_attributes_to_update, | ||
1475 | rh); | ||
906 | } | 1476 | } |
907 | 1477 | ||
908 | /** | 1478 | /** |
909 | * Shutdown task | 1479 | * Checks a ticket revocation message |
910 | * | 1480 | * |
911 | * @param cls NULL | 1481 | * @param cls client sending the message |
912 | * @param tc task context | 1482 | * @param im message of type `struct RevokeTicketMessage` |
1483 | * @return #GNUNET_OK if @a im is well-formed | ||
913 | */ | 1484 | */ |
914 | static void | 1485 | static int |
915 | do_shutdown (void *cls) | 1486 | check_revoke_ticket_message(void *cls, |
1487 | const struct RevokeTicketMessage *im) | ||
916 | { | 1488 | { |
917 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1489 | uint16_t size; |
918 | "Shutting down...\n"); | ||
919 | cleanup(); | ||
920 | } | ||
921 | |||
922 | 1490 | ||
923 | static struct GNUNET_MQ_Envelope* | 1491 | size = ntohs (im->header.size); |
924 | create_exchange_result_message (const char* token, | 1492 | if (size <= sizeof (struct RevokeTicketMessage)) |
925 | const char* label, | 1493 | { |
926 | uint64_t ticket_nonce, | 1494 | GNUNET_break (0); |
927 | uint64_t id) | 1495 | return GNUNET_SYSERR; |
928 | { | 1496 | } |
929 | struct GNUNET_MQ_Envelope *env; | 1497 | return GNUNET_OK; |
930 | struct ExchangeResultMessage *erm; | ||
931 | uint16_t token_len = strlen (token) + 1; | ||
932 | |||
933 | env = GNUNET_MQ_msg_extra (erm, | ||
934 | token_len, | ||
935 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT); | ||
936 | erm->ticket_nonce = htonl (ticket_nonce); | ||
937 | erm->id = id; | ||
938 | GNUNET_memcpy (&erm[1], token, token_len); | ||
939 | return env; | ||
940 | } | 1498 | } |
941 | 1499 | /** | |
942 | 1500 | * | |
943 | static struct GNUNET_MQ_Envelope* | 1501 | * Handler for ticket revocation message |
944 | create_issue_result_message (const char* label, | 1502 | * |
945 | const char* ticket, | 1503 | * @param cls unused |
946 | const char* token, | 1504 | * @param client who sent the message |
947 | uint64_t id) | 1505 | * @param message the message |
1506 | */ | ||
1507 | static void | ||
1508 | handle_revoke_ticket_message (void *cls, | ||
1509 | const struct RevokeTicketMessage *rm) | ||
948 | { | 1510 | { |
949 | struct GNUNET_MQ_Envelope *env; | 1511 | struct TicketRevocationHandle *rh; |
950 | struct IssueResultMessage *irm; | 1512 | struct IdpClient *idp = cls; |
951 | char *tmp_str; | 1513 | struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; |
952 | size_t len; | 1514 | |
1515 | rh = GNUNET_new (struct TicketRevocationHandle); | ||
1516 | ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1]; | ||
1517 | rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); | ||
1518 | rh->ticket = *ticket; | ||
1519 | rh->r_id = ntohl (rm->id); | ||
1520 | rh->client = idp; | ||
1521 | rh->identity = rm->identity; | ||
1522 | GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity, | ||
1523 | &rh->ticket.identity); | ||
1524 | GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head, | ||
1525 | idp->revocation_list_tail, | ||
1526 | rh); | ||
1527 | bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO); | ||
1528 | GNUNET_SERVICE_client_continue (idp->client); | ||
953 | 1529 | ||
954 | GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token); | ||
955 | len = strlen (tmp_str) + 1; | ||
956 | env = GNUNET_MQ_msg_extra (irm, | ||
957 | len, | ||
958 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT); | ||
959 | irm->id = id; | ||
960 | GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1); | ||
961 | GNUNET_free (tmp_str); | ||
962 | return env; | ||
963 | } | 1530 | } |
964 | 1531 | ||
965 | static void | ||
966 | cleanup_issue_handle (struct IssueHandle *handle) | ||
967 | { | ||
968 | if (NULL != handle->attr_map) | ||
969 | GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map); | ||
970 | if (NULL != handle->scopes) | ||
971 | GNUNET_free (handle->scopes); | ||
972 | if (NULL != handle->token) | ||
973 | token_destroy (handle->token); | ||
974 | if (NULL != handle->ticket) | ||
975 | ticket_destroy (handle->ticket); | ||
976 | if (NULL != handle->label) | ||
977 | GNUNET_free (handle->label); | ||
978 | GNUNET_free (handle); | ||
979 | } | ||
980 | 1532 | ||
981 | static void | 1533 | static void |
982 | store_token_issue_cont (void *cls, | 1534 | cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle) |
983 | int32_t success, | ||
984 | const char *emsg) | ||
985 | { | 1535 | { |
986 | struct IssueHandle *handle = cls; | 1536 | if (NULL != handle->key) |
987 | struct GNUNET_MQ_Envelope *env; | 1537 | GNUNET_CRYPTO_cpabe_delete_key (handle->key, |
988 | char *ticket_str; | 1538 | GNUNET_YES); |
989 | char *token_str; | 1539 | if (NULL != handle->attrs) |
990 | 1540 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs); | |
991 | handle->ns_qe = NULL; | 1541 | GNUNET_free (handle); |
992 | if (GNUNET_SYSERR == success) | ||
993 | { | ||
994 | cleanup_issue_handle (handle); | ||
995 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", | ||
996 | "Unknown Error\n"); | ||
997 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
998 | return; | ||
999 | } | ||
1000 | if (GNUNET_OK != ticket_serialize (handle->ticket, | ||
1001 | &handle->iss_key, | ||
1002 | &ticket_str)) | ||
1003 | { | ||
1004 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", | ||
1005 | "Error serializing ticket\n"); | ||
1006 | cleanup_issue_handle (handle); | ||
1007 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
1008 | return; | ||
1009 | } | ||
1010 | if (GNUNET_OK != token_to_string (handle->token, | ||
1011 | &handle->iss_key, | ||
1012 | &token_str)) | ||
1013 | { | ||
1014 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", | ||
1015 | "Error serializing token\n"); | ||
1016 | GNUNET_free (ticket_str); | ||
1017 | cleanup_issue_handle (handle); | ||
1018 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
1019 | return; | ||
1020 | } | ||
1021 | env = create_issue_result_message (handle->label, | ||
1022 | ticket_str, | ||
1023 | token_str, | ||
1024 | handle->r_id); | ||
1025 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client), | ||
1026 | env); | ||
1027 | cleanup_issue_handle (handle); | ||
1028 | GNUNET_free (ticket_str); | ||
1029 | GNUNET_free (token_str); | ||
1030 | } | 1542 | } |
1031 | 1543 | ||
1032 | 1544 | ||
1545 | |||
1033 | /** | 1546 | /** |
1034 | * Build a token and store it | 1547 | * Checks a ticket consume message |
1035 | * | 1548 | * |
1036 | * @param cls the IssueHandle | 1549 | * @param cls client sending the message |
1550 | * @param im message of type `struct ConsumeTicketMessage` | ||
1551 | * @return #GNUNET_OK if @a im is well-formed | ||
1037 | */ | 1552 | */ |
1038 | static void | 1553 | static int |
1039 | sign_and_return_token (void *cls) | 1554 | check_consume_ticket_message(void *cls, |
1555 | const struct ConsumeTicketMessage *cm) | ||
1040 | { | 1556 | { |
1041 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | 1557 | uint16_t size; |
1042 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; | ||
1043 | struct IssueHandle *handle = cls; | ||
1044 | struct GNUNET_GNSRECORD_Data token_record[2]; | ||
1045 | char *nonce_str; | ||
1046 | char *enc_token_str; | ||
1047 | char *token_metadata; | ||
1048 | char* write_ptr; | ||
1049 | uint64_t time; | ||
1050 | uint64_t exp_time; | ||
1051 | size_t token_metadata_len; | ||
1052 | |||
1053 | //Remote nonce | ||
1054 | nonce_str = NULL; | ||
1055 | GNUNET_asprintf (&nonce_str, "%lu", handle->nonce); | ||
1056 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str); | ||
1057 | |||
1058 | GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key, | ||
1059 | &pub_key); | ||
1060 | handle->ticket = ticket_create (handle->nonce, | ||
1061 | &pub_key, | ||
1062 | handle->label, | ||
1063 | &handle->aud_key); | ||
1064 | |||
1065 | time = GNUNET_TIME_absolute_get().abs_value_us; | ||
1066 | exp_time = time + token_expiration_interval.rel_value_us; | ||
1067 | |||
1068 | token_add_attr_int (handle->token, "nbf", time); | ||
1069 | token_add_attr_int (handle->token, "iat", time); | ||
1070 | token_add_attr_int (handle->token, "exp", exp_time); | ||
1071 | token_add_attr (handle->token, "nonce", nonce_str); | ||
1072 | |||
1073 | //Token in a serialized encrypted format | ||
1074 | GNUNET_assert (token_serialize (handle->token, | ||
1075 | &handle->iss_key, | ||
1076 | &ecdhe_privkey, | ||
1077 | &enc_token_str)); | ||
1078 | |||
1079 | //Token record E,E_K (Token) | ||
1080 | token_record[0].data = enc_token_str; | ||
1081 | token_record[0].data_size = strlen (enc_token_str) + 1; | ||
1082 | token_record[0].expiration_time = exp_time; | ||
1083 | token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; | ||
1084 | token_record[0].flags = GNUNET_GNSRECORD_RF_NONE; | ||
1085 | |||
1086 | |||
1087 | token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) | ||
1088 | + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) | ||
1089 | + strlen (handle->scopes) + 1; //With 0-Terminator | ||
1090 | token_metadata = GNUNET_malloc (token_metadata_len); | ||
1091 | write_ptr = token_metadata; | ||
1092 | GNUNET_memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); | ||
1093 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); | ||
1094 | GNUNET_memcpy (write_ptr, &handle->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1095 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
1096 | GNUNET_memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); //with 0-Terminator; | ||
1097 | |||
1098 | token_record[1].data = token_metadata; | ||
1099 | token_record[1].data_size = token_metadata_len; | ||
1100 | token_record[1].expiration_time = exp_time; | ||
1101 | token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA; | ||
1102 | token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; | ||
1103 | |||
1104 | //Persist token | ||
1105 | handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1106 | &handle->iss_key, | ||
1107 | handle->label, | ||
1108 | 2, | ||
1109 | token_record, | ||
1110 | &store_token_issue_cont, | ||
1111 | handle); | ||
1112 | GNUNET_free (ecdhe_privkey); | ||
1113 | GNUNET_free (nonce_str); | ||
1114 | GNUNET_free (enc_token_str); | ||
1115 | GNUNET_free (token_metadata); | ||
1116 | } | ||
1117 | 1558 | ||
1559 | size = ntohs (cm->header.size); | ||
1560 | if (size <= sizeof (struct ConsumeTicketMessage)) | ||
1561 | { | ||
1562 | GNUNET_break (0); | ||
1563 | return GNUNET_SYSERR; | ||
1564 | } | ||
1565 | return GNUNET_OK; | ||
1566 | } | ||
1118 | 1567 | ||
1119 | static void | 1568 | static void |
1120 | attr_collect_error (void *cls) | 1569 | process_parallel_lookup2 (void *cls, uint32_t rd_count, |
1570 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1121 | { | 1571 | { |
1122 | struct IssueHandle *handle = cls; | 1572 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1573 | "Parallel lookup finished (count=%u)\n", rd_count); | ||
1574 | struct ParallelLookup *parallel_lookup = cls; | ||
1575 | struct ConsumeTicketHandle *handle = parallel_lookup->handle; | ||
1576 | struct ConsumeTicketResultMessage *crm; | ||
1577 | struct GNUNET_MQ_Envelope *env; | ||
1578 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le; | ||
1579 | struct GNUNET_TIME_Absolute decrypt_duration; | ||
1580 | char *data; | ||
1581 | char *data_tmp; | ||
1582 | ssize_t attr_len; | ||
1583 | size_t attrs_len; | ||
1584 | |||
1585 | GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head, | ||
1586 | handle->parallel_lookups_tail, | ||
1587 | parallel_lookup); | ||
1588 | GNUNET_free (parallel_lookup->label); | ||
1589 | |||
1590 | GNUNET_STATISTICS_update (stats_handle, | ||
1591 | "attribute_lookup_time_total", | ||
1592 | GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us, | ||
1593 | GNUNET_YES); | ||
1594 | GNUNET_STATISTICS_update (stats_handle, | ||
1595 | "attribute_lookups_count", | ||
1596 | 1, | ||
1597 | GNUNET_YES); | ||
1598 | |||
1599 | |||
1600 | GNUNET_free (parallel_lookup); | ||
1601 | if (1 != rd_count) | ||
1602 | GNUNET_break(0);//TODO | ||
1603 | if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | ||
1604 | { | ||
1605 | decrypt_duration = GNUNET_TIME_absolute_get (); | ||
1606 | attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data + sizeof (uint32_t), | ||
1607 | rd->data_size - sizeof (uint32_t), | ||
1608 | handle->key, | ||
1609 | (void**)&data); | ||
1610 | if (GNUNET_SYSERR != attr_len) | ||
1611 | { | ||
1612 | GNUNET_STATISTICS_update (stats_handle, | ||
1613 | "abe_decrypt_time_total", | ||
1614 | GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us, | ||
1615 | GNUNET_YES); | ||
1616 | GNUNET_STATISTICS_update (stats_handle, | ||
1617 | "abe_decrypt_count", | ||
1618 | 1, | ||
1619 | GNUNET_YES); | ||
1620 | |||
1621 | attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry); | ||
1622 | attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data, | ||
1623 | attr_len); | ||
1624 | attr_le->claim->version = ntohl(*(uint32_t*)rd->data); | ||
1625 | GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head, | ||
1626 | handle->attrs->list_tail, | ||
1627 | attr_le); | ||
1628 | GNUNET_free (data); | ||
1629 | } | ||
1630 | } | ||
1631 | if (NULL != handle->parallel_lookups_head) | ||
1632 | return; //Wait for more | ||
1633 | /* Else we are done */ | ||
1634 | |||
1635 | /* Store ticket in DB */ | ||
1636 | if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls, | ||
1637 | &handle->ticket, | ||
1638 | handle->attrs)) | ||
1639 | { | ||
1640 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1641 | "Unable to store ticket after consume\n"); | ||
1642 | GNUNET_break (0); | ||
1643 | } | ||
1123 | 1644 | ||
1124 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n"); | 1645 | GNUNET_SCHEDULER_cancel (handle->kill_task); |
1125 | handle->ns_it = NULL; | 1646 | attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs); |
1126 | GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); | 1647 | env = GNUNET_MQ_msg_extra (crm, |
1648 | attrs_len, | ||
1649 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT); | ||
1650 | crm->id = htonl (handle->r_id); | ||
1651 | crm->attrs_len = htons (attrs_len); | ||
1652 | crm->identity = handle->ticket.identity; | ||
1653 | data_tmp = (char *) &crm[1]; | ||
1654 | GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs, | ||
1655 | data_tmp); | ||
1656 | GNUNET_MQ_send (handle->client->mq, env); | ||
1657 | cleanup_consume_ticket_handle (handle); | ||
1127 | } | 1658 | } |
1128 | 1659 | ||
1129 | 1660 | void | |
1130 | static void | 1661 | abort_parallel_lookups2 (void *cls) |
1131 | attr_collect_finished (void *cls) | ||
1132 | { | 1662 | { |
1133 | struct IssueHandle *handle = cls; | 1663 | struct ConsumeTicketHandle *handle = cls; |
1664 | struct ParallelLookup *lu; | ||
1665 | struct ParallelLookup *tmp; | ||
1666 | struct AttributeResultMessage *arm; | ||
1667 | struct GNUNET_MQ_Envelope *env; | ||
1668 | |||
1669 | for (lu = handle->parallel_lookups_head; | ||
1670 | NULL != lu;) { | ||
1671 | GNUNET_GNS_lookup_cancel (lu->lookup_request); | ||
1672 | GNUNET_free (lu->label); | ||
1673 | tmp = lu->next; | ||
1674 | GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head, | ||
1675 | handle->parallel_lookups_tail, | ||
1676 | lu); | ||
1677 | GNUNET_free (lu); | ||
1678 | lu = tmp; | ||
1679 | } | ||
1680 | env = GNUNET_MQ_msg (arm, | ||
1681 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT); | ||
1682 | arm->id = htonl (handle->r_id); | ||
1683 | arm->attr_len = htons (0); | ||
1684 | GNUNET_MQ_send (handle->client->mq, env); | ||
1134 | 1685 | ||
1135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n"); | ||
1136 | handle->ns_it = NULL; | ||
1137 | GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); | ||
1138 | } | 1686 | } |
1139 | 1687 | ||
1140 | 1688 | ||
1141 | /** | ||
1142 | * Collect attributes for token | ||
1143 | */ | ||
1144 | static void | 1689 | static void |
1145 | attr_collect (void *cls, | 1690 | process_consume_abe_key (void *cls, uint32_t rd_count, |
1146 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 1691 | const struct GNUNET_GNSRECORD_Data *rd) |
1147 | const char *label, | ||
1148 | unsigned int rd_count, | ||
1149 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1150 | { | 1692 | { |
1151 | struct IssueHandle *handle = cls; | 1693 | struct ConsumeTicketHandle *handle = cls; |
1152 | int i; | 1694 | struct GNUNET_HashCode new_key_hash; |
1153 | char* data; | 1695 | struct GNUNET_CRYPTO_SymmetricSessionKey enc_key; |
1154 | struct GNUNET_HashCode key; | 1696 | struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv; |
1155 | 1697 | struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key; | |
1156 | GNUNET_CRYPTO_hash (label, | 1698 | struct ParallelLookup *parallel_lookup; |
1157 | strlen (label), | 1699 | size_t size; |
1158 | &key); | 1700 | char *buf; |
1159 | 1701 | char *scope; | |
1160 | if (0 == rd_count || | 1702 | char *lookup_query; |
1161 | ( (NULL != handle->attr_map) && | 1703 | |
1162 | (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, | 1704 | handle->lookup_request = NULL; |
1163 | &key)) | 1705 | if (1 != rd_count) |
1164 | ) | ||
1165 | ) | ||
1166 | { | 1706 | { |
1167 | GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); | 1707 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1708 | "Number of keys %d != 1.", | ||
1709 | rd_count); | ||
1710 | cleanup_consume_ticket_handle (handle); | ||
1711 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
1168 | return; | 1712 | return; |
1169 | } | 1713 | } |
1170 | 1714 | ||
1171 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label); | 1715 | //Decrypt |
1716 | ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data; | ||
1717 | |||
1718 | buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); | ||
1719 | |||
1720 | //Calculate symmetric key from ecdh parameters | ||
1721 | GNUNET_assert (GNUNET_OK == | ||
1722 | GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity, | ||
1723 | ecdh_key, | ||
1724 | &new_key_hash)); | ||
1725 | create_sym_key_from_ecdh (&new_key_hash, | ||
1726 | &enc_key, | ||
1727 | &enc_iv); | ||
1728 | size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey), | ||
1729 | rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey), | ||
1730 | &enc_key, | ||
1731 | &enc_iv, | ||
1732 | buf); | ||
1172 | 1733 | ||
1173 | if (1 == rd_count) | 1734 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1174 | { | 1735 | "Decrypted bytes: %zd Expected bytes: %zd\n", |
1175 | if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | 1736 | size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); |
1176 | { | 1737 | GNUNET_STATISTICS_update (stats_handle, |
1177 | data = GNUNET_GNSRECORD_value_to_string (rd->record_type, | 1738 | "abe_key_lookup_time_total", |
1178 | rd->data, | 1739 | GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us, |
1179 | rd->data_size); | 1740 | GNUNET_YES); |
1180 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data); | 1741 | GNUNET_STATISTICS_update (stats_handle, |
1181 | token_add_attr (handle->token, | 1742 | "abe_key_lookups_count", |
1182 | label, | 1743 | 1, |
1183 | data); | 1744 | GNUNET_YES); |
1184 | GNUNET_free (data); | 1745 | scopes = GNUNET_strdup (buf); |
1185 | } | 1746 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1186 | GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); | 1747 | "Scopes %s\n", scopes); |
1187 | return; | 1748 | handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1), |
1188 | } | 1749 | rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) |
1750 | - strlen (scopes) - 1); | ||
1189 | 1751 | ||
1190 | i = 0; | 1752 | for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ",")) |
1191 | for (; i < rd_count; i++) | ||
1192 | { | 1753 | { |
1193 | if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | 1754 | GNUNET_asprintf (&lookup_query, |
1194 | { | 1755 | "%s.gnu", |
1195 | data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | 1756 | scope); |
1196 | rd[i].data, | 1757 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1197 | rd[i].data_size); | 1758 | "Looking up %s\n", lookup_query); |
1198 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data); | 1759 | parallel_lookup = GNUNET_new (struct ParallelLookup); |
1199 | token_add_attr (handle->token, label, data); | 1760 | parallel_lookup->handle = handle; |
1200 | GNUNET_free (data); | 1761 | parallel_lookup->label = GNUNET_strdup (scope); |
1201 | } | 1762 | parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get(); |
1763 | parallel_lookup->lookup_request | ||
1764 | = GNUNET_GNS_lookup (gns_handle, | ||
1765 | lookup_query, | ||
1766 | &handle->ticket.identity, | ||
1767 | GNUNET_GNSRECORD_TYPE_ID_ATTR, | ||
1768 | GNUNET_GNS_LO_DEFAULT, | ||
1769 | &process_parallel_lookup2, | ||
1770 | parallel_lookup); | ||
1771 | GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head, | ||
1772 | handle->parallel_lookups_tail, | ||
1773 | parallel_lookup); | ||
1774 | GNUNET_free (lookup_query); | ||
1202 | } | 1775 | } |
1776 | GNUNET_free (scopes); | ||
1777 | GNUNET_free (buf); | ||
1778 | handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3), | ||
1779 | &abort_parallel_lookups2, | ||
1780 | handle); | ||
1781 | } | ||
1203 | 1782 | ||
1204 | GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); | 1783 | |
1784 | /** | ||
1785 | * | ||
1786 | * Handler for ticket issue message | ||
1787 | * | ||
1788 | * @param cls unused | ||
1789 | * @param client who sent the message | ||
1790 | * @param message the message | ||
1791 | */ | ||
1792 | static void | ||
1793 | handle_consume_ticket_message (void *cls, | ||
1794 | const struct ConsumeTicketMessage *cm) | ||
1795 | { | ||
1796 | struct ConsumeTicketHandle *ch; | ||
1797 | struct IdpClient *idp = cls; | ||
1798 | char* lookup_query; | ||
1799 | char* rnd_label; | ||
1800 | |||
1801 | ch = GNUNET_new (struct ConsumeTicketHandle); | ||
1802 | ch->r_id = ntohl (cm->id); | ||
1803 | ch->client = idp; | ||
1804 | ch->identity = cm->identity; | ||
1805 | ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); | ||
1806 | GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity, | ||
1807 | &ch->identity_pub); | ||
1808 | ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]); | ||
1809 | rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd, | ||
1810 | sizeof (uint64_t)); | ||
1811 | GNUNET_asprintf (&lookup_query, | ||
1812 | "%s.gnu", | ||
1813 | rnd_label); | ||
1814 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1815 | "Looking for ABE key under %s\n", lookup_query); | ||
1816 | ch->lookup_start_time = GNUNET_TIME_absolute_get (); | ||
1817 | ch->lookup_request | ||
1818 | = GNUNET_GNS_lookup (gns_handle, | ||
1819 | lookup_query, | ||
1820 | &ch->ticket.identity, | ||
1821 | GNUNET_GNSRECORD_TYPE_ABE_KEY, | ||
1822 | GNUNET_GNS_LO_DEFAULT, | ||
1823 | &process_consume_abe_key, | ||
1824 | ch); | ||
1825 | GNUNET_free (rnd_label); | ||
1826 | GNUNET_free (lookup_query); | ||
1827 | GNUNET_SERVICE_client_continue (idp->client); | ||
1205 | } | 1828 | } |
1206 | 1829 | ||
1207 | static void | 1830 | static void |
1208 | cleanup_exchange_handle (struct ExchangeHandle *handle) | 1831 | cleanup_as_handle (struct AttributeStoreHandle *handle) |
1209 | { | 1832 | { |
1210 | if (NULL != handle->ticket) | 1833 | if (NULL != handle->claim) |
1211 | ticket_destroy (handle->ticket); | 1834 | GNUNET_free (handle->claim); |
1212 | if (NULL != handle->token) | 1835 | if (NULL != handle->abe_key) |
1213 | token_destroy (handle->token); | 1836 | GNUNET_CRYPTO_cpabe_delete_master_key (handle->abe_key); |
1214 | GNUNET_free (handle); | 1837 | GNUNET_free (handle); |
1215 | } | 1838 | } |
1216 | 1839 | ||
1217 | static void | 1840 | static void |
1218 | process_lookup_result (void *cls, uint32_t rd_count, | 1841 | attr_store_cont (void *cls, |
1219 | const struct GNUNET_GNSRECORD_Data *rd) | 1842 | int32_t success, |
1843 | const char *emsg) | ||
1220 | { | 1844 | { |
1221 | struct ExchangeHandle *handle = cls; | 1845 | struct AttributeStoreHandle *as_handle = cls; |
1222 | struct GNUNET_MQ_Envelope *env; | 1846 | struct GNUNET_MQ_Envelope *env; |
1223 | char* token_str; | 1847 | struct AttributeStoreResultMessage *acr_msg; |
1224 | char* record_str; | ||
1225 | 1848 | ||
1226 | handle->lookup_request = NULL; | 1849 | if (GNUNET_SYSERR == success) |
1227 | if (2 != rd_count) | ||
1228 | { | 1850 | { |
1229 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1851 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1230 | "Number of tokens %d != 2.", | 1852 | "Failed to store attribute %s\n", |
1231 | rd_count); | 1853 | emsg); |
1232 | cleanup_exchange_handle (handle); | 1854 | cleanup_as_handle (as_handle); |
1233 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | 1855 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); |
1234 | return; | 1856 | return; |
1235 | } | 1857 | } |
1236 | 1858 | ||
1237 | record_str = | 1859 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1238 | GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN, | 1860 | "Sending ATTRIBUTE_STORE_RESPONSE message\n"); |
1239 | rd->data, | 1861 | env = GNUNET_MQ_msg (acr_msg, |
1240 | rd->data_size); | 1862 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE); |
1241 | 1863 | acr_msg->id = htonl (as_handle->r_id); | |
1242 | //Decrypt and parse | 1864 | acr_msg->op_result = htonl (GNUNET_OK); |
1243 | GNUNET_assert (GNUNET_OK == token_parse (record_str, | 1865 | GNUNET_MQ_send (as_handle->client->mq, |
1244 | &handle->aud_privkey, | ||
1245 | &handle->token)); | ||
1246 | |||
1247 | //Readable | ||
1248 | GNUNET_assert (GNUNET_OK == token_to_string (handle->token, | ||
1249 | &handle->aud_privkey, | ||
1250 | &token_str)); | ||
1251 | |||
1252 | env = create_exchange_result_message (token_str, | ||
1253 | handle->label, | ||
1254 | handle->ticket->payload->nonce, | ||
1255 | handle->r_id); | ||
1256 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client), | ||
1257 | env); | 1866 | env); |
1258 | cleanup_exchange_handle (handle); | 1867 | cleanup_as_handle (as_handle); |
1259 | GNUNET_free (record_str); | 1868 | } |
1260 | GNUNET_free (token_str); | 1869 | |
1870 | static void | ||
1871 | attr_store_task (void *cls) | ||
1872 | { | ||
1873 | struct AttributeStoreHandle *as_handle = cls; | ||
1874 | struct GNUNET_GNSRECORD_Data rd[1]; | ||
1875 | char* buf; | ||
1876 | char* policy; | ||
1877 | char* enc_buf; | ||
1878 | char* rd_buf; | ||
1879 | size_t enc_size; | ||
1880 | size_t buf_size; | ||
1881 | uint32_t attr_ver; | ||
1882 | |||
1883 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1884 | "Storing attribute\n"); | ||
1885 | buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim); | ||
1886 | buf = GNUNET_malloc (buf_size); | ||
1887 | |||
1888 | GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim, | ||
1889 | buf); | ||
1890 | |||
1891 | GNUNET_asprintf (&policy, | ||
1892 | "%s_%lu", | ||
1893 | as_handle->claim->name, | ||
1894 | as_handle->claim->version); | ||
1895 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1896 | "Encrypting with policy %s\n", policy); | ||
1897 | /** | ||
1898 | * Encrypt the attribute value and store in namestore | ||
1899 | */ | ||
1900 | enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf, | ||
1901 | buf_size, | ||
1902 | policy, //Policy | ||
1903 | as_handle->abe_key, | ||
1904 | (void**)&enc_buf); | ||
1905 | GNUNET_free (buf); | ||
1906 | GNUNET_free (policy); | ||
1907 | rd[0].data_size = enc_size + sizeof (uint32_t); | ||
1908 | rd_buf = GNUNET_malloc (rd[0].data_size); | ||
1909 | attr_ver = htonl (as_handle->claim->version); | ||
1910 | GNUNET_memcpy (rd_buf, | ||
1911 | &attr_ver, | ||
1912 | sizeof (uint32_t)); | ||
1913 | GNUNET_memcpy (rd_buf+sizeof (uint32_t), | ||
1914 | enc_buf, | ||
1915 | enc_size); | ||
1916 | rd[0].data = rd_buf; | ||
1917 | rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR; | ||
1918 | rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1919 | rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane? | ||
1920 | as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1921 | &as_handle->identity, | ||
1922 | as_handle->claim->name, | ||
1923 | 1, | ||
1924 | rd, | ||
1925 | &attr_store_cont, | ||
1926 | as_handle); | ||
1927 | GNUNET_free (enc_buf); | ||
1928 | GNUNET_free (rd_buf); | ||
1929 | } | ||
1930 | |||
1931 | |||
1932 | static void | ||
1933 | store_after_abe_bootstrap (void *cls, | ||
1934 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key) | ||
1935 | { | ||
1936 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1937 | "Finished ABE bootstrap\n"); | ||
1938 | struct AttributeStoreHandle *ash = cls; | ||
1939 | ash->abe_key = abe_key; | ||
1940 | GNUNET_SCHEDULER_add_now (&attr_store_task, ash); | ||
1261 | } | 1941 | } |
1262 | 1942 | ||
1263 | /** | 1943 | /** |
1264 | * Checks a exchange message | 1944 | * Checks a store message |
1265 | * | 1945 | * |
1266 | * @param cls client sending the message | 1946 | * @param cls client sending the message |
1267 | * @param xm message of type `struct ExchangeMessage` | 1947 | * @param sam message of type `struct AttributeStoreMessage` |
1268 | * @return #GNUNET_OK if @a xm is well-formed | 1948 | * @return #GNUNET_OK if @a im is well-formed |
1269 | */ | 1949 | */ |
1270 | static int | 1950 | static int |
1271 | check_exchange_message (void *cls, | 1951 | check_attribute_store_message(void *cls, |
1272 | const struct ExchangeMessage *xm) | 1952 | const struct AttributeStoreMessage *sam) |
1273 | { | 1953 | { |
1274 | uint16_t size; | 1954 | uint16_t size; |
1275 | 1955 | ||
1276 | size = ntohs (xm->header.size); | 1956 | size = ntohs (sam->header.size); |
1277 | if (size <= sizeof (struct ExchangeMessage)) | 1957 | if (size <= sizeof (struct AttributeStoreMessage)) |
1278 | { | 1958 | { |
1279 | GNUNET_break (0); | 1959 | GNUNET_break (0); |
1280 | return GNUNET_SYSERR; | 1960 | return GNUNET_SYSERR; |
@@ -1282,301 +1962,492 @@ check_exchange_message (void *cls, | |||
1282 | return GNUNET_OK; | 1962 | return GNUNET_OK; |
1283 | } | 1963 | } |
1284 | 1964 | ||
1965 | |||
1285 | /** | 1966 | /** |
1286 | * | 1967 | * |
1287 | * Handler for exchange message | 1968 | * Handler for store message |
1288 | * | 1969 | * |
1289 | * @param cls unused | 1970 | * @param cls unused |
1290 | * @param client who sent the message | 1971 | * @param client who sent the message |
1291 | * @param message the message | 1972 | * @param message the message |
1292 | */ | 1973 | */ |
1293 | static void | 1974 | static void |
1294 | handle_exchange_message (void *cls, | 1975 | handle_attribute_store_message (void *cls, |
1295 | const struct ExchangeMessage *xm) | 1976 | const struct AttributeStoreMessage *sam) |
1296 | { | 1977 | { |
1297 | struct ExchangeHandle *xchange_handle; | 1978 | struct AttributeStoreHandle *as_handle; |
1298 | struct GNUNET_SERVICE_Client *client = cls; | 1979 | struct IdpClient *idp = cls; |
1299 | const char *ticket; | 1980 | size_t data_len; |
1300 | char *lookup_query; | ||
1301 | |||
1302 | ticket = (const char *) &xm[1]; | ||
1303 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1981 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1304 | "Received EXCHANGE of `%s' from client\n", | 1982 | "Received ATTRIBUTE_STORE message\n"); |
1305 | ticket); | 1983 | |
1306 | xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle)); | 1984 | data_len = ntohs (sam->attr_len); |
1307 | xchange_handle->aud_privkey = xm->aud_privkey; | 1985 | |
1308 | xchange_handle->r_id = xm->id; | 1986 | as_handle = GNUNET_new (struct AttributeStoreHandle); |
1309 | if (GNUNET_SYSERR == ticket_parse (ticket, | 1987 | as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1], |
1310 | &xchange_handle->aud_privkey, | 1988 | data_len); |
1311 | &xchange_handle->ticket)) | 1989 | |
1312 | { | 1990 | as_handle->r_id = ntohl (sam->id); |
1313 | GNUNET_free (xchange_handle); | 1991 | as_handle->identity = sam->identity; |
1314 | GNUNET_SERVICE_client_drop (client); | 1992 | GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, |
1315 | return; | 1993 | &as_handle->identity_pkey); |
1316 | } | ||
1317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for token under %s\n", | ||
1318 | xchange_handle->ticket->payload->label); | ||
1319 | GNUNET_asprintf (&lookup_query, | ||
1320 | "%s.gnu", | ||
1321 | xchange_handle->ticket->payload->label); | ||
1322 | GNUNET_SERVICE_client_continue (client); | ||
1323 | xchange_handle->client = client; | ||
1324 | xchange_handle->lookup_request | ||
1325 | = GNUNET_GNS_lookup (gns_handle, | ||
1326 | lookup_query, | ||
1327 | &xchange_handle->ticket->payload->identity_key, | ||
1328 | GNUNET_GNSRECORD_TYPE_ID_TOKEN, | ||
1329 | GNUNET_GNS_LO_LOCAL_MASTER, | ||
1330 | &process_lookup_result, | ||
1331 | xchange_handle); | ||
1332 | GNUNET_free (lookup_query); | ||
1333 | 1994 | ||
1995 | GNUNET_SERVICE_client_continue (idp->client); | ||
1996 | as_handle->client = idp; | ||
1997 | bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO); | ||
1334 | } | 1998 | } |
1335 | 1999 | ||
2000 | static void | ||
2001 | cleanup_iter_handle (struct AttributeIterator *ai) | ||
2002 | { | ||
2003 | if (NULL != ai->abe_key) | ||
2004 | GNUNET_CRYPTO_cpabe_delete_master_key (ai->abe_key); | ||
2005 | GNUNET_CONTAINER_DLL_remove (ai->client->op_head, | ||
2006 | ai->client->op_tail, | ||
2007 | ai); | ||
2008 | GNUNET_free (ai); | ||
2009 | } | ||
1336 | 2010 | ||
1337 | static void | 2011 | static void |
1338 | find_existing_token_error (void *cls) | 2012 | attr_iter_error (void *cls) |
1339 | { | 2013 | { |
1340 | struct IssueHandle *handle = cls; | 2014 | struct AttributeIterator *ai = cls; |
1341 | cleanup_issue_handle (handle); | 2015 | //TODO |
1342 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error looking for existing token\n"); | 2016 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2017 | "Failed to iterate over attributes\n"); | ||
2018 | cleanup_iter_handle (ai); | ||
1343 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | 2019 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); |
1344 | } | 2020 | } |
1345 | 2021 | ||
2022 | static void | ||
2023 | attr_iter_finished (void *cls) | ||
2024 | { | ||
2025 | struct AttributeIterator *ai = cls; | ||
2026 | struct GNUNET_MQ_Envelope *env; | ||
2027 | struct AttributeResultMessage *arm; | ||
2028 | |||
2029 | env = GNUNET_MQ_msg (arm, | ||
2030 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT); | ||
2031 | arm->id = htonl (ai->request_id); | ||
2032 | arm->attr_len = htons (0); | ||
2033 | GNUNET_MQ_send (ai->client->mq, env); | ||
2034 | cleanup_iter_handle (ai); | ||
2035 | } | ||
1346 | 2036 | ||
1347 | static void | 2037 | static void |
1348 | find_existing_token_finished (void *cls) | 2038 | attr_iter_cb (void *cls, |
2039 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
2040 | const char *label, | ||
2041 | unsigned int rd_count, | ||
2042 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1349 | { | 2043 | { |
1350 | struct IssueHandle *handle = cls; | 2044 | struct AttributeIterator *ai = cls; |
1351 | uint64_t rnd_key; | 2045 | struct AttributeResultMessage *arm; |
2046 | struct GNUNET_CRYPTO_AbeKey *key; | ||
2047 | struct GNUNET_MQ_Envelope *env; | ||
2048 | ssize_t msg_extra_len; | ||
2049 | char* attr_ser; | ||
2050 | char* attrs[2]; | ||
2051 | char* data_tmp; | ||
2052 | char* policy; | ||
2053 | uint32_t attr_ver; | ||
2054 | |||
2055 | if (rd_count != 1) | ||
2056 | { | ||
2057 | GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it); | ||
2058 | return; | ||
2059 | } | ||
1352 | 2060 | ||
2061 | if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) { | ||
2062 | GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it); | ||
2063 | return; | ||
2064 | } | ||
2065 | attr_ver = ntohl(*((uint32_t*)rd->data)); | ||
2066 | GNUNET_asprintf (&policy, "%s_%lu", | ||
2067 | label, attr_ver); | ||
2068 | attrs[0] = policy; | ||
2069 | attrs[1] = 0; | ||
2070 | key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key, | ||
2071 | attrs); | ||
2072 | msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data+sizeof (uint32_t), | ||
2073 | rd->data_size-sizeof (uint32_t), | ||
2074 | key, | ||
2075 | (void**)&attr_ser); | ||
2076 | |||
2077 | GNUNET_CRYPTO_cpabe_delete_key (key, | ||
2078 | GNUNET_YES); | ||
2079 | //GNUNET_free (policy); | ||
1353 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2080 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1354 | ">>> No existing token found\n"); | 2081 | "Found attribute: %s\n", label); |
1355 | rnd_key = | 2082 | env = GNUNET_MQ_msg_extra (arm, |
1356 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, | 2083 | msg_extra_len, |
1357 | UINT64_MAX); | 2084 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT); |
1358 | GNUNET_STRINGS_base64_encode ((char*)&rnd_key, | 2085 | arm->id = htonl (ai->request_id); |
1359 | sizeof (uint64_t), | 2086 | arm->attr_len = htons (msg_extra_len); |
1360 | &handle->label); | 2087 | GNUNET_CRYPTO_ecdsa_key_get_public (zone, |
1361 | handle->ns_it = NULL; | 2088 | &arm->identity); |
1362 | handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | 2089 | data_tmp = (char *) &arm[1]; |
1363 | &handle->iss_key, | 2090 | GNUNET_memcpy (data_tmp, |
1364 | &attr_collect_error, | 2091 | attr_ser, |
1365 | handle, | 2092 | msg_extra_len); |
1366 | &attr_collect, | 2093 | GNUNET_MQ_send (ai->client->mq, env); |
1367 | handle, | 2094 | GNUNET_free (attr_ser); |
1368 | &attr_collect_finished, | 2095 | GNUNET_CRYPTO_cpabe_delete_master_key (ai->abe_key); |
1369 | handle); | 2096 | ai->abe_key = NULL; |
2097 | } | ||
2098 | |||
2099 | |||
2100 | void | ||
2101 | iterate_after_abe_bootstrap (void *cls, | ||
2102 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key) | ||
2103 | { | ||
2104 | struct AttributeIterator *ai = cls; | ||
2105 | ai->abe_key = abe_key; | ||
2106 | ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
2107 | &ai->identity, | ||
2108 | &attr_iter_error, | ||
2109 | ai, | ||
2110 | &attr_iter_cb, | ||
2111 | ai, | ||
2112 | &attr_iter_finished, | ||
2113 | ai); | ||
1370 | } | 2114 | } |
1371 | 2115 | ||
2116 | void | ||
2117 | iterate_next_after_abe_bootstrap (void *cls, | ||
2118 | struct GNUNET_CRYPTO_AbeMasterKey *abe_key) | ||
2119 | { | ||
2120 | struct AttributeIterator *ai = cls; | ||
2121 | ai->abe_key = abe_key; | ||
2122 | GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it); | ||
2123 | } | ||
2124 | |||
2125 | |||
1372 | 2126 | ||
1373 | /** | 2127 | /** |
2128 | * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message | ||
1374 | * | 2129 | * |
1375 | * Look for existing token | 2130 | * @param cls the client sending the message |
1376 | * | 2131 | * @param zis_msg message from the client |
1377 | * @param cls the identity entry | 2132 | */ |
1378 | * @param zone the identity | 2133 | static void |
1379 | * @param lbl the name of the record | 2134 | handle_iteration_start (void *cls, |
1380 | * @param rd_count number of records | 2135 | const struct AttributeIterationStartMessage *ais_msg) |
1381 | * @param rd record data | 2136 | { |
2137 | struct IdpClient *idp = cls; | ||
2138 | struct AttributeIterator *ai; | ||
2139 | |||
2140 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2141 | "Received ATTRIBUTE_ITERATION_START message\n"); | ||
2142 | ai = GNUNET_new (struct AttributeIterator); | ||
2143 | ai->request_id = ntohl (ais_msg->id); | ||
2144 | ai->client = idp; | ||
2145 | ai->identity = ais_msg->identity; | ||
2146 | |||
2147 | GNUNET_CONTAINER_DLL_insert (idp->op_head, | ||
2148 | idp->op_tail, | ||
2149 | ai); | ||
2150 | bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO); | ||
2151 | GNUNET_SERVICE_client_continue (idp->client); | ||
2152 | } | ||
2153 | |||
2154 | |||
2155 | /** | ||
2156 | * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message | ||
1382 | * | 2157 | * |
2158 | * @param cls the client sending the message | ||
2159 | * @param ais_msg message from the client | ||
1383 | */ | 2160 | */ |
1384 | static void | 2161 | static void |
1385 | find_existing_token (void *cls, | 2162 | handle_iteration_stop (void *cls, |
1386 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 2163 | const struct AttributeIterationStopMessage *ais_msg) |
1387 | const char *lbl, | 2164 | { |
1388 | unsigned int rd_count, | 2165 | struct IdpClient *idp = cls; |
1389 | const struct GNUNET_GNSRECORD_Data *rd) | 2166 | struct AttributeIterator *ai; |
1390 | { | 2167 | uint32_t rid; |
1391 | struct IssueHandle *handle = cls; | ||
1392 | const struct GNUNET_GNSRECORD_Data *token_metadata_record; | ||
1393 | struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key; | ||
1394 | struct GNUNET_HashCode key; | ||
1395 | int scope_count_token; | ||
1396 | char *scope; | ||
1397 | char *tmp_scopes; | ||
1398 | 2168 | ||
1399 | //There should be only a single record for a token under a label | 2169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1400 | if (2 != rd_count) | 2170 | "Received `%s' message\n", |
2171 | "ATTRIBUTE_ITERATION_STOP"); | ||
2172 | rid = ntohl (ais_msg->id); | ||
2173 | for (ai = idp->op_head; NULL != ai; ai = ai->next) | ||
2174 | if (ai->request_id == rid) | ||
2175 | break; | ||
2176 | if (NULL == ai) | ||
1401 | { | 2177 | { |
1402 | GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); | 2178 | GNUNET_break (0); |
2179 | GNUNET_SERVICE_client_drop (idp->client); | ||
1403 | return; | 2180 | return; |
1404 | } | 2181 | } |
2182 | GNUNET_CONTAINER_DLL_remove (idp->op_head, | ||
2183 | idp->op_tail, | ||
2184 | ai); | ||
2185 | GNUNET_free (ai); | ||
2186 | GNUNET_SERVICE_client_continue (idp->client); | ||
2187 | } | ||
1405 | 2188 | ||
1406 | if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) | 2189 | |
1407 | { | 2190 | /** |
1408 | token_metadata_record = &rd[0]; | 2191 | * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message |
1409 | } | 2192 | * |
1410 | else | 2193 | * @param cls the client sending the message |
1411 | { | 2194 | * @param message message from the client |
1412 | token_metadata_record = &rd[1]; | 2195 | */ |
1413 | } | 2196 | static void |
1414 | if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) | 2197 | handle_iteration_next (void *cls, |
2198 | const struct AttributeIterationNextMessage *ais_msg) | ||
2199 | { | ||
2200 | struct IdpClient *idp = cls; | ||
2201 | struct AttributeIterator *ai; | ||
2202 | uint32_t rid; | ||
2203 | |||
2204 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2205 | "Received ATTRIBUTE_ITERATION_NEXT message\n"); | ||
2206 | rid = ntohl (ais_msg->id); | ||
2207 | for (ai = idp->op_head; NULL != ai; ai = ai->next) | ||
2208 | if (ai->request_id == rid) | ||
2209 | break; | ||
2210 | if (NULL == ai) | ||
1415 | { | 2211 | { |
1416 | GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); | 2212 | GNUNET_break (0); |
2213 | GNUNET_SERVICE_client_drop (idp->client); | ||
1417 | return; | 2214 | return; |
1418 | } | 2215 | } |
1419 | ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data); | 2216 | bootstrap_abe (&ai->identity, |
1420 | aud_key = | 2217 | &iterate_next_after_abe_bootstrap, |
1421 | (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey)); | 2218 | ai, |
1422 | tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | 2219 | GNUNET_NO); |
2220 | GNUNET_SERVICE_client_continue (idp->client); | ||
2221 | } | ||
1423 | 2222 | ||
1424 | if (0 != memcmp (aud_key, &handle->aud_key, | 2223 | /** |
1425 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | 2224 | * Ticket iteration processor result |
2225 | */ | ||
2226 | enum ZoneIterationResult | ||
2227 | { | ||
2228 | /** | ||
2229 | * Iteration start. | ||
2230 | */ | ||
2231 | IT_START = 0, | ||
2232 | |||
2233 | /** | ||
2234 | * Found tickets, | ||
2235 | * Continue to iterate with next iteration_next call | ||
2236 | */ | ||
2237 | IT_SUCCESS_MORE_AVAILABLE = 1, | ||
2238 | |||
2239 | /** | ||
2240 | * Iteration complete | ||
2241 | */ | ||
2242 | IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2 | ||
2243 | }; | ||
2244 | |||
2245 | |||
2246 | /** | ||
2247 | * Context for ticket iteration | ||
2248 | */ | ||
2249 | struct TicketIterationProcResult | ||
2250 | { | ||
2251 | /** | ||
2252 | * The ticket iteration handle | ||
2253 | */ | ||
2254 | struct TicketIteration *ti; | ||
2255 | |||
2256 | /** | ||
2257 | * Iteration result: iteration done? | ||
2258 | * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but | ||
2259 | * we got one for now and have sent it to the client | ||
2260 | * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results, | ||
2261 | * #IT_START: if we are still trying to find a result. | ||
2262 | */ | ||
2263 | int res_iteration_finished; | ||
2264 | |||
2265 | }; | ||
2266 | |||
2267 | static void | ||
2268 | cleanup_ticket_iter_handle (struct TicketIteration *ti) | ||
2269 | { | ||
2270 | GNUNET_free (ti); | ||
2271 | } | ||
2272 | |||
2273 | /** | ||
2274 | * Process ticket from database | ||
2275 | * | ||
2276 | * @param cls struct TicketIterationProcResult | ||
2277 | * @param ticket the ticket | ||
2278 | * @param attrs the attributes | ||
2279 | */ | ||
2280 | static void | ||
2281 | ticket_iterate_proc (void *cls, | ||
2282 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
2283 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) | ||
2284 | { | ||
2285 | struct TicketIterationProcResult *proc = cls; | ||
2286 | |||
2287 | if (NULL == ticket) | ||
1426 | { | 2288 | { |
1427 | char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key, | ||
1428 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1429 | //Audience does not match! | ||
1430 | char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA, | ||
1431 | token_metadata_record->data, | ||
1432 | token_metadata_record->data_size); | ||
1433 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2289 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1434 | "Token does not match audience %s vs %s. Moving on\n", | 2290 | "Iteration done\n"); |
1435 | tmp2, | 2291 | proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE; |
1436 | tmp); | ||
1437 | GNUNET_free (tmp_scopes); | ||
1438 | GNUNET_free (tmp2); | ||
1439 | GNUNET_free (tmp); | ||
1440 | GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); | ||
1441 | return; | 2292 | return; |
1442 | } | 2293 | } |
2294 | proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE; | ||
2295 | send_ticket_result (proc->ti->client, | ||
2296 | proc->ti->r_id, | ||
2297 | ticket, | ||
2298 | attrs); | ||
1443 | 2299 | ||
1444 | scope = strtok (tmp_scopes, ","); | 2300 | } |
1445 | scope_count_token = 0; | 2301 | |
1446 | while (NULL != scope) | 2302 | /** |
1447 | { | 2303 | * Perform ticket iteration step |
1448 | GNUNET_CRYPTO_hash (scope, | 2304 | * |
1449 | strlen (scope), | 2305 | * @param ti ticket iterator to process |
1450 | &key); | 2306 | */ |
2307 | static void | ||
2308 | run_ticket_iteration_round (struct TicketIteration *ti) | ||
2309 | { | ||
2310 | struct TicketIterationProcResult proc; | ||
2311 | struct GNUNET_MQ_Envelope *env; | ||
2312 | struct TicketResultMessage *trm; | ||
2313 | int ret; | ||
1451 | 2314 | ||
1452 | if ((NULL != handle->attr_map) && | 2315 | memset (&proc, 0, sizeof (proc)); |
1453 | (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key))) | 2316 | proc.ti = ti; |
2317 | proc.res_iteration_finished = IT_START; | ||
2318 | while (IT_START == proc.res_iteration_finished) | ||
2319 | { | ||
2320 | if (GNUNET_SYSERR == | ||
2321 | (ret = TKT_database->iterate_tickets (TKT_database->cls, | ||
2322 | &ti->identity, | ||
2323 | ti->is_audience, | ||
2324 | ti->offset, | ||
2325 | &ticket_iterate_proc, | ||
2326 | &proc))) | ||
1454 | { | 2327 | { |
1455 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2328 | GNUNET_break (0); |
1456 | "Issued token does not include `%s'. Moving on\n", scope); | 2329 | break; |
1457 | GNUNET_free (tmp_scopes); | ||
1458 | GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); | ||
1459 | return; | ||
1460 | } | 2330 | } |
1461 | scope_count_token++; | 2331 | if (GNUNET_NO == ret) |
1462 | scope = strtok (NULL, ","); | 2332 | proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE; |
2333 | ti->offset++; | ||
1463 | } | 2334 | } |
1464 | GNUNET_free (tmp_scopes); | 2335 | if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished) |
1465 | //All scopes in token are also in request. Now | ||
1466 | //Check length | ||
1467 | if ((NULL != handle->attr_map) && | ||
1468 | (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == scope_count_token)) | ||
1469 | { | 2336 | { |
1470 | //We have an existing token | 2337 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1471 | handle->label = GNUNET_strdup (lbl); | 2338 | "More results available\n"); |
1472 | handle->ns_it = NULL; | 2339 | return; /* more later */ |
1473 | handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
1474 | &handle->iss_key, | ||
1475 | &attr_collect_error, | ||
1476 | handle, | ||
1477 | &attr_collect, | ||
1478 | handle, | ||
1479 | &attr_collect_finished, | ||
1480 | handle); | ||
1481 | |||
1482 | return; | ||
1483 | } | 2340 | } |
1484 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2341 | /* send empty response to indicate end of list */ |
1485 | "Nuber of attributes in token do not match request\n"); | 2342 | env = GNUNET_MQ_msg (trm, |
1486 | //No luck | 2343 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT); |
1487 | GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); | 2344 | trm->id = htonl (ti->r_id); |
2345 | GNUNET_MQ_send (ti->client->mq, | ||
2346 | env); | ||
2347 | GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head, | ||
2348 | ti->client->ticket_iter_tail, | ||
2349 | ti); | ||
2350 | cleanup_ticket_iter_handle (ti); | ||
1488 | } | 2351 | } |
1489 | 2352 | ||
1490 | /** | 2353 | /** |
1491 | * Checks an issue message | 2354 | * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START message |
1492 | * | 2355 | * |
1493 | * @param cls client sending the message | 2356 | * @param cls the client sending the message |
1494 | * @param im message of type `struct IssueMessage` | 2357 | * @param tis_msg message from the client |
1495 | * @return #GNUNET_OK if @a im is well-formed | ||
1496 | */ | 2358 | */ |
1497 | static int | 2359 | static void |
1498 | check_issue_message(void *cls, | 2360 | handle_ticket_iteration_start (void *cls, |
1499 | const struct IssueMessage *im) | 2361 | const struct TicketIterationStartMessage *tis_msg) |
1500 | { | 2362 | { |
1501 | uint16_t size; | 2363 | struct IdpClient *client = cls; |
2364 | struct TicketIteration *ti; | ||
1502 | 2365 | ||
1503 | size = ntohs (im->header.size); | 2366 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1504 | if (size <= sizeof (struct IssueMessage)) | 2367 | "Received TICKET_ITERATION_START message\n"); |
1505 | { | 2368 | ti = GNUNET_new (struct TicketIteration); |
1506 | GNUNET_break (0); | 2369 | ti->r_id = ntohl (tis_msg->id); |
1507 | return GNUNET_SYSERR; | 2370 | ti->offset = 0; |
1508 | } | 2371 | ti->client = client; |
1509 | scopes = (char *) &im[1]; | 2372 | ti->identity = tis_msg->identity; |
1510 | if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1]) | 2373 | ti->is_audience = ntohl (tis_msg->is_audience); |
2374 | |||
2375 | GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head, | ||
2376 | client->ticket_iter_tail, | ||
2377 | ti); | ||
2378 | run_ticket_iteration_round (ti); | ||
2379 | GNUNET_SERVICE_client_continue (client->client); | ||
2380 | } | ||
2381 | |||
2382 | |||
2383 | /** | ||
2384 | * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP message | ||
2385 | * | ||
2386 | * @param cls the client sending the message | ||
2387 | * @param tis_msg message from the client | ||
2388 | */ | ||
2389 | static void | ||
2390 | handle_ticket_iteration_stop (void *cls, | ||
2391 | const struct TicketIterationStopMessage *tis_msg) | ||
2392 | { | ||
2393 | struct IdpClient *client = cls; | ||
2394 | struct TicketIteration *ti; | ||
2395 | uint32_t rid; | ||
2396 | |||
2397 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2398 | "Received `%s' message\n", | ||
2399 | "TICKET_ITERATION_STOP"); | ||
2400 | rid = ntohl (tis_msg->id); | ||
2401 | for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next) | ||
2402 | if (ti->r_id == rid) | ||
2403 | break; | ||
2404 | if (NULL == ti) | ||
1511 | { | 2405 | { |
1512 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1513 | "Malformed scopes received!\n"); | ||
1514 | GNUNET_break (0); | 2406 | GNUNET_break (0); |
1515 | return GNUNET_SYSERR; | 2407 | GNUNET_SERVICE_client_drop (client->client); |
2408 | return; | ||
1516 | } | 2409 | } |
1517 | return GNUNET_OK; | 2410 | GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head, |
2411 | client->ticket_iter_tail, | ||
2412 | ti); | ||
2413 | cleanup_ticket_iter_handle (ti); | ||
2414 | GNUNET_SERVICE_client_continue (client->client); | ||
1518 | } | 2415 | } |
1519 | 2416 | ||
2417 | |||
1520 | /** | 2418 | /** |
2419 | * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT message | ||
1521 | * | 2420 | * |
1522 | * Handler for issue message | 2421 | * @param cls the client sending the message |
1523 | * | 2422 | * @param message message from the client |
1524 | * @param cls unused | ||
1525 | * @param client who sent the message | ||
1526 | * @param message the message | ||
1527 | */ | 2423 | */ |
1528 | static void | 2424 | static void |
1529 | handle_issue_message (void *cls, | 2425 | handle_ticket_iteration_next (void *cls, |
1530 | const struct IssueMessage *im) | 2426 | const struct TicketIterationNextMessage *tis_msg) |
1531 | { | 2427 | { |
1532 | const char *scopes; | 2428 | struct IdpClient *client = cls; |
1533 | char *scopes_tmp; | 2429 | struct TicketIteration *ti; |
1534 | char *scope; | 2430 | uint32_t rid; |
1535 | struct GNUNET_HashCode key; | ||
1536 | struct IssueHandle *issue_handle; | ||
1537 | struct GNUNET_SERVICE_Client *client = cls; | ||
1538 | |||
1539 | scopes = (const char *) &im[1]; | ||
1540 | issue_handle = GNUNET_malloc (sizeof (struct IssueHandle)); | ||
1541 | issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5, | ||
1542 | GNUNET_NO); | ||
1543 | scopes_tmp = GNUNET_strdup (scopes); | ||
1544 | 2431 | ||
1545 | for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) | 2432 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2433 | "Received TICKET_ITERATION_NEXT message\n"); | ||
2434 | rid = ntohl (tis_msg->id); | ||
2435 | for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next) | ||
2436 | if (ti->r_id == rid) | ||
2437 | break; | ||
2438 | if (NULL == ti) | ||
1546 | { | 2439 | { |
1547 | GNUNET_CRYPTO_hash (scope, | 2440 | GNUNET_break (0); |
1548 | strlen (scope), | 2441 | GNUNET_SERVICE_client_drop (client->client); |
1549 | &key); | 2442 | return; |
1550 | GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map, | ||
1551 | &key, | ||
1552 | scope, | ||
1553 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
1554 | } | 2443 | } |
1555 | GNUNET_free (scopes_tmp); | 2444 | run_ticket_iteration_round (ti); |
1556 | issue_handle->r_id = im->id; | 2445 | GNUNET_SERVICE_client_continue (client->client); |
1557 | issue_handle->aud_key = im->aud_key; | ||
1558 | issue_handle->iss_key = im->iss_key; | ||
1559 | GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key, | ||
1560 | &issue_handle->iss_pkey); | ||
1561 | issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration); | ||
1562 | issue_handle->nonce = ntohl (im->nonce); | ||
1563 | GNUNET_SERVICE_client_continue (client); | ||
1564 | issue_handle->client = client; | ||
1565 | issue_handle->scopes = GNUNET_strdup (scopes); | ||
1566 | issue_handle->token = token_create (&issue_handle->iss_pkey, | ||
1567 | &issue_handle->aud_key); | ||
1568 | |||
1569 | issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
1570 | &im->iss_key, | ||
1571 | &find_existing_token_error, | ||
1572 | issue_handle, | ||
1573 | &find_existing_token, | ||
1574 | issue_handle, | ||
1575 | &find_existing_token_finished, | ||
1576 | issue_handle); | ||
1577 | } | 2446 | } |
1578 | 2447 | ||
1579 | 2448 | ||
2449 | |||
2450 | |||
1580 | /** | 2451 | /** |
1581 | * Main function that will be run | 2452 | * Main function that will be run |
1582 | * | 2453 | * |
@@ -1590,6 +2461,7 @@ run (void *cls, | |||
1590 | const struct GNUNET_CONFIGURATION_Handle *c, | 2461 | const struct GNUNET_CONFIGURATION_Handle *c, |
1591 | struct GNUNET_SERVICE_Handle *server) | 2462 | struct GNUNET_SERVICE_Handle *server) |
1592 | { | 2463 | { |
2464 | char *database; | ||
1593 | cfg = c; | 2465 | cfg = c; |
1594 | 2466 | ||
1595 | stats = GNUNET_STATISTICS_create ("identity-provider", cfg); | 2467 | stats = GNUNET_STATISTICS_create ("identity-provider", cfg); |
@@ -1606,10 +2478,38 @@ run (void *cls, | |||
1606 | { | 2478 | { |
1607 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); | 2479 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); |
1608 | } | 2480 | } |
1609 | 2481 | credential_handle = GNUNET_CREDENTIAL_connect (cfg); | |
2482 | if (NULL == credential_handle) | ||
2483 | { | ||
2484 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential"); | ||
2485 | } | ||
1610 | identity_handle = GNUNET_IDENTITY_connect (cfg, | 2486 | identity_handle = GNUNET_IDENTITY_connect (cfg, |
1611 | &list_ego, | 2487 | NULL, |
1612 | NULL); | 2488 | NULL); |
2489 | stats_handle = GNUNET_STATISTICS_create ("identity-provider", | ||
2490 | cfg); | ||
2491 | /* Loading DB plugin */ | ||
2492 | if (GNUNET_OK != | ||
2493 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
2494 | "identity-provider", | ||
2495 | "database", | ||
2496 | &database)) | ||
2497 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2498 | "No database backend configured\n"); | ||
2499 | GNUNET_asprintf (&db_lib_name, | ||
2500 | "libgnunet_plugin_identity_provider_%s", | ||
2501 | database); | ||
2502 | TKT_database = GNUNET_PLUGIN_load (db_lib_name, | ||
2503 | (void *) cfg); | ||
2504 | GNUNET_free (database); | ||
2505 | if (NULL == TKT_database) | ||
2506 | { | ||
2507 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2508 | "Could not load database backend `%s'\n", | ||
2509 | db_lib_name); | ||
2510 | GNUNET_SCHEDULER_shutdown (); | ||
2511 | return; | ||
2512 | } | ||
1613 | 2513 | ||
1614 | if (GNUNET_OK == | 2514 | if (GNUNET_OK == |
1615 | GNUNET_CONFIGURATION_get_value_time (cfg, | 2515 | GNUNET_CONFIGURATION_get_value_time (cfg, |
@@ -1640,9 +2540,39 @@ client_disconnect_cb (void *cls, | |||
1640 | struct GNUNET_SERVICE_Client *client, | 2540 | struct GNUNET_SERVICE_Client *client, |
1641 | void *app_ctx) | 2541 | void *app_ctx) |
1642 | { | 2542 | { |
2543 | struct IdpClient *idp = app_ctx; | ||
2544 | struct AttributeIterator *ai; | ||
2545 | struct TicketIteration *ti; | ||
2546 | struct TicketRevocationHandle *rh; | ||
2547 | |||
2548 | //TODO other operations | ||
2549 | |||
1643 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2550 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1644 | "Client %p disconnected\n", | 2551 | "Client %p disconnected\n", |
1645 | client); | 2552 | client); |
2553 | |||
2554 | while (NULL != (ai = idp->op_head)) | ||
2555 | { | ||
2556 | GNUNET_CONTAINER_DLL_remove (idp->op_head, | ||
2557 | idp->op_tail, | ||
2558 | ai); | ||
2559 | GNUNET_free (ai); | ||
2560 | } | ||
2561 | while (NULL != (rh = idp->revocation_list_head)) | ||
2562 | { | ||
2563 | GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head, | ||
2564 | idp->revocation_list_tail, | ||
2565 | rh); | ||
2566 | cleanup_revoke_ticket_handle (rh); | ||
2567 | } | ||
2568 | while (NULL != (ti = idp->ticket_iter_head)) | ||
2569 | { | ||
2570 | GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head, | ||
2571 | idp->ticket_iter_tail, | ||
2572 | ti); | ||
2573 | cleanup_ticket_iter_handle (ti); | ||
2574 | } | ||
2575 | GNUNET_free (idp); | ||
1646 | } | 2576 | } |
1647 | 2577 | ||
1648 | 2578 | ||
@@ -1659,10 +2589,14 @@ client_connect_cb (void *cls, | |||
1659 | struct GNUNET_SERVICE_Client *client, | 2589 | struct GNUNET_SERVICE_Client *client, |
1660 | struct GNUNET_MQ_Handle *mq) | 2590 | struct GNUNET_MQ_Handle *mq) |
1661 | { | 2591 | { |
2592 | struct IdpClient *idp; | ||
1662 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2593 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1663 | "Client %p connected\n", | 2594 | "Client %p connected\n", |
1664 | client); | 2595 | client); |
1665 | return client; | 2596 | idp = GNUNET_new (struct IdpClient); |
2597 | idp->client = client; | ||
2598 | idp->mq = mq; | ||
2599 | return idp; | ||
1666 | } | 2600 | } |
1667 | 2601 | ||
1668 | 2602 | ||
@@ -1677,13 +2611,45 @@ GNUNET_SERVICE_MAIN | |||
1677 | &client_connect_cb, | 2611 | &client_connect_cb, |
1678 | &client_disconnect_cb, | 2612 | &client_disconnect_cb, |
1679 | NULL, | 2613 | NULL, |
1680 | GNUNET_MQ_hd_var_size (issue_message, | 2614 | GNUNET_MQ_hd_var_size (attribute_store_message, |
1681 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE, | 2615 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE, |
1682 | struct IssueMessage, | 2616 | struct AttributeStoreMessage, |
2617 | NULL), | ||
2618 | GNUNET_MQ_hd_fixed_size (iteration_start, | ||
2619 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START, | ||
2620 | struct AttributeIterationStartMessage, | ||
2621 | NULL), | ||
2622 | GNUNET_MQ_hd_fixed_size (iteration_next, | ||
2623 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT, | ||
2624 | struct AttributeIterationNextMessage, | ||
2625 | NULL), | ||
2626 | GNUNET_MQ_hd_fixed_size (iteration_stop, | ||
2627 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP, | ||
2628 | struct AttributeIterationStopMessage, | ||
2629 | NULL), | ||
2630 | GNUNET_MQ_hd_var_size (issue_ticket_message, | ||
2631 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET, | ||
2632 | struct IssueTicketMessage, | ||
2633 | NULL), | ||
2634 | GNUNET_MQ_hd_var_size (consume_ticket_message, | ||
2635 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET, | ||
2636 | struct ConsumeTicketMessage, | ||
1683 | NULL), | 2637 | NULL), |
1684 | GNUNET_MQ_hd_var_size (exchange_message, | 2638 | GNUNET_MQ_hd_fixed_size (ticket_iteration_start, |
1685 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE, | 2639 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START, |
1686 | struct ExchangeMessage, | 2640 | struct TicketIterationStartMessage, |
2641 | NULL), | ||
2642 | GNUNET_MQ_hd_fixed_size (ticket_iteration_next, | ||
2643 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT, | ||
2644 | struct TicketIterationNextMessage, | ||
2645 | NULL), | ||
2646 | GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, | ||
2647 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP, | ||
2648 | struct TicketIterationStopMessage, | ||
2649 | NULL), | ||
2650 | GNUNET_MQ_hd_var_size (revoke_ticket_message, | ||
2651 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET, | ||
2652 | struct RevokeTicketMessage, | ||
1687 | NULL), | 2653 | NULL), |
1688 | GNUNET_MQ_handler_end()); | 2654 | GNUNET_MQ_handler_end()); |
1689 | /* end of gnunet-service-identity-provider.c */ | 2655 | /* end of gnunet-service-identity-provider.c */ |
diff --git a/src/identity-provider/identity-provider.conf b/src/identity-provider/identity-provider.conf index bac8e69ed..7ee5e50d8 100644 --- a/src/identity-provider/identity-provider.conf +++ b/src/identity-provider/identity-provider.conf | |||
@@ -10,3 +10,7 @@ UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-identity-provider.sock | |||
10 | UNIX_MATCH_UID = NO | 10 | UNIX_MATCH_UID = NO |
11 | UNIX_MATCH_GID = YES | 11 | UNIX_MATCH_GID = YES |
12 | TOKEN_EXPIRATION_INTERVAL = 30 m | 12 | TOKEN_EXPIRATION_INTERVAL = 30 m |
13 | DATABASE = sqlite | ||
14 | |||
15 | [identity-provider-sqlite] | ||
16 | FILENAME = $GNUNET_DATA_HOME/identity-provider/sqlite.db | ||
diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h index 6fe6102c8..be9fdc6f5 100644 --- a/src/identity-provider/identity_provider.h +++ b/src/identity-provider/identity_provider.h | |||
@@ -34,34 +34,157 @@ | |||
34 | GNUNET_NETWORK_STRUCT_BEGIN | 34 | GNUNET_NETWORK_STRUCT_BEGIN |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * The token | 37 | * Use to store an identity attribute |
38 | */ | 38 | */ |
39 | struct GNUNET_IDENTITY_PROVIDER_Token | 39 | struct 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 | */ |
50 | struct GNUNET_IDENTITY_PROVIDER_Ticket | 68 | struct 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 | */ | ||
90 | struct 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 | */ | ||
126 | struct 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 | */ | ||
149 | struct 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 | */ | ||
167 | struct 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 | */ |
61 | struct IssueResultMessage | 184 | struct 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 | */ |
81 | struct ExchangeResultMessage | 211 | struct 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 | */ | ||
229 | struct 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 | */ |
108 | struct IssueMessage | 248 | struct IssueTicketMessage |
109 | { | 249 | { |
110 | /** | 250 | /** |
111 | * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT | 251 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE |
112 | */ | 252 | */ |
113 | struct GNUNET_MessageHeader header; | 253 | struct GNUNET_MessageHeader header; |
114 | 254 | ||
@@ -117,40 +257,98 @@ struct IssueMessage | |||
117 | */ | 257 | */ |
118 | uint32_t id GNUNET_PACKED; | 258 | uint32_t id GNUNET_PACKED; |
119 | 259 | ||
260 | /** | ||
261 | * Identity. | ||
262 | */ | ||
263 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
120 | 264 | ||
121 | /** | 265 | /** |
122 | * Issuer identity private key | 266 | * Requesting party. |
123 | */ | 267 | */ |
124 | struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key; | 268 | struct GNUNET_CRYPTO_EcdsaPublicKey rp; |
125 | 269 | ||
126 | /** | 270 | /** |
127 | * Audience public key | 271 | * length of serialized attribute list |
128 | */ | 272 | */ |
129 | struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; | 273 | uint32_t attr_len GNUNET_PACKED; |
130 | 274 | ||
275 | //Followed by a serialized attribute list | ||
276 | }; | ||
277 | |||
278 | /** | ||
279 | * Ticket revoke message | ||
280 | */ | ||
281 | struct RevokeTicketMessage | ||
282 | { | ||
131 | /** | 283 | /** |
132 | * Nonce | 284 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE |
133 | */ | 285 | */ |
134 | uint64_t nonce; | 286 | struct GNUNET_MessageHeader header; |
135 | 287 | ||
136 | /** | 288 | /** |
137 | * Expiration of token in NBO. | 289 | * Unique identifier for this request (for key collisions). |
138 | */ | 290 | */ |
139 | struct GNUNET_TIME_AbsoluteNBO expiration; | 291 | uint32_t id GNUNET_PACKED; |
140 | 292 | ||
293 | /** | ||
294 | * Identity. | ||
295 | */ | ||
296 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
141 | 297 | ||
142 | /* followed by 0-terminated comma-separated scope list */ | 298 | /** |
299 | * length of serialized attribute list | ||
300 | */ | ||
301 | uint32_t attrs_len GNUNET_PACKED; | ||
143 | 302 | ||
303 | //Followed by a ticket and serialized attribute list | ||
304 | }; | ||
305 | |||
306 | /** | ||
307 | * Ticket revoke message | ||
308 | */ | ||
309 | struct RevokeTicketResultMessage | ||
310 | { | ||
311 | /** | ||
312 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE | ||
313 | */ | ||
314 | struct GNUNET_MessageHeader header; | ||
315 | |||
316 | /** | ||
317 | * Unique identifier for this request (for key collisions). | ||
318 | */ | ||
319 | uint32_t id GNUNET_PACKED; | ||
320 | |||
321 | /** | ||
322 | * Revocation result | ||
323 | */ | ||
324 | uint32_t success GNUNET_PACKED; | ||
144 | }; | 325 | }; |
145 | 326 | ||
146 | 327 | ||
147 | /** | 328 | /** |
148 | * Use to exchange a ticket for a token | 329 | * Ticket result message |
149 | */ | 330 | */ |
150 | struct ExchangeMessage | 331 | struct 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 | */ | ||
348 | struct ConsumeTicketMessage | ||
349 | { | ||
350 | /** | ||
351 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE | ||
154 | */ | 352 | */ |
155 | struct GNUNET_MessageHeader header; | 353 | struct GNUNET_MessageHeader header; |
156 | 354 | ||
@@ -160,15 +358,50 @@ struct ExchangeMessage | |||
160 | uint32_t id GNUNET_PACKED; | 358 | uint32_t id GNUNET_PACKED; |
161 | 359 | ||
162 | /** | 360 | /** |
163 | * Audience identity private key | 361 | * Identity. |
362 | */ | ||
363 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
364 | |||
365 | //Followed by a serialized ticket | ||
366 | }; | ||
367 | |||
368 | /** | ||
369 | * Attribute list is returned from the idp. | ||
370 | */ | ||
371 | struct 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 | |||
172 | GNUNET_NETWORK_STRUCT_END | 405 | GNUNET_NETWORK_STRUCT_END |
173 | 406 | ||
174 | #endif | 407 | #endif |
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c index 845d1f753..6fc8d228a 100644 --- a/src/identity-provider/identity_provider_api.c +++ b/src/identity-provider/identity_provider_api.c | |||
@@ -29,12 +29,12 @@ | |||
29 | #include "gnunet_protocols.h" | 29 | #include "gnunet_protocols.h" |
30 | #include "gnunet_mq_lib.h" | 30 | #include "gnunet_mq_lib.h" |
31 | #include "gnunet_identity_provider_service.h" | 31 | #include "gnunet_identity_provider_service.h" |
32 | #include "gnunet_identity_attribute_lib.h" | ||
32 | #include "identity_provider.h" | 33 | #include "identity_provider.h" |
33 | 34 | ||
34 | #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) | 35 | #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) |
35 | 36 | ||
36 | 37 | ||
37 | |||
38 | /** | 38 | /** |
39 | * Handle for an operation with the service. | 39 | * Handle for an operation with the service. |
40 | */ | 40 | */ |
@@ -63,16 +63,24 @@ struct GNUNET_IDENTITY_PROVIDER_Operation | |||
63 | const struct GNUNET_MessageHeader *msg; | 63 | const struct GNUNET_MessageHeader *msg; |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * Continuation to invoke with the result of the transmission; @e cb | 66 | * Continuation to invoke after attribute store call |
67 | * will be NULL in this case. | 67 | */ |
68 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb; | ||
69 | |||
70 | /** | ||
71 | * Attribute result callback | ||
72 | */ | ||
73 | GNUNET_IDENTITY_PROVIDER_AttributeResult ar_cb; | ||
74 | |||
75 | /** | ||
76 | * Revocation result callback | ||
68 | */ | 77 | */ |
69 | GNUNET_IDENTITY_PROVIDER_ExchangeCallback ex_cb; | 78 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus rvk_cb; |
70 | 79 | ||
71 | /** | 80 | /** |
72 | * Continuation to invoke with the result of the transmission for | 81 | * Ticket result callback |
73 | * 'issue' operations (@e cont will be NULL in this case). | ||
74 | */ | 82 | */ |
75 | GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb; | 83 | GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb; |
76 | 84 | ||
77 | /** | 85 | /** |
78 | * Envelope with the message for this queue entry. | 86 | * Envelope with the message for this queue entry. |
@@ -91,6 +99,140 @@ struct GNUNET_IDENTITY_PROVIDER_Operation | |||
91 | 99 | ||
92 | }; | 100 | }; |
93 | 101 | ||
102 | /** | ||
103 | * Handle for a ticket iterator operation | ||
104 | */ | ||
105 | struct 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 | */ | ||
170 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator | ||
171 | { | ||
172 | |||
173 | /** | ||
174 | * Kept in a DLL. | ||
175 | */ | ||
176 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next; | ||
177 | |||
178 | /** | ||
179 | * Kept in a DLL. | ||
180 | */ | ||
181 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev; | ||
182 | |||
183 | /** | ||
184 | * Main handle to access the idp. | ||
185 | */ | ||
186 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
187 | |||
188 | /** | ||
189 | * Function to call on completion. | ||
190 | */ | ||
191 | GNUNET_SCHEDULER_TaskCallback finish_cb; | ||
192 | |||
193 | /** | ||
194 | * Closure for @e error_cb. | ||
195 | */ | ||
196 | void *finish_cb_cls; | ||
197 | |||
198 | /** | ||
199 | * The continuation to call with the results | ||
200 | */ | ||
201 | GNUNET_IDENTITY_PROVIDER_AttributeResult proc; | ||
202 | |||
203 | /** | ||
204 | * Closure for @e proc. | ||
205 | */ | ||
206 | void *proc_cls; | ||
207 | |||
208 | /** | ||
209 | * Function to call on errors. | ||
210 | */ | ||
211 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
212 | |||
213 | /** | ||
214 | * Closure for @e error_cb. | ||
215 | */ | ||
216 | void *error_cb_cls; | ||
217 | |||
218 | /** | ||
219 | * Envelope of the message to send to the service, if not yet | ||
220 | * sent. | ||
221 | */ | ||
222 | struct GNUNET_MQ_Envelope *env; | ||
223 | |||
224 | /** | ||
225 | * Private key of the zone. | ||
226 | */ | ||
227 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
228 | |||
229 | /** | ||
230 | * The operation id this zone iteration operation has | ||
231 | */ | ||
232 | uint32_t r_id; | ||
233 | |||
234 | }; | ||
235 | |||
94 | 236 | ||
95 | /** | 237 | /** |
96 | * Handle for the service. | 238 | * Handle for the service. |
@@ -123,6 +265,27 @@ struct GNUNET_IDENTITY_PROVIDER_Handle | |||
123 | struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail; | 265 | struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail; |
124 | 266 | ||
125 | /** | 267 | /** |
268 | * Head of active iterations | ||
269 | */ | ||
270 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head; | ||
271 | |||
272 | /** | ||
273 | * Tail of active iterations | ||
274 | */ | ||
275 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail; | ||
276 | |||
277 | /** | ||
278 | * Head of active iterations | ||
279 | */ | ||
280 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_head; | ||
281 | |||
282 | /** | ||
283 | * Tail of active iterations | ||
284 | */ | ||
285 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_tail; | ||
286 | |||
287 | |||
288 | /** | ||
126 | * Currently pending transmission request, or NULL for none. | 289 | * Currently pending transmission request, or NULL for none. |
127 | */ | 290 | */ |
128 | struct GNUNET_CLIENT_TransmitHandle *th; | 291 | struct GNUNET_CLIENT_TransmitHandle *th; |
@@ -197,6 +360,26 @@ force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle) | |||
197 | } | 360 | } |
198 | 361 | ||
199 | /** | 362 | /** |
363 | * Free @a it. | ||
364 | * | ||
365 | * @param it entry to free | ||
366 | */ | ||
367 | static void | ||
368 | free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) | ||
369 | { | ||
370 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
371 | |||
372 | GNUNET_CONTAINER_DLL_remove (h->it_head, | ||
373 | h->it_tail, | ||
374 | it); | ||
375 | if (NULL != it->env) | ||
376 | GNUNET_MQ_discard (it->env); | ||
377 | GNUNET_free (it); | ||
378 | } | ||
379 | |||
380 | |||
381 | |||
382 | /** | ||
200 | * Generic error handler, called with the appropriate error code and | 383 | * Generic error handler, called with the appropriate error code and |
201 | * the same closure specified at the creation of the message queue. | 384 | * the same closure specified at the creation of the message queue. |
202 | * Not every message queue implementation supports an error handler. | 385 | * Not every message queue implementation supports an error handler. |
@@ -213,22 +396,68 @@ mq_error_handler (void *cls, | |||
213 | } | 396 | } |
214 | 397 | ||
215 | /** | 398 | /** |
216 | * Check validity of message received from the service | 399 | * Handle an incoming message of type |
400 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE | ||
401 | * | ||
402 | * @param cls | ||
403 | * @param msg the message we received | ||
404 | */ | ||
405 | static void | ||
406 | handle_attribute_store_response (void *cls, | ||
407 | const struct AttributeStoreResultMessage *msg) | ||
408 | { | ||
409 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
410 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
411 | uint32_t r_id = ntohl (msg->id); | ||
412 | int res; | ||
413 | const char *emsg; | ||
414 | |||
415 | for (op = h->op_head; NULL != op; op = op->next) | ||
416 | if (op->r_id == r_id) | ||
417 | break; | ||
418 | if (NULL == op) | ||
419 | return; | ||
420 | |||
421 | res = ntohl (msg->op_result); | ||
422 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
423 | "Received ATTRIBUTE_STORE_RESPONSE with result %d\n", | ||
424 | res); | ||
425 | |||
426 | /* TODO: add actual error message to response... */ | ||
427 | if (GNUNET_SYSERR == res) | ||
428 | emsg = _("failed to store record\n"); | ||
429 | else | ||
430 | emsg = NULL; | ||
431 | if (NULL != op->as_cb) | ||
432 | op->as_cb (op->cls, | ||
433 | res, | ||
434 | emsg); | ||
435 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
436 | h->op_tail, | ||
437 | op); | ||
438 | GNUNET_free (op); | ||
439 | |||
440 | } | ||
441 | |||
442 | |||
443 | /** | ||
444 | * Handle an incoming message of type | ||
445 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT | ||
217 | * | 446 | * |
218 | * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` | 447 | * @param cls |
219 | * @param result_msg the incoming message | 448 | * @param msg the message we received |
449 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
220 | */ | 450 | */ |
221 | static int | 451 | static int |
222 | check_exchange_result (void *cls, | 452 | check_consume_ticket_result (void *cls, |
223 | const struct ExchangeResultMessage *erm) | 453 | const struct ConsumeTicketResultMessage *msg) |
224 | { | 454 | { |
225 | char *str; | 455 | size_t msg_len; |
226 | size_t size = ntohs (erm->header.size) - sizeof (*erm); | 456 | size_t attrs_len; |
227 | |||
228 | 457 | ||
229 | str = (char *) &erm[1]; | 458 | msg_len = ntohs (msg->header.size); |
230 | if ( (size > sizeof (struct ExchangeResultMessage)) && | 459 | attrs_len = ntohs (msg->attrs_len); |
231 | ('\0' != str[size - sizeof (struct ExchangeResultMessage) - 1]) ) | 460 | if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len) |
232 | { | 461 | { |
233 | GNUNET_break (0); | 462 | GNUNET_break (0); |
234 | return GNUNET_SYSERR; | 463 | return GNUNET_SYSERR; |
@@ -238,20 +467,85 @@ check_exchange_result (void *cls, | |||
238 | 467 | ||
239 | 468 | ||
240 | /** | 469 | /** |
241 | * Check validity of message received from the service | 470 | * Handle an incoming message of type |
471 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT | ||
472 | * | ||
473 | * @param cls | ||
474 | * @param msg the message we received | ||
475 | */ | ||
476 | static void | ||
477 | handle_consume_ticket_result (void *cls, | ||
478 | const struct ConsumeTicketResultMessage *msg) | ||
479 | { | ||
480 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
481 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
482 | size_t attrs_len; | ||
483 | uint32_t r_id = ntohl (msg->id); | ||
484 | |||
485 | attrs_len = ntohs (msg->attrs_len); | ||
486 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
487 | "Processing attribute result.\n"); | ||
488 | |||
489 | |||
490 | for (op = h->op_head; NULL != op; op = op->next) | ||
491 | if (op->r_id == r_id) | ||
492 | break; | ||
493 | if (NULL == op) | ||
494 | return; | ||
495 | |||
496 | { | ||
497 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
498 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
499 | attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1], | ||
500 | attrs_len); | ||
501 | if (NULL != op->ar_cb) | ||
502 | { | ||
503 | if (NULL == attrs) | ||
504 | { | ||
505 | op->ar_cb (op->cls, | ||
506 | &msg->identity, | ||
507 | NULL); | ||
508 | } | ||
509 | else | ||
510 | { | ||
511 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
512 | op->ar_cb (op->cls, | ||
513 | &msg->identity, | ||
514 | le->claim); | ||
515 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs); | ||
516 | } | ||
517 | } | ||
518 | op->ar_cb (op->cls, | ||
519 | NULL, | ||
520 | NULL); | ||
521 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
522 | h->op_tail, | ||
523 | op); | ||
524 | GNUNET_free (op); | ||
525 | return; | ||
526 | } | ||
527 | GNUNET_assert (0); | ||
528 | } | ||
529 | |||
530 | |||
531 | /** | ||
532 | * Handle an incoming message of type | ||
533 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT | ||
242 | * | 534 | * |
243 | * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` | 535 | * @param cls |
244 | * @param result_msg the incoming message | 536 | * @param msg the message we received |
537 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
245 | */ | 538 | */ |
246 | static int | 539 | static int |
247 | check_result (void *cls, | 540 | check_attribute_result (void *cls, |
248 | const struct IssueResultMessage *irm) | 541 | const struct AttributeResultMessage *msg) |
249 | { | 542 | { |
250 | char *str; | 543 | size_t msg_len; |
251 | size_t size = ntohs (irm->header.size) - sizeof (*irm); | 544 | size_t attr_len; |
252 | str = (char*) &irm[1]; | 545 | |
253 | if ( (size > sizeof (struct IssueResultMessage)) && | 546 | msg_len = ntohs (msg->header.size); |
254 | ('\0' != str[size - sizeof (struct IssueResultMessage) - 1]) ) | 547 | attr_len = ntohs (msg->attr_len); |
548 | if (msg_len != sizeof (struct AttributeResultMessage) + attr_len) | ||
255 | { | 549 | { |
256 | GNUNET_break (0); | 550 | GNUNET_break (0); |
257 | return GNUNET_SYSERR; | 551 | return GNUNET_SYSERR; |
@@ -259,102 +553,225 @@ check_result (void *cls, | |||
259 | return GNUNET_OK; | 553 | return GNUNET_OK; |
260 | } | 554 | } |
261 | 555 | ||
556 | |||
262 | /** | 557 | /** |
263 | * Handler for messages received from the GNS service | 558 | * Handle an incoming message of type |
559 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT | ||
264 | * | 560 | * |
265 | * @param cls the `struct GNUNET_GNS_Handle *` | 561 | * @param cls |
266 | * @param loookup_msg the incoming message | 562 | * @param msg the message we received |
267 | */ | 563 | */ |
268 | static void | 564 | static void |
269 | handle_exchange_result (void *cls, | 565 | handle_attribute_result (void *cls, |
270 | const struct ExchangeResultMessage *erm) | 566 | const struct AttributeResultMessage *msg) |
271 | { | 567 | { |
272 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; | 568 | static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy; |
569 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
570 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it; | ||
273 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | 571 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; |
274 | struct GNUNET_IDENTITY_PROVIDER_Token token; | 572 | size_t attr_len; |
275 | uint64_t ticket_nonce; | 573 | uint32_t r_id = ntohl (msg->id); |
276 | uint32_t r_id = ntohl (erm->id); | 574 | |
277 | char *str; | 575 | attr_len = ntohs (msg->attr_len); |
278 | 576 | LOG (GNUNET_ERROR_TYPE_DEBUG, | |
279 | for (op = handle->op_head; NULL != op; op = op->next) | 577 | "Processing attribute result.\n"); |
578 | |||
579 | |||
580 | for (it = h->it_head; NULL != it; it = it->next) | ||
581 | if (it->r_id == r_id) | ||
582 | break; | ||
583 | for (op = h->op_head; NULL != op; op = op->next) | ||
280 | if (op->r_id == r_id) | 584 | if (op->r_id == r_id) |
281 | break; | 585 | break; |
282 | if (NULL == op) | 586 | if ((NULL == it) && (NULL == op)) |
283 | return; | 587 | return; |
284 | str = GNUNET_strdup ((char*)&erm[1]); | ||
285 | op = handle->op_head; | ||
286 | GNUNET_CONTAINER_DLL_remove (handle->op_head, | ||
287 | handle->op_tail, | ||
288 | op); | ||
289 | token.data = str; | ||
290 | ticket_nonce = ntohl (erm->ticket_nonce); | ||
291 | if (NULL != op->ex_cb) | ||
292 | op->ex_cb (op->cls, &token, ticket_nonce); | ||
293 | GNUNET_free (str); | ||
294 | GNUNET_free (op); | ||
295 | 588 | ||
589 | if ( (0 == (memcmp (&msg->identity, | ||
590 | &identity_dummy, | ||
591 | sizeof (identity_dummy)))) ) | ||
592 | { | ||
593 | if ((NULL == it) && (NULL == op)) | ||
594 | { | ||
595 | GNUNET_break (0); | ||
596 | force_reconnect (h); | ||
597 | return; | ||
598 | } | ||
599 | if (NULL != it) | ||
600 | { | ||
601 | if (NULL != it->finish_cb) | ||
602 | it->finish_cb (it->finish_cb_cls); | ||
603 | free_it (it); | ||
604 | } | ||
605 | if (NULL != op) | ||
606 | { | ||
607 | if (NULL != op->ar_cb) | ||
608 | op->ar_cb (op->cls, | ||
609 | NULL, | ||
610 | NULL); | ||
611 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
612 | h->op_tail, | ||
613 | op); | ||
614 | GNUNET_free (op); | ||
615 | |||
616 | } | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | { | ||
621 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr; | ||
622 | attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1], | ||
623 | attr_len); | ||
624 | if (NULL != it) | ||
625 | { | ||
626 | if (NULL != it->proc) | ||
627 | it->proc (it->proc_cls, | ||
628 | &msg->identity, | ||
629 | attr); | ||
630 | } else if (NULL != op) | ||
631 | { | ||
632 | if (NULL != op->ar_cb) | ||
633 | op->ar_cb (op->cls, | ||
634 | &msg->identity, | ||
635 | attr); | ||
636 | |||
637 | } | ||
638 | GNUNET_free (attr); | ||
639 | return; | ||
640 | } | ||
641 | GNUNET_assert (0); | ||
296 | } | 642 | } |
297 | 643 | ||
298 | /** | 644 | /** |
299 | * Handler for messages received from the GNS service | 645 | * Handle an incoming message of type |
646 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT | ||
300 | * | 647 | * |
301 | * @param cls the `struct GNUNET_GNS_Handle *` | 648 | * @param cls |
302 | * @param loookup_msg the incoming message | 649 | * @param msg the message we received |
650 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
651 | */ | ||
652 | static int | ||
653 | check_ticket_result (void *cls, | ||
654 | const struct TicketResultMessage *msg) | ||
655 | { | ||
656 | size_t msg_len; | ||
657 | |||
658 | msg_len = ntohs (msg->header.size); | ||
659 | if (msg_len < sizeof (struct TicketResultMessage)) | ||
660 | { | ||
661 | GNUNET_break (0); | ||
662 | return GNUNET_SYSERR; | ||
663 | } | ||
664 | return GNUNET_OK; | ||
665 | } | ||
666 | |||
667 | |||
668 | |||
669 | /** | ||
670 | * Handle an incoming message of type | ||
671 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT | ||
672 | * | ||
673 | * @param cls | ||
674 | * @param msg the message we received | ||
303 | */ | 675 | */ |
304 | static void | 676 | static void |
305 | handle_result (void *cls, | 677 | handle_ticket_result (void *cls, |
306 | const struct IssueResultMessage *irm) | 678 | const struct TicketResultMessage *msg) |
307 | { | 679 | { |
308 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; | 680 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; |
309 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | 681 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; |
310 | struct GNUNET_IDENTITY_PROVIDER_Token token; | 682 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; |
311 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | 683 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; |
312 | uint32_t r_id = ntohl (irm->id); | 684 | uint32_t r_id = ntohl (msg->id); |
313 | char *str; | 685 | size_t msg_len; |
314 | char *label_str; | ||
315 | char *ticket_str; | ||
316 | char *token_str; | ||
317 | 686 | ||
318 | for (op = handle->op_head; NULL != op; op = op->next) | 687 | for (op = handle->op_head; NULL != op; op = op->next) |
319 | if (op->r_id == r_id) | 688 | if (op->r_id == r_id) |
320 | break; | 689 | break; |
321 | if (NULL == op) | 690 | for (it = handle->ticket_it_head; NULL != it; it = it->next) |
691 | if (it->r_id == r_id) | ||
692 | break; | ||
693 | if ((NULL == op) && (NULL == it)) | ||
322 | return; | 694 | return; |
323 | str = GNUNET_strdup ((char*)&irm[1]); | 695 | msg_len = ntohs (msg->header.size); |
324 | label_str = strtok (str, ","); | 696 | if (NULL != op) |
325 | |||
326 | if (NULL == label_str) | ||
327 | { | 697 | { |
328 | GNUNET_free (str); | 698 | GNUNET_CONTAINER_DLL_remove (handle->op_head, |
329 | GNUNET_break (0); | 699 | handle->op_tail, |
700 | op); | ||
701 | if (msg_len == sizeof (struct TicketResultMessage)) | ||
702 | { | ||
703 | if (NULL != op->tr_cb) | ||
704 | op->tr_cb (op->cls, NULL); | ||
705 | } else { | ||
706 | ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1]; | ||
707 | if (NULL != op->tr_cb) | ||
708 | op->tr_cb (op->cls, ticket); | ||
709 | } | ||
710 | GNUNET_free (op); | ||
330 | return; | 711 | return; |
331 | } | 712 | } else if (NULL != it) { |
332 | ticket_str = strtok (NULL, ","); | 713 | if (msg_len == sizeof (struct TicketResultMessage)) |
333 | if (NULL == ticket_str) | 714 | { |
334 | { | 715 | if (NULL != it->tr_cb) |
335 | GNUNET_free (str); | 716 | GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head, |
336 | GNUNET_break (0); | 717 | handle->ticket_it_tail, |
718 | it); | ||
719 | it->finish_cb (it->finish_cb_cls); | ||
720 | GNUNET_free (it); | ||
721 | } else { | ||
722 | ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1]; | ||
723 | if (NULL != it->tr_cb) | ||
724 | it->tr_cb (it->cls, ticket); | ||
725 | } | ||
337 | return; | 726 | return; |
338 | } | 727 | } |
339 | token_str = strtok (NULL, ","); | 728 | GNUNET_break (0); |
340 | if (NULL == token_str) | 729 | } |
730 | |||
731 | /** | ||
732 | * Handle an incoming message of type | ||
733 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT | ||
734 | * | ||
735 | * @param cls | ||
736 | * @param msg the message we received | ||
737 | */ | ||
738 | static void | ||
739 | handle_revoke_ticket_result (void *cls, | ||
740 | const struct RevokeTicketResultMessage *msg) | ||
741 | { | ||
742 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
743 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
744 | uint32_t r_id = ntohl (msg->id); | ||
745 | int32_t success; | ||
746 | |||
747 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
748 | "Processing revocation result.\n"); | ||
749 | |||
750 | |||
751 | for (op = h->op_head; NULL != op; op = op->next) | ||
752 | if (op->r_id == r_id) | ||
753 | break; | ||
754 | if (NULL == op) | ||
755 | return; | ||
756 | success = ntohl (msg->success); | ||
341 | { | 757 | { |
342 | GNUNET_free (str); | 758 | if (NULL != op->rvk_cb) |
343 | GNUNET_break (0); | 759 | { |
760 | op->rvk_cb (op->cls, | ||
761 | success, | ||
762 | NULL); | ||
763 | } | ||
764 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
765 | h->op_tail, | ||
766 | op); | ||
767 | GNUNET_free (op); | ||
344 | return; | 768 | return; |
345 | } | 769 | } |
346 | GNUNET_CONTAINER_DLL_remove (handle->op_head, | 770 | GNUNET_assert (0); |
347 | handle->op_tail, | ||
348 | op); | ||
349 | ticket.data = ticket_str; | ||
350 | token.data = token_str; | ||
351 | if (NULL != op->iss_cb) | ||
352 | op->iss_cb (op->cls, label_str, &ticket, &token); | ||
353 | GNUNET_free (str); | ||
354 | GNUNET_free (op); | ||
355 | |||
356 | } | 771 | } |
357 | 772 | ||
773 | |||
774 | |||
358 | /** | 775 | /** |
359 | * Try again to connect to the service. | 776 | * Try again to connect to the service. |
360 | * | 777 | * |
@@ -364,14 +781,26 @@ static void | |||
364 | reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) | 781 | reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) |
365 | { | 782 | { |
366 | struct GNUNET_MQ_MessageHandler handlers[] = { | 783 | struct GNUNET_MQ_MessageHandler handlers[] = { |
367 | GNUNET_MQ_hd_var_size (result, | 784 | GNUNET_MQ_hd_fixed_size (attribute_store_response, |
368 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT, | 785 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE, |
369 | struct IssueResultMessage, | 786 | struct AttributeStoreResultMessage, |
787 | h), | ||
788 | GNUNET_MQ_hd_var_size (attribute_result, | ||
789 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT, | ||
790 | struct AttributeResultMessage, | ||
370 | h), | 791 | h), |
371 | GNUNET_MQ_hd_var_size (exchange_result, | 792 | GNUNET_MQ_hd_var_size (ticket_result, |
372 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT, | 793 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT, |
373 | struct ExchangeResultMessage, | 794 | struct TicketResultMessage, |
374 | h), | 795 | h), |
796 | GNUNET_MQ_hd_var_size (consume_ticket_result, | ||
797 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT, | ||
798 | struct ConsumeTicketResultMessage, | ||
799 | h), | ||
800 | GNUNET_MQ_hd_fixed_size (revoke_ticket_result, | ||
801 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT, | ||
802 | struct RevokeTicketResultMessage, | ||
803 | h), | ||
375 | GNUNET_MQ_handler_end () | 804 | GNUNET_MQ_handler_end () |
376 | }; | 805 | }; |
377 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | 806 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; |
@@ -417,111 +846,6 @@ GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
417 | 846 | ||
418 | 847 | ||
419 | /** | 848 | /** |
420 | * Issue an identity token | ||
421 | * | ||
422 | * @param id identity service to query | ||
423 | * @param service_name for which service is an identity wanted | ||
424 | * @param cb function to call with the result (will only be called once) | ||
425 | * @param cb_cls closure for @a cb | ||
426 | * @return handle to abort the operation | ||
427 | */ | ||
428 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
429 | GNUNET_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 | */ | ||
481 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
482 | GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id, | ||
483 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
484 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey, | ||
485 | GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont, | ||
486 | void *cont_cls) | ||
487 | { | ||
488 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
489 | struct ExchangeMessage *em; | ||
490 | size_t slen; | ||
491 | char *ticket_str; | ||
492 | |||
493 | ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket); | ||
494 | |||
495 | slen = strlen (ticket_str) + 1; | ||
496 | if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct ExchangeMessage)) | ||
497 | { | ||
498 | GNUNET_free (ticket_str); | ||
499 | GNUNET_break (0); | ||
500 | return NULL; | ||
501 | } | ||
502 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
503 | op->h = id; | ||
504 | op->ex_cb = cont; | ||
505 | op->cls = cont_cls; | ||
506 | op->r_id = id->r_id_gen++; | ||
507 | op->env = GNUNET_MQ_msg_extra (em, | ||
508 | slen, | ||
509 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE); | ||
510 | em->aud_privkey = *aud_privkey; | ||
511 | em->id = htonl (op->r_id); | ||
512 | GNUNET_memcpy (&em[1], ticket_str, slen); | ||
513 | GNUNET_free (ticket_str); | ||
514 | GNUNET_CONTAINER_DLL_insert_tail (id->op_head, | ||
515 | id->op_tail, | ||
516 | op); | ||
517 | if (NULL != id->mq) | ||
518 | GNUNET_MQ_send_copy (id->mq, | ||
519 | op->env); | ||
520 | return op; | ||
521 | } | ||
522 | |||
523 | |||
524 | /** | ||
525 | * Cancel an operation. Note that the operation MAY still | 849 | * Cancel an operation. Note that the operation MAY still |
526 | * be executed; this merely cancels the continuation; if the request | 850 | * be executed; this merely cancels the continuation; if the request |
527 | * was already transmitted, the service may still choose to complete | 851 | * was already transmitted, the service may still choose to complete |
@@ -566,80 +890,483 @@ GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) | |||
566 | } | 890 | } |
567 | 891 | ||
568 | /** | 892 | /** |
569 | * Convenience API | 893 | * Store an attribute. If the attribute is already present, |
894 | * it is replaced with the new attribute. | ||
895 | * | ||
896 | * @param h handle to the identity provider | ||
897 | * @param pkey private key of the identity | ||
898 | * @param name the attribute name | ||
899 | * @param value the attribute value | ||
900 | * @param cont continuation to call when done | ||
901 | * @param cont_cls closure for @a cont | ||
902 | * @return handle to abort the request | ||
903 | */ | ||
904 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
905 | GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
906 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, | ||
907 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr, | ||
908 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont, | ||
909 | void *cont_cls) | ||
910 | { | ||
911 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
912 | struct AttributeStoreMessage *sam; | ||
913 | size_t attr_len; | ||
914 | |||
915 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
916 | op->h = h; | ||
917 | op->as_cb = cont; | ||
918 | op->cls = cont_cls; | ||
919 | op->r_id = h->r_id_gen++; | ||
920 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
921 | h->op_tail, | ||
922 | op); | ||
923 | attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr); | ||
924 | op->env = GNUNET_MQ_msg_extra (sam, | ||
925 | attr_len, | ||
926 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE); | ||
927 | sam->identity = *pkey; | ||
928 | sam->id = htonl (op->r_id); | ||
929 | |||
930 | GNUNET_IDENTITY_ATTRIBUTE_serialize (attr, | ||
931 | (char*)&sam[1]); | ||
932 | |||
933 | sam->attr_len = htons (attr_len); | ||
934 | if (NULL != h->mq) | ||
935 | GNUNET_MQ_send_copy (h->mq, | ||
936 | op->env); | ||
937 | return op; | ||
938 | |||
939 | } | ||
940 | |||
941 | |||
942 | /** | ||
943 | * List all attributes for a local identity. | ||
944 | * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle` | ||
945 | * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and | ||
946 | * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once | ||
947 | * immediately, and then again after | ||
948 | * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked. | ||
949 | * | ||
950 | * On error (disconnect), @a error_cb will be invoked. | ||
951 | * On normal completion, @a finish_cb proc will be | ||
952 | * invoked. | ||
953 | * | ||
954 | * @param h handle to the idp | ||
955 | * @param identity identity to access | ||
956 | * @param error_cb function to call on error (i.e. disconnect), | ||
957 | * the handle is afterwards invalid | ||
958 | * @param error_cb_cls closure for @a error_cb | ||
959 | * @param proc function to call on each attribute; it | ||
960 | * will be called repeatedly with a value (if available) | ||
961 | * @param proc_cls closure for @a proc | ||
962 | * @param finish_cb function to call on completion | ||
963 | * the handle is afterwards invalid | ||
964 | * @param finish_cb_cls closure for @a finish_cb | ||
965 | * @return an iterator handle to use for iteration | ||
966 | */ | ||
967 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator * | ||
968 | GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
969 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
970 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
971 | void *error_cb_cls, | ||
972 | GNUNET_IDENTITY_PROVIDER_AttributeResult proc, | ||
973 | void *proc_cls, | ||
974 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
975 | void *finish_cb_cls) | ||
976 | { | ||
977 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it; | ||
978 | struct GNUNET_MQ_Envelope *env; | ||
979 | struct AttributeIterationStartMessage *msg; | ||
980 | uint32_t rid; | ||
981 | |||
982 | rid = h->r_id_gen++; | ||
983 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator); | ||
984 | it->h = h; | ||
985 | it->error_cb = error_cb; | ||
986 | it->error_cb_cls = error_cb_cls; | ||
987 | it->finish_cb = finish_cb; | ||
988 | it->finish_cb_cls = finish_cb_cls; | ||
989 | it->proc = proc; | ||
990 | it->proc_cls = proc_cls; | ||
991 | it->r_id = rid; | ||
992 | it->identity = *identity; | ||
993 | GNUNET_CONTAINER_DLL_insert_tail (h->it_head, | ||
994 | h->it_tail, | ||
995 | it); | ||
996 | env = GNUNET_MQ_msg (msg, | ||
997 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START); | ||
998 | msg->id = htonl (rid); | ||
999 | msg->identity = *identity; | ||
1000 | if (NULL == h->mq) | ||
1001 | it->env = env; | ||
1002 | else | ||
1003 | GNUNET_MQ_send (h->mq, | ||
1004 | env); | ||
1005 | return it; | ||
1006 | } | ||
1007 | |||
1008 | |||
1009 | /** | ||
1010 | * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start | ||
1011 | * for the next record. | ||
1012 | * | ||
1013 | * @param it the iterator | ||
570 | */ | 1014 | */ |
1015 | void | ||
1016 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) | ||
1017 | { | ||
1018 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
1019 | struct AttributeIterationNextMessage *msg; | ||
1020 | struct GNUNET_MQ_Envelope *env; | ||
1021 | |||
1022 | env = GNUNET_MQ_msg (msg, | ||
1023 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT); | ||
1024 | msg->id = htonl (it->r_id); | ||
1025 | GNUNET_MQ_send (h->mq, | ||
1026 | env); | ||
1027 | } | ||
571 | 1028 | ||
572 | 1029 | ||
573 | /** | 1030 | /** |
574 | * Destroy token | 1031 | * Stops iteration and releases the idp handle for further calls. Must |
1032 | * be called on any iteration that has not yet completed prior to calling | ||
1033 | * #GNUNET_IDENTITY_PROVIDER_disconnect. | ||
575 | * | 1034 | * |
576 | * @param token the token | 1035 | * @param it the iterator |
577 | */ | 1036 | */ |
578 | void | 1037 | void |
579 | GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token) | 1038 | GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) |
1039 | { | ||
1040 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
1041 | struct GNUNET_MQ_Envelope *env; | ||
1042 | struct AttributeIterationStopMessage *msg; | ||
1043 | |||
1044 | if (NULL != h->mq) | ||
1045 | { | ||
1046 | env = GNUNET_MQ_msg (msg, | ||
1047 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP); | ||
1048 | msg->id = htonl (it->r_id); | ||
1049 | GNUNET_MQ_send (h->mq, | ||
1050 | env); | ||
1051 | } | ||
1052 | free_it (it); | ||
1053 | } | ||
1054 | |||
1055 | |||
1056 | /** TODO | ||
1057 | * Issues a ticket to another identity. The identity may use | ||
1058 | * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket | ||
1059 | * and retrieve the attributes specified in the AttributeList. | ||
1060 | * | ||
1061 | * @param h the identity provider to use | ||
1062 | * @param iss the issuing identity | ||
1063 | * @param rp the subject of the ticket (the relying party) | ||
1064 | * @param attr the attributes that the relying party is given access to | ||
1065 | * @param cb the callback | ||
1066 | * @param cb_cls the callback closure | ||
1067 | * @return handle to abort the operation | ||
1068 | */ | ||
1069 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1070 | GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1071 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, | ||
1072 | const struct GNUNET_CRYPTO_EcdsaPublicKey *rp, | ||
1073 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
1074 | GNUNET_IDENTITY_PROVIDER_TicketCallback cb, | ||
1075 | void *cb_cls) | ||
1076 | { | ||
1077 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
1078 | struct IssueTicketMessage *tim; | ||
1079 | size_t attr_len; | ||
1080 | |||
1081 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
1082 | op->h = h; | ||
1083 | op->tr_cb = cb; | ||
1084 | op->cls = cb_cls; | ||
1085 | op->r_id = h->r_id_gen++; | ||
1086 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1087 | h->op_tail, | ||
1088 | op); | ||
1089 | attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs); | ||
1090 | op->env = GNUNET_MQ_msg_extra (tim, | ||
1091 | attr_len, | ||
1092 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET); | ||
1093 | tim->identity = *iss; | ||
1094 | tim->rp = *rp; | ||
1095 | tim->id = htonl (op->r_id); | ||
1096 | |||
1097 | GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs, | ||
1098 | (char*)&tim[1]); | ||
1099 | |||
1100 | tim->attr_len = htons (attr_len); | ||
1101 | if (NULL != h->mq) | ||
1102 | GNUNET_MQ_send_copy (h->mq, | ||
1103 | op->env); | ||
1104 | return op; | ||
1105 | } | ||
1106 | |||
1107 | /** | ||
1108 | * Consumes an issued ticket. The ticket is persisted | ||
1109 | * and used to retrieve identity information from the issuer | ||
1110 | * | ||
1111 | * @param id the identity provider to use | ||
1112 | * @param identity the identity that is the subject of the issued ticket (the relying party) | ||
1113 | * @param ticket the issued ticket to consume | ||
1114 | * @param cb the callback to call | ||
1115 | * @param cb_cls the callback closure | ||
1116 | * @return handle to abort the operation | ||
1117 | */ | ||
1118 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1119 | GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1120 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1121 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1122 | GNUNET_IDENTITY_PROVIDER_AttributeResult cb, | ||
1123 | void *cb_cls) | ||
580 | { | 1124 | { |
581 | GNUNET_assert (NULL != token); | 1125 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; |
582 | if (NULL != token->data) | 1126 | struct ConsumeTicketMessage *ctm; |
583 | GNUNET_free (token->data); | 1127 | |
584 | GNUNET_free (token); | 1128 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); |
1129 | op->h = h; | ||
1130 | op->ar_cb = cb; | ||
1131 | op->cls = cb_cls; | ||
1132 | op->r_id = h->r_id_gen++; | ||
1133 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1134 | h->op_tail, | ||
1135 | op); | ||
1136 | op->env = GNUNET_MQ_msg_extra (ctm, | ||
1137 | sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket), | ||
1138 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET); | ||
1139 | ctm->identity = *identity; | ||
1140 | ctm->id = htonl (op->r_id); | ||
1141 | |||
1142 | GNUNET_memcpy ((char*)&ctm[1], | ||
1143 | ticket, | ||
1144 | sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
1145 | |||
1146 | if (NULL != h->mq) | ||
1147 | GNUNET_MQ_send_copy (h->mq, | ||
1148 | op->env); | ||
1149 | return op; | ||
1150 | |||
585 | } | 1151 | } |
586 | 1152 | ||
1153 | |||
587 | /** | 1154 | /** |
588 | * Returns string representation of token. A JSON-Web-Token. | 1155 | * Lists all tickets that have been issued to remote |
1156 | * identites (relying parties) | ||
589 | * | 1157 | * |
590 | * @param token the token | 1158 | * @param h the identity provider to use |
591 | * @return The JWT (must be freed) | 1159 | * @param identity the issuing identity |
1160 | * @param error_cb function to call on error (i.e. disconnect), | ||
1161 | * the handle is afterwards invalid | ||
1162 | * @param error_cb_cls closure for @a error_cb | ||
1163 | * @param proc function to call on each ticket; it | ||
1164 | * will be called repeatedly with a value (if available) | ||
1165 | * @param proc_cls closure for @a proc | ||
1166 | * @param finish_cb function to call on completion | ||
1167 | * the handle is afterwards invalid | ||
1168 | * @param finish_cb_cls closure for @a finish_cb | ||
1169 | * @return an iterator handle to use for iteration | ||
592 | */ | 1170 | */ |
593 | char * | 1171 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator * |
594 | GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token) | 1172 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h, |
1173 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1174 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1175 | void *error_cb_cls, | ||
1176 | GNUNET_IDENTITY_PROVIDER_TicketCallback proc, | ||
1177 | void *proc_cls, | ||
1178 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1179 | void *finish_cb_cls) | ||
595 | { | 1180 | { |
596 | return GNUNET_strdup (token->data); | 1181 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; |
1182 | struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub; | ||
1183 | struct GNUNET_MQ_Envelope *env; | ||
1184 | struct TicketIterationStartMessage *msg; | ||
1185 | uint32_t rid; | ||
1186 | |||
1187 | GNUNET_CRYPTO_ecdsa_key_get_public (identity, | ||
1188 | &identity_pub); | ||
1189 | rid = h->r_id_gen++; | ||
1190 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator); | ||
1191 | it->h = h; | ||
1192 | it->error_cb = error_cb; | ||
1193 | it->error_cb_cls = error_cb_cls; | ||
1194 | it->finish_cb = finish_cb; | ||
1195 | it->finish_cb_cls = finish_cb_cls; | ||
1196 | it->tr_cb = proc; | ||
1197 | it->cls = proc_cls; | ||
1198 | it->r_id = rid; | ||
1199 | GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, | ||
1200 | h->ticket_it_tail, | ||
1201 | it); | ||
1202 | env = GNUNET_MQ_msg (msg, | ||
1203 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START); | ||
1204 | msg->id = htonl (rid); | ||
1205 | msg->identity = identity_pub; | ||
1206 | msg->is_audience = htonl (GNUNET_NO); | ||
1207 | if (NULL == h->mq) | ||
1208 | it->env = env; | ||
1209 | else | ||
1210 | GNUNET_MQ_send (h->mq, | ||
1211 | env); | ||
1212 | return it; | ||
1213 | |||
597 | } | 1214 | } |
598 | 1215 | ||
1216 | |||
599 | /** | 1217 | /** |
600 | * Returns string representation of ticket. Base64-Encoded | 1218 | * Lists all tickets that have been issued to remote |
1219 | * identites (relying parties) | ||
601 | * | 1220 | * |
602 | * @param ticket the ticket | 1221 | * @param id the identity provider to use |
603 | * @return the Base64-Encoded ticket | 1222 | * @param identity the issuing identity |
1223 | * @param error_cb function to call on error (i.e. disconnect), | ||
1224 | * the handle is afterwards invalid | ||
1225 | * @param error_cb_cls closure for @a error_cb | ||
1226 | * @param proc function to call on each ticket; it | ||
1227 | * will be called repeatedly with a value (if available) | ||
1228 | * @param proc_cls closure for @a proc | ||
1229 | * @param finish_cb function to call on completion | ||
1230 | * the handle is afterwards invalid | ||
1231 | * @param finish_cb_cls closure for @a finish_cb | ||
1232 | * @return an iterator handle to use for iteration | ||
604 | */ | 1233 | */ |
605 | char * | 1234 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator * |
606 | GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | 1235 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h, |
1236 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
1237 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1238 | void *error_cb_cls, | ||
1239 | GNUNET_IDENTITY_PROVIDER_TicketCallback proc, | ||
1240 | void *proc_cls, | ||
1241 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1242 | void *finish_cb_cls) | ||
607 | { | 1243 | { |
608 | return GNUNET_strdup (ticket->data); | 1244 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; |
1245 | struct GNUNET_MQ_Envelope *env; | ||
1246 | struct TicketIterationStartMessage *msg; | ||
1247 | uint32_t rid; | ||
1248 | |||
1249 | rid = h->r_id_gen++; | ||
1250 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator); | ||
1251 | it->h = h; | ||
1252 | it->error_cb = error_cb; | ||
1253 | it->error_cb_cls = error_cb_cls; | ||
1254 | it->finish_cb = finish_cb; | ||
1255 | it->finish_cb_cls = finish_cb_cls; | ||
1256 | it->tr_cb = proc; | ||
1257 | it->cls = proc_cls; | ||
1258 | it->r_id = rid; | ||
1259 | GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, | ||
1260 | h->ticket_it_tail, | ||
1261 | it); | ||
1262 | env = GNUNET_MQ_msg (msg, | ||
1263 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START); | ||
1264 | msg->id = htonl (rid); | ||
1265 | msg->identity = *identity; | ||
1266 | msg->is_audience = htonl (GNUNET_YES); | ||
1267 | if (NULL == h->mq) | ||
1268 | it->env = env; | ||
1269 | else | ||
1270 | GNUNET_MQ_send (h->mq, | ||
1271 | env); | ||
1272 | return it; | ||
1273 | |||
1274 | |||
609 | } | 1275 | } |
610 | 1276 | ||
611 | /** | 1277 | /** |
612 | * Created a ticket from a string (Base64 encoded ticket) | 1278 | * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start |
1279 | * for the next record. | ||
613 | * | 1280 | * |
614 | * @param input Base64 encoded ticket | 1281 | * @param it the iterator |
615 | * @param ticket pointer where the ticket is stored | ||
616 | * @return GNUNET_OK | ||
617 | */ | 1282 | */ |
618 | int | 1283 | void |
619 | GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, | 1284 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it) |
620 | struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket) | ||
621 | { | 1285 | { |
622 | *ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | 1286 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; |
623 | (*ticket)->data = GNUNET_strdup (input); | 1287 | struct TicketIterationNextMessage *msg; |
624 | return GNUNET_OK; | 1288 | struct GNUNET_MQ_Envelope *env; |
1289 | |||
1290 | env = GNUNET_MQ_msg (msg, | ||
1291 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT); | ||
1292 | msg->id = htonl (it->r_id); | ||
1293 | GNUNET_MQ_send (h->mq, | ||
1294 | env); | ||
625 | } | 1295 | } |
626 | 1296 | ||
627 | 1297 | ||
628 | /** | 1298 | /** |
629 | * Destroys a ticket | 1299 | * Stops iteration and releases the idp handle for further calls. Must |
1300 | * be called on any iteration that has not yet completed prior to calling | ||
1301 | * #GNUNET_IDENTITY_PROVIDER_disconnect. | ||
630 | * | 1302 | * |
631 | * @param ticket the ticket to destroy | 1303 | * @param it the iterator |
632 | */ | 1304 | */ |
633 | void | 1305 | void |
634 | GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | 1306 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it) |
635 | { | 1307 | { |
636 | GNUNET_assert (NULL != ticket); | 1308 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; |
637 | if (NULL != ticket->data) | 1309 | struct GNUNET_MQ_Envelope *env; |
638 | GNUNET_free (ticket->data); | 1310 | struct TicketIterationStopMessage *msg; |
639 | GNUNET_free (ticket); | 1311 | |
1312 | if (NULL != h->mq) | ||
1313 | { | ||
1314 | env = GNUNET_MQ_msg (msg, | ||
1315 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP); | ||
1316 | msg->id = htonl (it->r_id); | ||
1317 | GNUNET_MQ_send (h->mq, | ||
1318 | env); | ||
1319 | } | ||
1320 | GNUNET_free (it); | ||
640 | } | 1321 | } |
641 | 1322 | ||
1323 | /** | ||
1324 | * Revoked an issued ticket. The relying party will be unable to retrieve | ||
1325 | * updated attributes. | ||
1326 | * | ||
1327 | * @param id the identity provider to use | ||
1328 | * @param identity the issuing identity | ||
1329 | * @param ticket the ticket to revoke | ||
1330 | * @param cb the callback | ||
1331 | * @param cb_cls the callback closure | ||
1332 | * @return handle to abort the operation | ||
1333 | */ | ||
1334 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1335 | GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1336 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1337 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1338 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb, | ||
1339 | void *cb_cls) | ||
1340 | { | ||
1341 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
1342 | struct GNUNET_MQ_Envelope *env; | ||
1343 | struct RevokeTicketMessage *msg; | ||
1344 | uint32_t rid; | ||
642 | 1345 | ||
1346 | rid = h->r_id_gen++; | ||
1347 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
1348 | op->h = h; | ||
1349 | op->rvk_cb = cb; | ||
1350 | op->cls = cb_cls; | ||
1351 | op->r_id = rid; | ||
1352 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1353 | h->op_tail, | ||
1354 | op); | ||
1355 | env = GNUNET_MQ_msg_extra (msg, | ||
1356 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket), | ||
1357 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET); | ||
1358 | msg->id = htonl (rid); | ||
1359 | msg->identity = *identity; | ||
1360 | memcpy (&msg[1], | ||
1361 | ticket, | ||
1362 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
1363 | if (NULL == h->mq) | ||
1364 | op->env = env; | ||
1365 | else | ||
1366 | GNUNET_MQ_send (h->mq, | ||
1367 | env); | ||
1368 | return op; | ||
1369 | } | ||
643 | 1370 | ||
644 | 1371 | ||
645 | 1372 | ||
diff --git a/src/identity-provider/identity_token.c b/src/identity-provider/identity_token.c deleted file mode 100644 index 31249840b..000000000 --- a/src/identity-provider/identity_token.c +++ /dev/null | |||
@@ -1,964 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2010-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file identity-provider/identity_token.c | ||
23 | * @brief helper library to manage identity tokens | ||
24 | * @author Martin Schanzenbach | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_signatures.h" | ||
29 | #include "identity_token.h" | ||
30 | #include <jansson.h> | ||
31 | #include <inttypes.h> | ||
32 | |||
33 | #define JWT_ALG "alg" | ||
34 | |||
35 | #define JWT_ALG_VALUE "ED512" | ||
36 | |||
37 | #define JWT_TYP "typ" | ||
38 | |||
39 | #define JWT_TYP_VALUE "jwt" | ||
40 | |||
41 | /** | ||
42 | * Crypto helper functions | ||
43 | */ | ||
44 | |||
45 | static int | ||
46 | create_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 | */ | ||
73 | static int | ||
74 | decrypt_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 | */ | ||
122 | static int | ||
123 | decrypt_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 | */ | ||
153 | static int | ||
154 | encrypt_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 | */ | ||
202 | struct IdentityToken* | ||
203 | token_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 | |||
225 | void | ||
226 | token_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 | |||
259 | void | ||
260 | token_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 | |||
290 | void | ||
291 | token_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 | |||
321 | static void | ||
322 | parse_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 | |||
366 | int | ||
367 | token_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 | |||
410 | int | ||
411 | token_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 | |||
461 | static char* | ||
462 | create_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 | |||
491 | static char* | ||
492 | create_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 | |||
506 | int | ||
507 | token_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 | |||
573 | int | ||
574 | token_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 | |||
607 | struct TokenTicketPayload* | ||
608 | ticket_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 | |||
621 | void | ||
622 | ticket_payload_destroy (struct TokenTicketPayload* payload) | ||
623 | { | ||
624 | if (NULL != payload->label) | ||
625 | GNUNET_free (payload->label); | ||
626 | GNUNET_free (payload); | ||
627 | } | ||
628 | |||
629 | void | ||
630 | ticket_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 | */ | ||
653 | struct TokenTicket* | ||
654 | ticket_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 | |||
673 | void | ||
674 | ticket_destroy (struct TokenTicket *ticket) | ||
675 | { | ||
676 | ticket_payload_destroy (ticket->payload); | ||
677 | GNUNET_free (ticket); | ||
678 | } | ||
679 | |||
680 | int | ||
681 | ticket_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 | |||
747 | int | ||
748 | ticket_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 | |||
840 | int | ||
841 | ticket_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 | |||
32 | struct 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 | |||
55 | struct 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 | |||
84 | struct 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 | |||
108 | struct 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 | |||
127 | struct 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 | */ | ||
160 | struct IdentityToken* | ||
161 | token_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 | */ | ||
169 | void | ||
170 | token_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 | */ | ||
179 | void | ||
180 | token_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 | */ | ||
191 | void | ||
192 | token_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 | */ | ||
269 | int | ||
270 | token_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 | */ | ||
303 | struct TokenTicket* | ||
304 | ticket_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 | */ | ||
329 | void | ||
330 | ticket_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 | */ | ||
341 | int | ||
342 | ticket_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 | |||
42 | static char* | ||
43 | create_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 | */ | ||
65 | char* | ||
66 | jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, | ||
67 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
68 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key) | ||
69 | { | ||
70 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
71 | struct GNUNET_CRYPTO_EcdsaPublicKey iss_key; | ||
72 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
73 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | ||
74 | char* audience; | ||
75 | char* issuer; | ||
76 | char* header; | ||
77 | char* padding; | ||
78 | char* body_str; | ||
79 | char* result; | ||
80 | char* header_base64; | ||
81 | char* body_base64; | ||
82 | char* signature_target; | ||
83 | char* signature_base64; | ||
84 | char* attr_val_str; | ||
85 | json_t* body; | ||
86 | |||
87 | GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &iss_key); | ||
88 | /* TODO maybe we should use a local identity here */ | ||
89 | issuer = GNUNET_STRINGS_data_to_string_alloc (&iss_key, | ||
90 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
91 | audience = GNUNET_STRINGS_data_to_string_alloc (sub_key, | ||
92 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
93 | header = create_jwt_header (); | ||
94 | body = json_object (); | ||
95 | /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */ | ||
96 | json_object_set_new (body, | ||
97 | "iss", json_string (issuer)); | ||
98 | json_object_set_new (body, | ||
99 | "sub", json_string (issuer)); | ||
100 | /* TODO what should be in here exactly? */ | ||
101 | json_object_set_new (body, | ||
102 | "aud", json_string (audience)); | ||
103 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
104 | { | ||
105 | /** | ||
106 | * TODO here we should have a function that | ||
107 | * calls the Attribute plugins to create a | ||
108 | * json representation for its value | ||
109 | */ | ||
110 | attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type, | ||
111 | le->claim->data, | ||
112 | le->claim->data_size); | ||
113 | json_object_set_new (body, | ||
114 | le->claim->name, | ||
115 | json_string (attr_val_str)); | ||
116 | GNUNET_free (attr_val_str); | ||
117 | } | ||
118 | body_str = json_dumps (body, JSON_INDENT(0)); | ||
119 | json_decref (body); | ||
120 | |||
121 | GNUNET_STRINGS_base64_encode (header, | ||
122 | strlen (header), | ||
123 | &header_base64); | ||
124 | //Remove GNUNET padding of base64 | ||
125 | padding = strtok(header_base64, "="); | ||
126 | while (NULL != padding) | ||
127 | padding = strtok(NULL, "="); | ||
128 | |||
129 | GNUNET_STRINGS_base64_encode (body_str, | ||
130 | strlen (body_str), | ||
131 | &body_base64); | ||
132 | |||
133 | //Remove GNUNET padding of base64 | ||
134 | padding = strtok(body_base64, "="); | ||
135 | while (NULL != padding) | ||
136 | padding = strtok(NULL, "="); | ||
137 | |||
138 | GNUNET_free (issuer); | ||
139 | GNUNET_free (audience); | ||
140 | |||
141 | /** | ||
142 | * TODO | ||
143 | * Creating the JWT signature. This might not be | ||
144 | * standards compliant, check. | ||
145 | */ | ||
146 | GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64); | ||
147 | |||
148 | purpose = | ||
149 | GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
150 | strlen (signature_target)); | ||
151 | purpose->size = | ||
152 | htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); | ||
153 | purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN); | ||
154 | GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target)); | ||
155 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key, | ||
156 | purpose, | ||
157 | (struct GNUNET_CRYPTO_EcdsaSignature *)&signature)) | ||
158 | { | ||
159 | GNUNET_free (signature_target); | ||
160 | GNUNET_free (body_str); | ||
161 | GNUNET_free (body_base64); | ||
162 | GNUNET_free (header_base64); | ||
163 | GNUNET_free (purpose); | ||
164 | return NULL; | ||
165 | } | ||
166 | GNUNET_STRINGS_base64_encode ((const char*)&signature, | ||
167 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature), | ||
168 | &signature_base64); | ||
169 | GNUNET_asprintf (&result, "%s.%s.%s", | ||
170 | header_base64, body_base64, signature_base64); | ||
171 | |||
172 | GNUNET_free (signature_target); | ||
173 | GNUNET_free (header); | ||
174 | GNUNET_free (body_str); | ||
175 | GNUNET_free (signature_base64); | ||
176 | GNUNET_free (body_base64); | ||
177 | GNUNET_free (header_base64); | ||
178 | GNUNET_free (purpose); | ||
179 | return result; | ||
180 | } | ||
diff --git a/src/identity/plugin_gnsrecord_identity.c b/src/identity-provider/plugin_gnsrecord_identity_provider.c index c26c04074..ad5a95dc7 100644 --- a/src/identity/plugin_gnsrecord_identity.c +++ b/src/identity-provider/plugin_gnsrecord_identity_provider.c | |||
@@ -54,9 +54,13 @@ value_to_string (void *cls, | |||
54 | switch (type) | 54 | switch (type) |
55 | { | 55 | { |
56 | case GNUNET_GNSRECORD_TYPE_ID_ATTR: | 56 | case GNUNET_GNSRECORD_TYPE_ID_ATTR: |
57 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN: | 57 | return GNUNET_STRINGS_data_to_string_alloc (data, data_size); |
58 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED | ||
58 | return GNUNET_strndup (data, data_size); | 59 | return GNUNET_strndup (data, data_size); |
59 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: | 60 | case GNUNET_GNSRECORD_TYPE_ABE_KEY: |
61 | case GNUNET_GNSRECORD_TYPE_ABE_MASTER: | ||
62 | return GNUNET_STRINGS_data_to_string_alloc (data, data_size); | ||
63 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED | ||
60 | ecdhe_privkey = data; | 64 | ecdhe_privkey = data; |
61 | audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); | 65 | audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); |
62 | scopes = (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | 66 | scopes = (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); |
@@ -106,12 +110,22 @@ string_to_value (void *cls, | |||
106 | switch (type) | 110 | switch (type) |
107 | { | 111 | { |
108 | case GNUNET_GNSRECORD_TYPE_ID_ATTR: | 112 | case GNUNET_GNSRECORD_TYPE_ID_ATTR: |
113 | return GNUNET_STRINGS_string_to_data (s, | ||
114 | strlen (s), | ||
115 | *data, | ||
116 | *data_size); | ||
109 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN: | 117 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN: |
110 | *data = GNUNET_strdup (s); | 118 | *data = GNUNET_strdup (s); |
111 | *data_size = strlen (s); | 119 | *data_size = strlen (s); |
112 | return GNUNET_OK; | 120 | return GNUNET_OK; |
121 | case GNUNET_GNSRECORD_TYPE_ABE_KEY: | ||
122 | case GNUNET_GNSRECORD_TYPE_ABE_MASTER: | ||
123 | return GNUNET_STRINGS_string_to_data (s, | ||
124 | strlen (s), | ||
125 | *data, | ||
126 | *data_size); | ||
113 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: | 127 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: |
114 | tmp_tok = GNUNET_strdup (s); | 128 | tmp_tok = GNUNET_strdup (s); |
115 | ecdhe_str = strtok (tmp_tok, ";"); | 129 | ecdhe_str = strtok (tmp_tok, ";"); |
116 | if (NULL == ecdhe_str) | 130 | if (NULL == ecdhe_str) |
117 | { | 131 | { |
@@ -160,15 +174,17 @@ string_to_value (void *cls, | |||
160 | * Mapping of record type numbers to human-readable | 174 | * Mapping of record type numbers to human-readable |
161 | * record type names. | 175 | * record type names. |
162 | */ | 176 | */ |
163 | static struct { | 177 | static 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 | */ |
222 | void * | 238 | void * |
223 | libgnunet_plugin_gnsrecord_identity_init (void *cls) | 239 | libgnunet_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 | */ |
242 | void * | 258 | void * |
243 | libgnunet_plugin_gnsrecord_identity_done (void *cls) | 259 | libgnunet_plugin_gnsrecord_identity_provider_done (void *cls) |
244 | { | 260 | { |
245 | struct GNUNET_GNSRECORD_PluginFunctions *api = cls; | 261 | struct GNUNET_GNSRECORD_PluginFunctions *api = cls; |
246 | 262 | ||
diff --git a/src/identity-provider/plugin_identity_provider_sqlite.c b/src/identity-provider/plugin_identity_provider_sqlite.c new file mode 100644 index 000000000..594e4788d --- /dev/null +++ b/src/identity-provider/plugin_identity_provider_sqlite.c | |||
@@ -0,0 +1,736 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2009-2017 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published | ||
7 | * by the Free Software Foundation; either version 3, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * GNUnet is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with GNUnet; see the file COPYING. If not, write to the | ||
17 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | * Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file identity-provider/plugin_identity_provider_sqlite.c | ||
23 | * @brief sqlite-based idp backend | ||
24 | * @author Martin Schanzenbach | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_identity_provider_service.h" | ||
29 | #include "gnunet_identity_provider_plugin.h" | ||
30 | #include "gnunet_identity_attribute_lib.h" | ||
31 | #include "gnunet_sq_lib.h" | ||
32 | #include <sqlite3.h> | ||
33 | |||
34 | /** | ||
35 | * After how many ms "busy" should a DB operation fail for good? A | ||
36 | * low value makes sure that we are more responsive to requests | ||
37 | * (especially PUTs). A high value guarantees a higher success rate | ||
38 | * (SELECTs in iterate can take several seconds despite LIMIT=1). | ||
39 | * | ||
40 | * The default value of 1s should ensure that users do not experience | ||
41 | * huge latencies while at the same time allowing operations to | ||
42 | * succeed with reasonable probability. | ||
43 | */ | ||
44 | #define BUSY_TIMEOUT_MS 1000 | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Log an error message at log-level 'level' that indicates | ||
49 | * a failure of the command 'cmd' on file 'filename' | ||
50 | * with the message given by strerror(errno). | ||
51 | */ | ||
52 | #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "identity-provider", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) | ||
53 | |||
54 | #define LOG(kind,...) GNUNET_log_from (kind, "identity-provider-sqlite", __VA_ARGS__) | ||
55 | |||
56 | |||
57 | /** | ||
58 | * Context for all functions in this plugin. | ||
59 | */ | ||
60 | struct 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 | */ | ||
110 | static int | ||
111 | sq_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 | */ | ||
137 | static void | ||
138 | create_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 | */ | ||
174 | static int | ||
175 | database_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 | */ | ||
316 | static void | ||
317 | database_shutdown (struct Plugin *plugin) | ||
318 | { | ||
319 | int result; | ||
320 | sqlite3_stmt *stmt; | ||
321 | |||
322 | if (NULL != plugin->store_ticket) | ||
323 | sqlite3_finalize (plugin->store_ticket); | ||
324 | if (NULL != plugin->delete_ticket) | ||
325 | sqlite3_finalize (plugin->delete_ticket); | ||
326 | if (NULL != plugin->iterate_tickets) | ||
327 | sqlite3_finalize (plugin->iterate_tickets); | ||
328 | if (NULL != plugin->iterate_tickets_by_audience) | ||
329 | sqlite3_finalize (plugin->iterate_tickets_by_audience); | ||
330 | if (NULL != plugin->get_ticket_attrs) | ||
331 | sqlite3_finalize (plugin->get_ticket_attrs); | ||
332 | result = sqlite3_close (plugin->dbh); | ||
333 | if (result == SQLITE_BUSY) | ||
334 | { | ||
335 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
336 | _("Tried to close sqlite without finalizing all prepared statements.\n")); | ||
337 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
338 | NULL); | ||
339 | while (NULL != stmt) | ||
340 | { | ||
341 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
342 | "sqlite", | ||
343 | "Closing statement %p\n", | ||
344 | stmt); | ||
345 | result = sqlite3_finalize (stmt); | ||
346 | if (result != SQLITE_OK) | ||
347 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
348 | "sqlite", | ||
349 | "Failed to close statement %p: %d\n", | ||
350 | stmt, | ||
351 | result); | ||
352 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
353 | NULL); | ||
354 | } | ||
355 | result = sqlite3_close (plugin->dbh); | ||
356 | } | ||
357 | if (SQLITE_OK != result) | ||
358 | LOG_SQLITE (plugin, | ||
359 | GNUNET_ERROR_TYPE_ERROR, | ||
360 | "sqlite3_close"); | ||
361 | |||
362 | GNUNET_free_non_null (plugin->fn); | ||
363 | } | ||
364 | |||
365 | |||
366 | /** | ||
367 | * Store a ticket in the database. | ||
368 | * | ||
369 | * @param cls closure (internal context for the plugin) | ||
370 | * @param ticket the ticket to persist | ||
371 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
372 | */ | ||
373 | static int | ||
374 | identity_provider_sqlite_store_ticket (void *cls, | ||
375 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
376 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) | ||
377 | { | ||
378 | struct Plugin *plugin = cls; | ||
379 | size_t attrs_len; | ||
380 | char *attrs_ser; | ||
381 | int n; | ||
382 | |||
383 | { | ||
384 | /* First delete duplicates */ | ||
385 | struct GNUNET_SQ_QueryParam dparams[] = { | ||
386 | GNUNET_SQ_query_param_auto_from_type (&ticket->identity), | ||
387 | GNUNET_SQ_query_param_uint64 (&ticket->rnd), | ||
388 | GNUNET_SQ_query_param_end | ||
389 | }; | ||
390 | if (GNUNET_OK != | ||
391 | GNUNET_SQ_bind (plugin->delete_ticket, | ||
392 | dparams)) | ||
393 | { | ||
394 | LOG_SQLITE (plugin, | ||
395 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
396 | "sqlite3_bind_XXXX"); | ||
397 | GNUNET_SQ_reset (plugin->dbh, | ||
398 | plugin->delete_ticket); | ||
399 | return GNUNET_SYSERR; | ||
400 | } | ||
401 | n = sqlite3_step (plugin->delete_ticket); | ||
402 | GNUNET_SQ_reset (plugin->dbh, | ||
403 | plugin->delete_ticket); | ||
404 | |||
405 | attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs); | ||
406 | attrs_ser = GNUNET_malloc (attrs_len); | ||
407 | GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs, | ||
408 | attrs_ser); | ||
409 | struct GNUNET_SQ_QueryParam sparams[] = { | ||
410 | GNUNET_SQ_query_param_auto_from_type (&ticket->identity), | ||
411 | GNUNET_SQ_query_param_auto_from_type (&ticket->audience), | ||
412 | GNUNET_SQ_query_param_uint64 (&ticket->rnd), | ||
413 | GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len), | ||
414 | GNUNET_SQ_query_param_end | ||
415 | }; | ||
416 | |||
417 | if (GNUNET_OK != | ||
418 | GNUNET_SQ_bind (plugin->store_ticket, | ||
419 | sparams)) | ||
420 | { | ||
421 | LOG_SQLITE (plugin, | ||
422 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
423 | "sqlite3_bind_XXXX"); | ||
424 | GNUNET_SQ_reset (plugin->dbh, | ||
425 | plugin->store_ticket); | ||
426 | return GNUNET_SYSERR; | ||
427 | } | ||
428 | n = sqlite3_step (plugin->store_ticket); | ||
429 | GNUNET_SQ_reset (plugin->dbh, | ||
430 | plugin->store_ticket); | ||
431 | GNUNET_free (attrs_ser); | ||
432 | } | ||
433 | switch (n) | ||
434 | { | ||
435 | case SQLITE_DONE: | ||
436 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
437 | "sqlite", | ||
438 | "Ticket stored\n"); | ||
439 | return GNUNET_OK; | ||
440 | case SQLITE_BUSY: | ||
441 | LOG_SQLITE (plugin, | ||
442 | GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
443 | "sqlite3_step"); | ||
444 | return GNUNET_NO; | ||
445 | default: | ||
446 | LOG_SQLITE (plugin, | ||
447 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
448 | "sqlite3_step"); | ||
449 | return GNUNET_SYSERR; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | |||
454 | /** | ||
455 | * Store a ticket in the database. | ||
456 | * | ||
457 | * @param cls closure (internal context for the plugin) | ||
458 | * @param ticket the ticket to delete | ||
459 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
460 | */ | ||
461 | static int | ||
462 | identity_provider_sqlite_delete_ticket (void *cls, | ||
463 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | ||
464 | { | ||
465 | struct Plugin *plugin = cls; | ||
466 | int n; | ||
467 | |||
468 | { | ||
469 | struct GNUNET_SQ_QueryParam sparams[] = { | ||
470 | GNUNET_SQ_query_param_auto_from_type (&ticket->identity), | ||
471 | GNUNET_SQ_query_param_uint64 (&ticket->rnd), | ||
472 | GNUNET_SQ_query_param_end | ||
473 | }; | ||
474 | |||
475 | if (GNUNET_OK != | ||
476 | GNUNET_SQ_bind (plugin->delete_ticket, | ||
477 | sparams)) | ||
478 | { | ||
479 | LOG_SQLITE (plugin, | ||
480 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
481 | "sqlite3_bind_XXXX"); | ||
482 | GNUNET_SQ_reset (plugin->dbh, | ||
483 | plugin->store_ticket); | ||
484 | return GNUNET_SYSERR; | ||
485 | } | ||
486 | n = sqlite3_step (plugin->delete_ticket); | ||
487 | GNUNET_SQ_reset (plugin->dbh, | ||
488 | plugin->delete_ticket); | ||
489 | } | ||
490 | switch (n) | ||
491 | { | ||
492 | case SQLITE_DONE: | ||
493 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
494 | "sqlite", | ||
495 | "Ticket deleted\n"); | ||
496 | return GNUNET_OK; | ||
497 | case SQLITE_BUSY: | ||
498 | LOG_SQLITE (plugin, | ||
499 | GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
500 | "sqlite3_step"); | ||
501 | return GNUNET_NO; | ||
502 | default: | ||
503 | LOG_SQLITE (plugin, | ||
504 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
505 | "sqlite3_step"); | ||
506 | return GNUNET_SYSERR; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | |||
511 | /** | ||
512 | * The given 'sqlite' statement has been prepared to be run. | ||
513 | * It will return a record which should be given to the iterator. | ||
514 | * Runs the statement and parses the returned record. | ||
515 | * | ||
516 | * @param plugin plugin context | ||
517 | * @param stmt to run (and then clean up) | ||
518 | * @param iter iterator to call with the result | ||
519 | * @param iter_cls closure for @a iter | ||
520 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
521 | */ | ||
522 | static int | ||
523 | get_ticket_and_call_iterator (struct Plugin *plugin, | ||
524 | sqlite3_stmt *stmt, | ||
525 | GNUNET_IDENTITY_PROVIDER_TicketIterator iter, | ||
526 | void *iter_cls) | ||
527 | { | ||
528 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
529 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
530 | int ret; | ||
531 | int sret; | ||
532 | size_t attrs_len; | ||
533 | char *attrs_ser; | ||
534 | |||
535 | ret = GNUNET_NO; | ||
536 | if (SQLITE_ROW == (sret = sqlite3_step (stmt))) | ||
537 | { | ||
538 | struct GNUNET_SQ_ResultSpec rs[] = { | ||
539 | GNUNET_SQ_result_spec_auto_from_type (&ticket.identity), | ||
540 | GNUNET_SQ_result_spec_auto_from_type (&ticket.audience), | ||
541 | GNUNET_SQ_result_spec_uint64 (&ticket.rnd), | ||
542 | GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser, | ||
543 | &attrs_len), | ||
544 | GNUNET_SQ_result_spec_end | ||
545 | |||
546 | }; | ||
547 | ret = GNUNET_SQ_extract_result (stmt, | ||
548 | rs); | ||
549 | if (GNUNET_OK != ret) | ||
550 | { | ||
551 | GNUNET_break (0); | ||
552 | ret = GNUNET_SYSERR; | ||
553 | } | ||
554 | else | ||
555 | { | ||
556 | attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (attrs_ser, | ||
557 | attrs_len); | ||
558 | if (NULL != iter) | ||
559 | iter (iter_cls, | ||
560 | &ticket, | ||
561 | attrs); | ||
562 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs); | ||
563 | ret = GNUNET_YES; | ||
564 | } | ||
565 | GNUNET_SQ_cleanup_result (rs); | ||
566 | } | ||
567 | else | ||
568 | { | ||
569 | if (SQLITE_DONE != sret) | ||
570 | LOG_SQLITE (plugin, | ||
571 | GNUNET_ERROR_TYPE_ERROR, | ||
572 | "sqlite_step"); | ||
573 | } | ||
574 | GNUNET_SQ_reset (plugin->dbh, | ||
575 | stmt); | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | |||
580 | /** | ||
581 | * Lookup tickets in the datastore. | ||
582 | * | ||
583 | * @param cls closure (internal context for the plugin) | ||
584 | * @param zone private key of the zone | ||
585 | * @param label name of the record in the zone | ||
586 | * @param iter function to call with the result | ||
587 | * @param iter_cls closure for @a iter | ||
588 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
589 | */ | ||
590 | static int | ||
591 | identity_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 | */ | ||
632 | static int | ||
633 | identity_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 | */ | ||
688 | void * | ||
689 | libgnunet_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 | */ | ||
722 | void * | ||
723 | libgnunet_plugin_identity_provider_sqlite_done (void *cls) | ||
724 | { | ||
725 | struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api = cls; | ||
726 | struct Plugin *plugin = api->cls; | ||
727 | |||
728 | database_shutdown (plugin); | ||
729 | plugin->cfg = NULL; | ||
730 | GNUNET_free (api); | ||
731 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
732 | "sqlite plugin is finished\n"); | ||
733 | return NULL; | ||
734 | } | ||
735 | |||
736 | /* end of plugin_identity_provider_sqlite.c */ | ||
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c index 907b28ba9..c27662a0d 100644 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ b/src/identity-provider/plugin_rest_identity_provider.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <jansson.h> | 37 | #include <jansson.h> |
38 | #include <inttypes.h> | 38 | #include <inttypes.h> |
39 | #include "gnunet_signatures.h" | 39 | #include "gnunet_signatures.h" |
40 | #include "gnunet_identity_attribute_lib.h" | ||
40 | #include "gnunet_identity_provider_service.h" | 41 | #include "gnunet_identity_provider_service.h" |
41 | 42 | ||
42 | /** | 43 | /** |
@@ -45,39 +46,40 @@ | |||
45 | #define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp" | 46 | #define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp" |
46 | 47 | ||
47 | /** | 48 | /** |
48 | * Issue namespace | 49 | * Attribute namespace |
49 | */ | 50 | */ |
50 | #define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/idp/issue" | 51 | #define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes" |
51 | 52 | ||
52 | /** | 53 | /** |
53 | * Check namespace TODO | 54 | * Ticket namespace |
54 | */ | 55 | */ |
55 | #define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/idp/check" | 56 | #define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets" |
56 | 57 | ||
57 | /** | 58 | /** |
58 | * Token namespace | 59 | * Revoke namespace |
59 | */ | 60 | */ |
60 | #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token" | 61 | #define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke" |
61 | 62 | ||
62 | /** | 63 | /** |
63 | * The parameter name in which the ticket must be provided | 64 | * Revoke namespace |
64 | */ | 65 | */ |
65 | #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket" | 66 | #define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume" |
66 | 67 | ||
67 | /** | 68 | /** |
68 | * The parameter name in which the expected nonce must be provided | 69 | * Attribute key |
69 | */ | 70 | */ |
70 | #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce" | 71 | #define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute" |
71 | 72 | ||
72 | /** | 73 | /** |
73 | * The parameter name in which the ticket must be provided | 74 | * Ticket key |
74 | */ | 75 | */ |
75 | #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token" | 76 | #define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket" |
77 | |||
76 | 78 | ||
77 | /** | 79 | /** |
78 | * The URL parameter name in which the nonce must be provided | 80 | * Value key |
79 | */ | 81 | */ |
80 | #define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce" | 82 | #define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value" |
81 | 83 | ||
82 | /** | 84 | /** |
83 | * State while collecting all egos | 85 | * State while collecting all egos |
@@ -89,41 +91,6 @@ | |||
89 | */ | 91 | */ |
90 | #define ID_REST_STATE_POST_INIT 1 | 92 | #define ID_REST_STATE_POST_INIT 1 |
91 | 93 | ||
92 | /** | ||
93 | * Resource type | ||
94 | */ | ||
95 | #define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token" | ||
96 | |||
97 | /** | ||
98 | * URL parameter to create a GNUid token for a specific audience | ||
99 | */ | ||
100 | #define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience" | ||
101 | |||
102 | /** | ||
103 | * URL parameter to create a GNUid token for a specific issuer (EGO) | ||
104 | */ | ||
105 | #define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer" | ||
106 | |||
107 | /** | ||
108 | * Attributes passed to issue request | ||
109 | */ | ||
110 | #define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs" | ||
111 | |||
112 | /** | ||
113 | * Token expiration string | ||
114 | */ | ||
115 | #define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration" | ||
116 | |||
117 | /** | ||
118 | * Error messages | ||
119 | */ | ||
120 | #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" | ||
121 | #define GNUNET_REST_ERROR_NO_DATA "No data" | ||
122 | |||
123 | /** | ||
124 | * GNUid token lifetime | ||
125 | */ | ||
126 | #define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000 | ||
127 | 94 | ||
128 | /** | 95 | /** |
129 | * The configuration handle | 96 | * The configuration handle |
@@ -198,11 +165,6 @@ struct RequestHandle | |||
198 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | 165 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; |
199 | 166 | ||
200 | /** | 167 | /** |
201 | * Handle to the rest connection | ||
202 | */ | ||
203 | struct GNUNET_REST_RequestHandle *conndata_handle; | ||
204 | |||
205 | /** | ||
206 | * The processing state | 168 | * The processing state |
207 | */ | 169 | */ |
208 | int state; | 170 | int state; |
@@ -213,6 +175,12 @@ struct RequestHandle | |||
213 | struct GNUNET_IDENTITY_Handle *identity_handle; | 175 | struct GNUNET_IDENTITY_Handle *identity_handle; |
214 | 176 | ||
215 | /** | 177 | /** |
178 | * Rest connection | ||
179 | */ | ||
180 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
181 | |||
182 | |||
183 | /** | ||
216 | * IDENTITY Operation | 184 | * IDENTITY Operation |
217 | */ | 185 | */ |
218 | struct GNUNET_IDENTITY_Operation *op; | 186 | struct GNUNET_IDENTITY_Operation *op; |
@@ -228,19 +196,14 @@ struct RequestHandle | |||
228 | struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; | 196 | struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; |
229 | 197 | ||
230 | /** | 198 | /** |
231 | * Handle to NS service | 199 | * Attribute iterator |
232 | */ | 200 | */ |
233 | struct GNUNET_NAMESTORE_Handle *ns_handle; | 201 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it; |
234 | 202 | ||
235 | /** | 203 | /** |
236 | * NS iterator | 204 | * Ticket iterator |
237 | */ | 205 | */ |
238 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | 206 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it; |
239 | |||
240 | /** | ||
241 | * NS Handle | ||
242 | */ | ||
243 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
244 | 207 | ||
245 | /** | 208 | /** |
246 | * Desired timeout for the lookup (default is no timeout). | 209 | * Desired timeout for the lookup (default is no timeout). |
@@ -285,6 +248,7 @@ struct RequestHandle | |||
285 | }; | 248 | }; |
286 | 249 | ||
287 | 250 | ||
251 | |||
288 | /** | 252 | /** |
289 | * Cleanup lookup handle | 253 | * Cleanup lookup handle |
290 | * @param handle Handle to clean up | 254 | * @param handle Handle to clean up |
@@ -302,14 +266,12 @@ cleanup_handle (struct RequestHandle *handle) | |||
302 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | 266 | GNUNET_SCHEDULER_cancel (handle->timeout_task); |
303 | if (NULL != handle->identity_handle) | 267 | if (NULL != handle->identity_handle) |
304 | GNUNET_IDENTITY_disconnect (handle->identity_handle); | 268 | GNUNET_IDENTITY_disconnect (handle->identity_handle); |
269 | if (NULL != handle->attr_it) | ||
270 | GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it); | ||
271 | if (NULL != handle->ticket_it) | ||
272 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it); | ||
305 | if (NULL != handle->idp) | 273 | if (NULL != handle->idp) |
306 | GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp); | 274 | GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp); |
307 | if (NULL != handle->ns_it) | ||
308 | GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it); | ||
309 | if (NULL != handle->ns_qe) | ||
310 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
311 | if (NULL != handle->ns_handle) | ||
312 | GNUNET_NAMESTORE_disconnect (handle->ns_handle); | ||
313 | if (NULL != handle->url) | 275 | if (NULL != handle->url) |
314 | GNUNET_free (handle->url); | 276 | GNUNET_free (handle->url); |
315 | if (NULL != handle->emsg) | 277 | if (NULL != handle->emsg) |
@@ -326,6 +288,12 @@ cleanup_handle (struct RequestHandle *handle) | |||
326 | GNUNET_free (handle); | 288 | GNUNET_free (handle); |
327 | } | 289 | } |
328 | 290 | ||
291 | static void | ||
292 | cleanup_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 | */ | ||
371 | static void | 334 | static void |
372 | do_cleanup_handle_delayed (void *cls) | 335 | collect_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 | */ | ||
385 | static void | 342 | static void |
386 | token_creat_cont (void *cls, | 343 | finished_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); | 366 | static void |
414 | GNUNET_JSONAPI_resource_add_attr (json_resource, | 367 | return_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 | |||
382 | static void | ||
383 | collect_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 | */ |
442 | static void | 397 | static void |
443 | issue_token_cont (struct GNUNET_REST_RequestHandle *con, | 398 | ticket_collect (void *cls, |
444 | const char *url, | 399 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) |
445 | void *cls) | ||
446 | { | 400 | { |
447 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | 401 | struct GNUNET_JSONAPI_Resource *json_resource; |
448 | const char *egoname; | 402 | struct RequestHandle *handle = cls; |
403 | json_t *value; | ||
404 | char* tmp; | ||
405 | |||
406 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n"); | ||
407 | tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, | ||
408 | sizeof (uint64_t)); | ||
409 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET, | ||
410 | tmp); | ||
411 | GNUNET_free (tmp); | ||
412 | GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); | ||
413 | |||
414 | tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity, | ||
415 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
416 | value = json_string (tmp); | ||
417 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
418 | "issuer", | ||
419 | value); | ||
420 | GNUNET_free (tmp); | ||
421 | json_decref (value); | ||
422 | tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience, | ||
423 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
424 | value = json_string (tmp); | ||
425 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
426 | "audience", | ||
427 | value); | ||
428 | GNUNET_free (tmp); | ||
429 | json_decref (value); | ||
430 | tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, | ||
431 | sizeof (uint64_t)); | ||
432 | value = json_string (tmp); | ||
433 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
434 | "rnd", | ||
435 | value); | ||
436 | GNUNET_free (tmp); | ||
437 | json_decref (value); | ||
438 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (handle->ticket_it); | ||
439 | } | ||
449 | 440 | ||
441 | |||
442 | |||
443 | /** | ||
444 | * List tickets for identity request | ||
445 | * | ||
446 | * @param con_handle the connection handle | ||
447 | * @param url the url | ||
448 | * @param cls the RequestHandle | ||
449 | */ | ||
450 | static void | ||
451 | list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
452 | const char* url, | ||
453 | void *cls) | ||
454 | { | ||
455 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
450 | struct RequestHandle *handle = cls; | 456 | struct RequestHandle *handle = cls; |
451 | struct EgoEntry *ego_entry; | 457 | struct EgoEntry *ego_entry; |
452 | struct GNUNET_HashCode key; | 458 | char *identity; |
453 | struct MHD_Response *resp; | 459 | |
454 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | 460 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n", |
455 | struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; | 461 | handle->url); |
456 | struct GNUNET_TIME_Relative etime_rel; | 462 | if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= |
457 | struct GNUNET_TIME_Absolute exp_time; | 463 | strlen (handle->url)) |
458 | char *ego_val; | ||
459 | char *audience; | ||
460 | char *exp_str; | ||
461 | char *nonce_str; | ||
462 | char *scopes; | ||
463 | uint64_t time; | ||
464 | uint64_t nonce; | ||
465 | |||
466 | if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, | ||
467 | GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE)) | ||
468 | { | ||
469 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url); | ||
470 | resp = GNUNET_REST_create_response (NULL); | ||
471 | handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); | ||
472 | cleanup_handle (handle); | ||
473 | return; | ||
474 | } | ||
475 | egoname = NULL; | ||
476 | ego_entry = NULL; | ||
477 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST, | ||
478 | strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST), | ||
479 | &key); | ||
480 | if ( GNUNET_YES != | ||
481 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | ||
482 | &key) ) | ||
483 | { | ||
484 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
485 | "Issuer not found\n"); | ||
486 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
487 | return; | ||
488 | } | ||
489 | ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | ||
490 | &key); | ||
491 | if (NULL == ego_val) | ||
492 | { | 464 | { |
465 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); | ||
493 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 466 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
494 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
495 | "Ego invalid: %s\n", | ||
496 | ego_val); | ||
497 | return; | 467 | return; |
498 | } | 468 | } |
469 | identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1; | ||
470 | |||
499 | for (ego_entry = handle->ego_head; | 471 | for (ego_entry = handle->ego_head; |
500 | NULL != ego_entry; | 472 | NULL != ego_entry; |
501 | ego_entry = ego_entry->next) | 473 | ego_entry = ego_entry->next) |
474 | if (0 == strcmp (identity, ego_entry->identifier)) | ||
475 | break; | ||
476 | handle->resp_object = GNUNET_JSONAPI_document_new (); | ||
477 | |||
478 | if (NULL == ego_entry) | ||
502 | { | 479 | { |
503 | if (0 != strcmp (ego_val, ego_entry->identifier)) | 480 | //Done |
504 | continue; | 481 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", |
505 | egoname = ego_entry->identifier; | 482 | identity); |
506 | break; | 483 | GNUNET_SCHEDULER_add_now (&return_response, handle); |
507 | } | ||
508 | if ( (NULL == egoname) || | ||
509 | (NULL == ego_entry) ) | ||
510 | { | ||
511 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
512 | "Ego not found: %s\n", | ||
513 | ego_val); | ||
514 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
515 | return; | 484 | return; |
516 | } | 485 | } |
517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 486 | priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); |
518 | "Ego to issue token for: %s\n", | 487 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); |
519 | egoname); | 488 | handle->ticket_it = GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (handle->idp, |
489 | priv_key, | ||
490 | &collect_error_cb, | ||
491 | handle, | ||
492 | &ticket_collect, | ||
493 | handle, | ||
494 | &collect_finished_cb, | ||
495 | handle); | ||
496 | } | ||
497 | |||
520 | 498 | ||
499 | static void | ||
500 | add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
501 | const char* url, | ||
502 | void *cls) | ||
503 | { | ||
504 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv; | ||
505 | const char* identity; | ||
506 | const char* name_str; | ||
507 | const char* value_str; | ||
521 | 508 | ||
522 | //Meta info | 509 | struct RequestHandle *handle = cls; |
523 | GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST, | 510 | struct EgoEntry *ego_entry; |
524 | strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST), | 511 | struct MHD_Response *resp; |
525 | &key); | 512 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attribute; |
513 | struct GNUNET_JSONAPI_Document *json_obj; | ||
514 | struct GNUNET_JSONAPI_Resource *json_res; | ||
515 | char term_data[handle->rest_handle->data_size+1]; | ||
516 | json_t *value_json; | ||
517 | json_t *data_json; | ||
518 | json_error_t err; | ||
519 | struct GNUNET_JSON_Specification docspec[] = { | ||
520 | GNUNET_JSON_spec_jsonapi_document (&json_obj), | ||
521 | GNUNET_JSON_spec_end() | ||
522 | }; | ||
526 | 523 | ||
527 | scopes = NULL; | 524 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n", |
528 | if ( GNUNET_YES != | 525 | handle->url); |
529 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | 526 | if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >= |
530 | &key) ) | 527 | strlen (handle->url)) |
531 | { | 528 | { |
532 | handle->emsg = GNUNET_strdup ("Scopes missing!\n"); | 529 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); |
533 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 530 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
534 | return; | 531 | return; |
535 | } | 532 | } |
536 | scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | 533 | identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1; |
537 | &key); | 534 | |
538 | 535 | for (ego_entry = handle->ego_head; | |
539 | 536 | NULL != ego_entry; | |
540 | //Token audience | 537 | ego_entry = ego_entry->next) |
541 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST, | 538 | if (0 == strcmp (identity, ego_entry->identifier)) |
542 | strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST), | 539 | break; |
543 | &key); | 540 | |
544 | audience = NULL; | 541 | if (NULL == ego_entry) |
545 | if ( GNUNET_YES != | ||
546 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | ||
547 | &key) ) | ||
548 | { | 542 | { |
549 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 543 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
550 | "Audience missing!\n"); | 544 | "Identity unknown (%s)\n", identity); |
551 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 545 | GNUNET_JSONAPI_document_delete (json_obj); |
552 | return; | 546 | return; |
553 | } | 547 | } |
554 | audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | 548 | identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); |
555 | &key); | ||
556 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
557 | "Audience to issue token for: %s\n", | ||
558 | audience); | ||
559 | 549 | ||
560 | priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | 550 | if (0 >= handle->rest_handle->data_size) |
561 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, | ||
562 | &pub_key); | ||
563 | GNUNET_STRINGS_string_to_data (audience, | ||
564 | strlen (audience), | ||
565 | &aud_key, | ||
566 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
567 | |||
568 | //Remote nonce | ||
569 | nonce_str = NULL; | ||
570 | GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE, | ||
571 | strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE), | ||
572 | &key); | ||
573 | if ( GNUNET_YES != | ||
574 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | ||
575 | &key) ) | ||
576 | { | 551 | { |
577 | handle->emsg = GNUNET_strdup ("Request nonce missing!\n"); | ||
578 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 552 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
579 | return; | 553 | return; |
580 | } | 554 | } |
581 | nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | 555 | |
582 | &key); | 556 | term_data[handle->rest_handle->data_size] = '\0'; |
583 | GNUNET_assert (NULL != nonce_str); | 557 | GNUNET_memcpy (term_data, |
584 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 558 | handle->rest_handle->data, |
585 | "Request nonce: %s\n", | 559 | handle->rest_handle->data_size); |
586 | nonce_str); | 560 | data_json = json_loads (term_data, |
587 | GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce)); | 561 | JSON_DECODE_ANY, |
588 | 562 | &err); | |
589 | //Get expiration for token from URL parameter | 563 | GNUNET_assert (GNUNET_OK == |
590 | GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING, | 564 | GNUNET_JSON_parse (data_json, docspec, |
591 | strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING), | 565 | NULL, NULL)); |
592 | &key); | 566 | json_decref (data_json); |
593 | 567 | if (NULL == json_obj) | |
594 | exp_str = NULL; | ||
595 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | ||
596 | &key)) | ||
597 | { | 568 | { |
598 | exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | 569 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
599 | &key); | 570 | "Unable to parse JSONAPI Object from %s\n", |
600 | } | 571 | term_data); |
601 | if (NULL == exp_str) { | ||
602 | handle->emsg = GNUNET_strdup ("No expiration given!\n"); | ||
603 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 572 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
604 | return; | 573 | return; |
605 | } | 574 | } |
606 | 575 | if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) | |
607 | if (GNUNET_OK != | ||
608 | GNUNET_STRINGS_fancy_time_to_relative (exp_str, | ||
609 | &etime_rel)) | ||
610 | { | 576 | { |
611 | handle->emsg = GNUNET_strdup ("Expiration invalid!\n"); | 577 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
578 | "Cannot create more than 1 resource! (Got %d)\n", | ||
579 | GNUNET_JSONAPI_document_resource_count (json_obj)); | ||
580 | GNUNET_JSONAPI_document_delete (json_obj); | ||
612 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 581 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
613 | return; | 582 | return; |
614 | } | 583 | } |
615 | time = GNUNET_TIME_absolute_get().abs_value_us; | 584 | json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); |
616 | exp_time.abs_value_us = time + etime_rel.rel_value_us; | 585 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, |
617 | 586 | GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE)) | |
587 | { | ||
588 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
589 | "Unsupported JSON data type\n"); | ||
590 | GNUNET_JSONAPI_document_delete (json_obj); | ||
591 | resp = GNUNET_REST_create_response (NULL); | ||
592 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
593 | cleanup_handle (handle); | ||
594 | return; | ||
595 | } | ||
596 | name_str = GNUNET_JSONAPI_resource_get_id (json_res); | ||
597 | value_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
598 | "value"); | ||
599 | value_str = json_string_value (value_json); | ||
600 | attribute = GNUNET_IDENTITY_ATTRIBUTE_claim_new (name_str, | ||
601 | GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, | ||
602 | value_str, | ||
603 | strlen (value_str) + 1); | ||
618 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | 604 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); |
619 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp, | 605 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (handle->idp, |
620 | priv_key, | 606 | identity_priv, |
621 | &aud_key, | 607 | attribute, |
622 | scopes, | 608 | &finished_cont, |
623 | exp_time, | 609 | handle); |
624 | nonce, | 610 | GNUNET_free (attribute); |
625 | &token_creat_cont, | 611 | GNUNET_JSONAPI_document_delete (json_obj); |
626 | handle); | ||
627 | |||
628 | } | ||
629 | |||
630 | |||
631 | /** | ||
632 | * Build a GNUid token for identity | ||
633 | * | ||
634 | * @param cls the request handle | ||
635 | */ | ||
636 | static void | ||
637 | return_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 | ||
652 | static void | ||
653 | token_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 | */ |
667 | static void | 620 | static void |
668 | token_collect (void *cls, | 621 | attr_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 | |||
675 | static void | ||
676 | token_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 | */ | ||
720 | static void | ||
721 | token_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 | */ |
772 | static void | 658 | static void |
773 | list_token_cont (struct GNUNET_REST_RequestHandle *con_handle, | 659 | list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle, |
774 | const char* url, | 660 | const char* url, |
775 | void *cls) | 661 | void *cls) |
776 | { | 662 | { |
777 | char* ego_val; | ||
778 | struct GNUNET_HashCode key; | ||
779 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | 663 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; |
780 | struct RequestHandle *handle = cls; | 664 | struct RequestHandle *handle = cls; |
781 | struct EgoEntry *ego_entry; | 665 | struct EgoEntry *ego_entry; |
782 | struct EgoEntry *ego_tmp; | 666 | char *identity; |
783 | |||
784 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST, | ||
785 | strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST), | ||
786 | &key); | ||
787 | 667 | ||
788 | if ( GNUNET_YES != | 668 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n", |
789 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | 669 | handle->url); |
790 | &key) ) | 670 | if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >= |
671 | strlen (handle->url)) | ||
791 | { | 672 | { |
792 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No issuer given.\n"); | 673 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); |
793 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 674 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
794 | return; | 675 | return; |
795 | } | 676 | } |
796 | ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | 677 | identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1; |
797 | &key); | 678 | |
798 | GNUNET_assert (NULL != ego_val); | ||
799 | //Remove non-matching egos | ||
800 | for (ego_entry = handle->ego_head; | 679 | for (ego_entry = handle->ego_head; |
801 | NULL != ego_entry;) | 680 | NULL != ego_entry; |
802 | { | 681 | ego_entry = ego_entry->next) |
803 | ego_tmp = ego_entry; | 682 | if (0 == strcmp (identity, ego_entry->identifier)) |
804 | ego_entry = ego_entry->next; | 683 | break; |
805 | if (0 != strcmp (ego_val, ego_tmp->identifier)) | ||
806 | { | ||
807 | GNUNET_CONTAINER_DLL_remove (handle->ego_head, | ||
808 | handle->ego_tail, | ||
809 | ego_tmp); | ||
810 | GNUNET_free (ego_tmp->identifier); | ||
811 | GNUNET_free (ego_tmp->keystring); | ||
812 | GNUNET_free (ego_tmp); | ||
813 | } | ||
814 | } | ||
815 | handle->resp_object = GNUNET_JSONAPI_document_new (); | 684 | handle->resp_object = GNUNET_JSONAPI_document_new (); |
816 | if (NULL == handle->ego_head) | 685 | |
686 | |||
687 | if (NULL == ego_entry) | ||
817 | { | 688 | { |
818 | //Done | 689 | //Done |
819 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n"); | 690 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", |
820 | GNUNET_SCHEDULER_add_now (&return_token_list, handle); | 691 | identity); |
692 | GNUNET_SCHEDULER_add_now (&return_response, handle); | ||
821 | return; | 693 | return; |
822 | } | 694 | } |
823 | priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); | 695 | priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); |
824 | handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); | 696 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); |
825 | handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, | 697 | handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (handle->idp, |
826 | priv_key, | 698 | priv_key, |
827 | &token_collect_error_cb, | 699 | &collect_error_cb, |
828 | handle, | 700 | handle, |
829 | &token_collect, | 701 | &attr_collect, |
830 | handle, | 702 | handle, |
831 | &token_collect_finished_cb, | 703 | &collect_finished_cb, |
832 | handle); | 704 | handle); |
833 | |||
834 | } | 705 | } |
835 | 706 | ||
836 | /** | 707 | |
837 | * Return token to requestor | ||
838 | * | ||
839 | * @param cls request handle | ||
840 | * @param token the token | ||
841 | */ | ||
842 | static void | 708 | static void |
843 | exchange_cont (void *cls, | 709 | revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle, |
844 | const struct GNUNET_IDENTITY_PROVIDER_Token *token, | 710 | const char* url, |
845 | uint64_t ticket_nonce) | 711 | void *cls) |
846 | { | 712 | { |
847 | json_t *root; | 713 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv; |
714 | const char* identity_str; | ||
715 | const char* audience_str; | ||
716 | const char* rnd_str; | ||
717 | |||
848 | struct RequestHandle *handle = cls; | 718 | struct RequestHandle *handle = cls; |
719 | struct EgoEntry *ego_entry; | ||
849 | struct MHD_Response *resp; | 720 | struct MHD_Response *resp; |
850 | struct GNUNET_HashCode key; | 721 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; |
851 | char* result; | 722 | struct GNUNET_JSONAPI_Document *json_obj; |
852 | char* token_str; | 723 | struct GNUNET_JSONAPI_Resource *json_res; |
853 | char* nonce_str; | 724 | struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk; |
854 | uint64_t expected_nonce; | 725 | char term_data[handle->rest_handle->data_size+1]; |
855 | 726 | json_t *rnd_json; | |
856 | //Get nonce | 727 | json_t *identity_json; |
857 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE, | 728 | json_t *audience_json; |
858 | strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE), | 729 | json_t *data_json; |
859 | &key); | 730 | json_error_t err; |
860 | 731 | struct GNUNET_JSON_Specification docspec[] = { | |
861 | if ( GNUNET_NO == | 732 | GNUNET_JSON_spec_jsonapi_document (&json_obj), |
862 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | 733 | GNUNET_JSON_spec_end() |
863 | &key) ) | 734 | }; |
735 | |||
736 | if (0 >= handle->rest_handle->data_size) | ||
864 | { | 737 | { |
865 | handle->emsg = GNUNET_strdup ("No nonce given."); | ||
866 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 738 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
867 | return; | 739 | return; |
868 | } | 740 | } |
869 | nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | ||
870 | &key); | ||
871 | GNUNET_assert (NULL != nonce_str); | ||
872 | GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce)); | ||
873 | 741 | ||
874 | if (ticket_nonce != expected_nonce) | 742 | term_data[handle->rest_handle->data_size] = '\0'; |
743 | GNUNET_memcpy (term_data, | ||
744 | handle->rest_handle->data, | ||
745 | handle->rest_handle->data_size); | ||
746 | data_json = json_loads (term_data, | ||
747 | JSON_DECODE_ANY, | ||
748 | &err); | ||
749 | GNUNET_assert (GNUNET_OK == | ||
750 | GNUNET_JSON_parse (data_json, docspec, | ||
751 | NULL, NULL)); | ||
752 | json_decref (data_json); | ||
753 | if (NULL == json_obj) | ||
875 | { | 754 | { |
876 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 755 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
877 | "Ticket nonce %"SCNu64" does not match expected nonce %"SCNu64"\n", | 756 | "Unable to parse JSONAPI Object from %s\n", |
878 | ticket_nonce, expected_nonce); | 757 | term_data); |
879 | handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n"); | ||
880 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 758 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
881 | return; | 759 | return; |
882 | } | 760 | } |
761 | if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) | ||
762 | { | ||
763 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
764 | "Cannot create more than 1 resource! (Got %d)\n", | ||
765 | GNUNET_JSONAPI_document_resource_count (json_obj)); | ||
766 | GNUNET_JSONAPI_document_delete (json_obj); | ||
767 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
768 | return; | ||
769 | } | ||
770 | json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); | ||
771 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, | ||
772 | GNUNET_REST_JSONAPI_IDENTITY_TICKET)) | ||
773 | { | ||
774 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
775 | "Unsupported JSON data type\n"); | ||
776 | GNUNET_JSONAPI_document_delete (json_obj); | ||
777 | resp = GNUNET_REST_create_response (NULL); | ||
778 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
779 | cleanup_handle (handle); | ||
780 | return; | ||
781 | } | ||
782 | rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
783 | "rnd"); | ||
784 | identity_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
785 | "identity"); | ||
786 | audience_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
787 | "audience"); | ||
788 | rnd_str = json_string_value (rnd_json); | ||
789 | identity_str = json_string_value (identity_json); | ||
790 | audience_str = json_string_value (audience_json); | ||
791 | |||
792 | GNUNET_STRINGS_string_to_data (rnd_str, | ||
793 | strlen (rnd_str), | ||
794 | &ticket.rnd, | ||
795 | sizeof (uint64_t)); | ||
796 | GNUNET_STRINGS_string_to_data (identity_str, | ||
797 | strlen (identity_str), | ||
798 | &ticket.identity, | ||
799 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
800 | GNUNET_STRINGS_string_to_data (audience_str, | ||
801 | strlen (audience_str), | ||
802 | &ticket.audience, | ||
803 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
883 | 804 | ||
884 | root = json_object (); | 805 | for (ego_entry = handle->ego_head; |
885 | token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token); | 806 | NULL != ego_entry; |
886 | json_object_set_new (root, "token", json_string (token_str)); | 807 | ego_entry = ego_entry->next) |
887 | json_object_set_new (root, "token_type", json_string ("jwt")); | 808 | { |
888 | GNUNET_free (token_str); | 809 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, |
810 | &tmp_pk); | ||
811 | if (0 == memcmp (&ticket.identity, | ||
812 | &tmp_pk, | ||
813 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
814 | break; | ||
815 | } | ||
816 | if (NULL == ego_entry) | ||
817 | { | ||
818 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
819 | "Identity unknown (%s)\n", identity_str); | ||
820 | GNUNET_JSONAPI_document_delete (json_obj); | ||
821 | return; | ||
822 | } | ||
823 | identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
889 | 824 | ||
890 | result = json_dumps (root, JSON_INDENT(1)); | 825 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); |
891 | resp = GNUNET_REST_create_response (result); | 826 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp, |
892 | GNUNET_free (result); | 827 | identity_priv, |
893 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | 828 | &ticket, |
894 | cleanup_handle (handle); | 829 | &finished_cont, |
895 | json_decref (root); | 830 | handle); |
831 | GNUNET_JSONAPI_document_delete (json_obj); | ||
896 | } | 832 | } |
897 | 833 | ||
898 | |||
899 | /** | ||
900 | * | ||
901 | * Callback called when identity for token exchange has been found | ||
902 | * | ||
903 | * @param cls request handle | ||
904 | * @param ego the identity to use as issuer | ||
905 | * @param ctx user context | ||
906 | * @param name identity name | ||
907 | * | ||
908 | */ | ||
909 | static void | 834 | static void |
910 | exchange_token_ticket_cb (void *cls, | 835 | consume_cont (void *cls, |
911 | struct GNUNET_IDENTITY_Ego *ego, | 836 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, |
912 | void **ctx, | 837 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) |
913 | const char *name) | ||
914 | { | 838 | { |
915 | struct RequestHandle *handle = cls; | 839 | struct RequestHandle *handle = cls; |
916 | struct GNUNET_HashCode key; | 840 | struct GNUNET_JSONAPI_Resource *json_resource; |
917 | struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; | 841 | json_t *value; |
918 | char* ticket_str; | 842 | |
843 | if (NULL == identity) | ||
844 | { | ||
845 | GNUNET_SCHEDULER_add_now (&return_response, handle); | ||
846 | return; | ||
847 | } | ||
919 | 848 | ||
920 | handle->op = NULL; | 849 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", |
850 | attr->name); | ||
851 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE, | ||
852 | attr->name); | ||
853 | GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); | ||
921 | 854 | ||
922 | if (NULL == ego) | 855 | value = json_string (attr->data); |
856 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
857 | "value", | ||
858 | value); | ||
859 | json_decref (value); | ||
860 | } | ||
861 | |||
862 | static void | ||
863 | consume_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 | */ | ||
967 | static void | ||
968 | exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
969 | const char* url, | ||
970 | void *cls) | ||
971 | { | ||
972 | struct RequestHandle *handle = cls; | ||
973 | |||
974 | //Get token from GNS | ||
975 | handle->op = GNUNET_IDENTITY_get (handle->identity_handle, | ||
976 | "gns-master", | ||
977 | &exchange_token_ticket_cb, | ||
978 | handle); | ||
979 | } | ||
980 | |||
981 | /** | ||
982 | * Respond to OPTIONS request | 991 | * Respond to OPTIONS request |
983 | * | 992 | * |
984 | * @param con_handle the connection handle | 993 | * @param con_handle the connection handle |
@@ -1013,15 +1022,17 @@ init_cont (struct RequestHandle *handle) | |||
1013 | { | 1022 | { |
1014 | struct GNUNET_REST_RequestHandlerError err; | 1023 | struct GNUNET_REST_RequestHandlerError err; |
1015 | static const struct GNUNET_REST_RequestHandler handlers[] = { | 1024 | static const struct GNUNET_REST_RequestHandler handlers[] = { |
1016 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont}, | 1025 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont}, |
1017 | //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont}, | 1026 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont}, |
1018 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont}, | 1027 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont}, |
1019 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &options_cont}, | 1028 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont}, |
1020 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont}, | 1029 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont}, |
1030 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, | ||
1031 | &options_cont}, | ||
1021 | GNUNET_REST_HANDLER_END | 1032 | GNUNET_REST_HANDLER_END |
1022 | }; | 1033 | }; |
1023 | 1034 | ||
1024 | if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, | 1035 | if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, |
1025 | handlers, | 1036 | handlers, |
1026 | &err, | 1037 | &err, |
1027 | handle)) | 1038 | handle)) |
@@ -1104,7 +1115,7 @@ list_ego (void *cls, | |||
1104 | * @return GNUNET_OK if request accepted | 1115 | * @return GNUNET_OK if request accepted |
1105 | */ | 1116 | */ |
1106 | static void | 1117 | static void |
1107 | rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, | 1118 | rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, |
1108 | GNUNET_REST_ResultProcessor proc, | 1119 | GNUNET_REST_ResultProcessor proc, |
1109 | void *proc_cls) | 1120 | void *proc_cls) |
1110 | { | 1121 | { |
@@ -1114,10 +1125,9 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, | |||
1114 | handle->proc_cls = proc_cls; | 1125 | handle->proc_cls = proc_cls; |
1115 | handle->proc = proc; | 1126 | handle->proc = proc; |
1116 | handle->state = ID_REST_STATE_INIT; | 1127 | handle->state = ID_REST_STATE_INIT; |
1117 | handle->conndata_handle = conndata_handle; | 1128 | handle->rest_handle = rest_handle; |
1118 | 1129 | ||
1119 | 1130 | handle->url = GNUNET_strdup (rest_handle->url); | |
1120 | handle->url = GNUNET_strdup (conndata_handle->url); | ||
1121 | if (handle->url[strlen (handle->url)-1] == '/') | 1131 | if (handle->url[strlen (handle->url)-1] == '/') |
1122 | handle->url[strlen (handle->url)-1] = '\0'; | 1132 | handle->url[strlen (handle->url)-1] = '\0'; |
1123 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1133 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1162,8 +1172,8 @@ libgnunet_plugin_rest_identity_provider_init (void *cls) | |||
1162 | MHD_HTTP_METHOD_DELETE, | 1172 | MHD_HTTP_METHOD_DELETE, |
1163 | MHD_HTTP_METHOD_OPTIONS); | 1173 | MHD_HTTP_METHOD_OPTIONS); |
1164 | 1174 | ||
1165 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1175 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1166 | _("Identity Token REST API initialized\n")); | 1176 | _("Identity Provider REST API initialized\n")); |
1167 | return api; | 1177 | return api; |
1168 | } | 1178 | } |
1169 | 1179 | ||
@@ -1184,8 +1194,8 @@ libgnunet_plugin_rest_identity_provider_done (void *cls) | |||
1184 | GNUNET_free_non_null (allow_methods); | 1194 | GNUNET_free_non_null (allow_methods); |
1185 | GNUNET_free (api); | 1195 | GNUNET_free (api); |
1186 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1196 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1187 | "Identity Token REST plugin is finished\n"); | 1197 | "Identity Provider REST plugin is finished\n"); |
1188 | return NULL; | 1198 | return NULL; |
1189 | } | 1199 | } |
1190 | 1200 | ||
1191 | /* end of plugin_rest_gns.c */ | 1201 | /* end of plugin_rest_identity_provider.c */ |
diff --git a/src/identity-provider/test_idp.conf b/src/identity-provider/test_idp.conf new file mode 100644 index 000000000..2b76c7bf2 --- /dev/null +++ b/src/identity-provider/test_idp.conf | |||
@@ -0,0 +1,28 @@ | |||
1 | @INLINE@ test_idp_defaults.conf | ||
2 | |||
3 | [PATHS] | ||
4 | GNUNET_TEST_HOME = /tmp/test-gnunet-idp-peer-1/ | ||
5 | |||
6 | [dht] | ||
7 | AUTOSTART = YES | ||
8 | |||
9 | [rest] | ||
10 | AUTOSTART = YES | ||
11 | #PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog | ||
12 | |||
13 | [transport] | ||
14 | PLUGINS = | ||
15 | |||
16 | [identity-provider] | ||
17 | AUTOSTART = 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 | ||
22 | AUTOSTART = YES | ||
23 | AUTO_IMPORT_PKEY = YES | ||
24 | MAX_PARALLEL_BACKGROUND_QUERIES = 10 | ||
25 | DEFAULT_LOOKUP_TIMEOUT = 15 s | ||
26 | RECORD_PUT_INTERVAL = 1 h | ||
27 | ZONE_PUBLISH_TIME_WINDOW = 1 h | ||
28 | DNS_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 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | gnunet-identity -C testego -c test_idp.conf | ||
28 | valgrind gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf | ||
29 | gnunet-idp -e testego -a name -V John -c test_idp.conf | ||
30 | gnunet-idp -e testego -D -c test_idp.conf | ||
31 | gnunet-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 | ||
2 | trap "gnunet-arm -e -c test_idp.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | #gnunet-arm -i rest -c test_idp.conf | ||
28 | gnunet-identity -C testego -c test_idp.conf | ||
29 | gnunet-identity -C rpego -c test_idp.conf | ||
30 | TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}') | ||
31 | gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf | ||
32 | gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1 | ||
33 | if test $? != 0 | ||
34 | then | ||
35 | echo "Failed." | ||
36 | exit 1 | ||
37 | fi | ||
38 | |||
39 | #curl localhost:7776/idp/attributes/testego | ||
40 | gnunet-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 | ||
2 | trap "gnunet-arm -e -c test_idp.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | #gnunet-arm -i rest -c test_idp.conf | ||
28 | gnunet-identity -C testego -c test_idp.conf | ||
29 | gnunet-identity -C rpego -c test_idp.conf | ||
30 | SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}') | ||
31 | TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}') | ||
32 | gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf | ||
33 | gnunet-idp -e testego -a name -V John -c test_idp.conf | ||
34 | TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf | awk '{print $1}') | ||
35 | gnunet-idp -e rpego -C $TICKET -c test_idp.conf > /dev/null 2>&1 | ||
36 | |||
37 | if test $? != 0 | ||
38 | then | ||
39 | "Failed." | ||
40 | exit 1 | ||
41 | fi | ||
42 | #curl http://localhost:7776/idp/tickets/testego | ||
43 | gnunet-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] | ||
4 | GNUNET_TEST_HOME = /tmp/test-gnunet-idp-testing/ | ||
5 | |||
6 | [namestore-sqlite] | ||
7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | ||
8 | |||
9 | [namecache-sqlite] | ||
10 | FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db | ||
11 | |||
12 | [identity] | ||
13 | # Directory where we store information about our egos | ||
14 | EGODIR = $GNUNET_TEST_HOME/identity/egos/ | ||
15 | |||
16 | [dhtcache] | ||
17 | DATABASE = heap | ||
18 | |||
19 | [transport] | ||
20 | PLUGINS = tcp | ||
21 | |||
22 | [transport-tcp] | ||
23 | BINDTO = 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 | ||
2 | trap "gnunet-arm -e -c test_idp.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | #gnunet-arm -i rest -c test_idp.conf | ||
28 | gnunet-identity -C testego -c test_idp.conf | ||
29 | gnunet-identity -C rpego -c test_idp.conf | ||
30 | SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}') | ||
31 | TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}') | ||
32 | gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf > /dev/null 2>&1 | ||
33 | gnunet-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 | ||
35 | gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf > /dev/null 2>&1 | ||
36 | if test $? != 0 | ||
37 | then | ||
38 | echo "Failed." | ||
39 | exit 1 | ||
40 | fi | ||
41 | #curl http://localhost:7776/idp/attributes/testego | ||
42 | gnunet-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 | ||
2 | trap "gnunet-arm -e -c test_idp.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -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 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | gnunet-identity -C alice -c test_idp.conf | ||
28 | gnunet-identity -C bob -c test_idp.conf | ||
29 | gnunet-identity -C eve -c test_idp.conf | ||
30 | ALICE_KEY=$(gnunet-identity -d -c test_idp.conf | grep alice | awk '{print $3}') | ||
31 | BOB_KEY=$(gnunet-identity -d -c test_idp.conf | grep bob | awk '{print $3}') | ||
32 | EVE_KEY=$(gnunet-identity -d -c test_idp.conf | grep eve | awk '{print $3}') | ||
33 | |||
34 | gnunet-idp -e alice -a email -V john@doe.gnu -c test_idp.conf | ||
35 | gnunet-idp -e alice -a name -V John -c test_idp.conf | ||
36 | TICKET_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 | ||
38 | TICKET_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 | ||
43 | gnunet-idp -e alice -R $TICKET_EVE -c test_idp.conf | ||
44 | |||
45 | gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf > /dev/null 2>&1 | ||
46 | if test $? == 0 | ||
47 | then | ||
48 | echo "Eve can still resolve attributes..." | ||
49 | gnunet-arm -e -c test_idp.conf | ||
50 | exit 1 | ||
51 | fi | ||
52 | gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf > /dev/null 2>&1 | ||
53 | if test $? != 0 | ||
54 | then | ||
55 | echo "Bob cannot resolve attributes..." | ||
56 | gnunet-arm -e -c test_idp.conf | ||
57 | exit 1 | ||
58 | fi | ||
59 | |||
60 | gnunet-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 = \ | |||
42 | if HAVE_MHD | 42 | if HAVE_MHD |
43 | if HAVE_JSON | 43 | if HAVE_JSON |
44 | plugin_LTLIBRARIES = \ | 44 | plugin_LTLIBRARIES = \ |
45 | libgnunet_plugin_rest_identity.la \ | 45 | libgnunet_plugin_rest_identity.la |
46 | libgnunet_plugin_gnsrecord_identity.la | ||
47 | endif | 46 | endif |
48 | endif | 47 | endif |
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 | ||
58 | libgnunet_plugin_gnsrecord_identity_la_SOURCES = \ | ||
59 | plugin_gnsrecord_identity.c | ||
60 | libgnunet_plugin_gnsrecord_identity_la_LIBADD = \ | ||
61 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
62 | $(LTLIBINTL) | ||
63 | libgnunet_plugin_gnsrecord_identity_la_LDFLAGS = \ | ||
64 | $(GN_PLUGIN_LDFLAGS) | ||
65 | |||
66 | 57 | ||
67 | libgnunet_plugin_rest_identity_la_SOURCES = \ | 58 | libgnunet_plugin_rest_identity_la_SOURCES = \ |
68 | plugin_rest_identity.c | 59 | plugin_rest_identity.c |
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index e64b2685a..5f34d0f1b 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c | |||
@@ -427,9 +427,6 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, | |||
427 | continue; | 427 | continue; |
428 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, | 428 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, |
429 | ego_entry->keystring); | 429 | ego_entry->keystring); |
430 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
431 | "Egoname: %s\n", | ||
432 | ego_entry->identifier); | ||
433 | name_str = json_string (ego_entry->identifier); | 430 | name_str = json_string (ego_entry->identifier); |
434 | GNUNET_JSONAPI_resource_add_attr ( | 431 | GNUNET_JSONAPI_resource_add_attr ( |
435 | json_resource, | 432 | json_resource, |
diff --git a/src/include/gnunet_credential_service.h b/src/include/gnunet_credential_service.h index 9e765c12b..67c2f2b4c 100644 --- a/src/include/gnunet_credential_service.h +++ b/src/include/gnunet_credential_service.h | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @author Martin Schanzenbach | 22 | * @author Martin Schanzenbach |
23 | * @author Adnan Husain | ||
23 | * | 24 | * |
24 | * @file | 25 | * @file |
25 | * API to the Credential service | 26 | * API to the Credential service |
@@ -34,6 +35,7 @@ | |||
34 | 35 | ||
35 | #include "gnunet_util_lib.h" | 36 | #include "gnunet_util_lib.h" |
36 | #include "gnunet_gns_service.h" | 37 | #include "gnunet_gns_service.h" |
38 | #include "gnunet_identity_service.h" | ||
37 | 39 | ||
38 | #ifdef __cplusplus | 40 | #ifdef __cplusplus |
39 | extern "C" | 41 | extern "C" |
@@ -52,7 +54,157 @@ struct GNUNET_CREDENTIAL_Handle; | |||
52 | /** | 54 | /** |
53 | * Handle to control a lookup operation. | 55 | * Handle to control a lookup operation. |
54 | */ | 56 | */ |
55 | struct GNUNET_CREDENTIAL_LookupRequest; | 57 | struct GNUNET_CREDENTIAL_Request; |
58 | |||
59 | /* | ||
60 | * Enum used for checking whether the issuer has the authority to issue credentials or is just a subject | ||
61 | */ | ||
62 | enum GNUNET_CREDENTIAL_CredentialFlags { | ||
63 | |||
64 | //Subject had credentials before, but have been revoked now | ||
65 | GNUNET_CREDENTIAL_FLAG_REVOKED=0, | ||
66 | |||
67 | //Subject flag indicates that the subject is a holder of this credential and may present it as such | ||
68 | GNUNET_CREDENTIAL_FLAG_SUBJECT=1, | ||
69 | |||
70 | //Issuer flag is used to signify that the subject is allowed to issue this credential and delegate issuance | ||
71 | GNUNET_CREDENTIAL_FLAG_ISSUER=2 | ||
72 | |||
73 | }; | ||
74 | |||
75 | GNUNET_NETWORK_STRUCT_BEGIN | ||
76 | /** | ||
77 | * The attribute delegation record | ||
78 | */ | ||
79 | struct GNUNET_CREDENTIAL_DelegationRecord { | ||
80 | |||
81 | /** | ||
82 | * Number of delegation sets in this record | ||
83 | */ | ||
84 | uint32_t set_count; | ||
85 | |||
86 | /** | ||
87 | * Length of delegation sets | ||
88 | */ | ||
89 | uint64_t data_size; | ||
90 | /** | ||
91 | * Followed by set_count DelegationSetRecords | ||
92 | * | ||
93 | */ | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * The attribute delegation record | ||
98 | */ | ||
99 | struct GNUNET_CREDENTIAL_DelegationRecordSet { | ||
100 | |||
101 | /** | ||
102 | * Public key of the subject this attribute was delegated to | ||
103 | */ | ||
104 | struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; | ||
105 | |||
106 | /** | ||
107 | * Length of attribute, may be 0 | ||
108 | */ | ||
109 | uint32_t subject_attribute_len; | ||
110 | }; | ||
111 | |||
112 | |||
113 | GNUNET_NETWORK_STRUCT_END | ||
114 | |||
115 | /** | ||
116 | * The attribute delegation record | ||
117 | */ | ||
118 | struct GNUNET_CREDENTIAL_DelegationSet { | ||
119 | |||
120 | /** | ||
121 | * Public key of the subject this attribute was delegated to | ||
122 | */ | ||
123 | struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; | ||
124 | |||
125 | uint32_t subject_attribute_len; | ||
126 | |||
127 | /** | ||
128 | * The subject attribute | ||
129 | */ | ||
130 | const char *subject_attribute; | ||
131 | }; | ||
132 | |||
133 | |||
134 | /** | ||
135 | * A delegation | ||
136 | */ | ||
137 | struct GNUNET_CREDENTIAL_Delegation { | ||
138 | |||
139 | /** | ||
140 | * The issuer of the delegation | ||
141 | */ | ||
142 | struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; | ||
143 | |||
144 | /** | ||
145 | * Public key of the subject this attribute was delegated to | ||
146 | */ | ||
147 | struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; | ||
148 | |||
149 | /** | ||
150 | * Length of the attribute | ||
151 | */ | ||
152 | uint32_t issuer_attribute_len; | ||
153 | |||
154 | /** | ||
155 | * The attribute | ||
156 | */ | ||
157 | const char *issuer_attribute; | ||
158 | |||
159 | /** | ||
160 | * Length of the attribute | ||
161 | */ | ||
162 | uint32_t subject_attribute_len; | ||
163 | |||
164 | /** | ||
165 | * The attribute | ||
166 | */ | ||
167 | const char *subject_attribute; | ||
168 | }; | ||
169 | |||
170 | |||
171 | /** | ||
172 | * A credential | ||
173 | */ | ||
174 | struct GNUNET_CREDENTIAL_Credential { | ||
175 | |||
176 | /** | ||
177 | * The issuer of the credential | ||
178 | */ | ||
179 | struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; | ||
180 | |||
181 | /** | ||
182 | * Public key of the subject this credential was issued to | ||
183 | */ | ||
184 | struct GNUNET_CRYPTO_EcdsaPublicKey subject_key; | ||
185 | |||
186 | /** | ||
187 | * Signature of this credential | ||
188 | */ | ||
189 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
190 | |||
191 | /** | ||
192 | * Expiration of this credential | ||
193 | */ | ||
194 | struct GNUNET_TIME_Absolute expiration; | ||
195 | |||
196 | /** | ||
197 | * Length of the attribute | ||
198 | */ | ||
199 | uint32_t issuer_attribute_len; | ||
200 | |||
201 | /** | ||
202 | * The attribute | ||
203 | */ | ||
204 | const char *issuer_attribute; | ||
205 | |||
206 | }; | ||
207 | |||
56 | 208 | ||
57 | 209 | ||
58 | /** | 210 | /** |
@@ -61,7 +213,7 @@ struct GNUNET_CREDENTIAL_LookupRequest; | |||
61 | * @param cfg configuration to use | 213 | * @param cfg configuration to use |
62 | * @return handle to the Credential service, or NULL on error | 214 | * @return handle to the Credential service, or NULL on error |
63 | */ | 215 | */ |
64 | struct GNUNET_Credential_Handle * | 216 | struct GNUNET_CREDENTIAL_Handle * |
65 | GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); | 217 | GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); |
66 | 218 | ||
67 | 219 | ||
@@ -75,56 +227,129 @@ GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle); | |||
75 | 227 | ||
76 | 228 | ||
77 | /** | 229 | /** |
78 | * Iterator called on obtained result for a Credential lookup. | 230 | * Iterator called on obtained result for an attribute verification. |
79 | * | 231 | * |
80 | * @param cls closure | 232 | * @param cls closure |
81 | * @param issuer the issuer chain | 233 | * @param d_count the number of delegations processed |
82 | * @param issuer_len length of issuer chain | 234 | * @param delegation_chain the delegations processed |
83 | * @param value the value returned | 235 | * @param c_count the number of credentials found |
236 | * @param credential the credentials | ||
84 | */ | 237 | */ |
85 | typedef void | 238 | typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls, |
86 | (*GNUNET_CREDENTIAL_LookupResultProcessor) (void *cls, | 239 | unsigned int d_count, |
87 | struct GNUNET_IDENTITY_Ego *issuer, | 240 | struct GNUNET_CREDENTIAL_Delegation *delegation_chain, |
88 | uint16_t issuer_len, | 241 | unsigned int c_count, |
89 | const struct GNUNET_CREDENTIAL_Value *value); | 242 | struct GNUNET_CREDENTIAL_Credential *credential); |
90 | 243 | ||
244 | /** | ||
245 | * Iterator called on obtained result for an attribute delegation. | ||
246 | * | ||
247 | * @param cls closure | ||
248 | * @param success GNUNET_YES if successful | ||
249 | * @param result the record data that can be handed to the subject | ||
250 | */ | ||
251 | typedef void (*GNUNET_CREDENTIAL_DelegateResultProcessor) (void *cls, | ||
252 | uint32_t success); | ||
91 | 253 | ||
92 | /** | 254 | /** |
93 | * Perform an asynchronous lookup operation for a credential. | 255 | * Iterator called on obtained result for an attribute delegation removal. |
256 | * | ||
257 | * @param cls closure | ||
258 | * @param success GNUNET_YES if successful | ||
259 | * @param result the record data that can be handed to the subject | ||
260 | */ | ||
261 | typedef void (*GNUNET_CREDENTIAL_RemoveDelegateResultProcessor) (void *cls, | ||
262 | uint32_t success); | ||
263 | |||
264 | |||
265 | /** | ||
266 | * Performs attribute verification. | ||
267 | * Checks if there is a delegation chain from | ||
268 | * attribute ``issuer_attribute'' issued by the issuer | ||
269 | * with public key ``issuer_key'' maps to the attribute | ||
270 | * ``subject_attribute'' claimed by the subject with key | ||
271 | * ``subject_key'' | ||
94 | * | 272 | * |
95 | * @param handle handle to the Credential service | 273 | * @param handle handle to the Credential service |
96 | * @param credential the credential to look up | 274 | * @param issuer_key the issuer public key |
97 | * @param subject Ego to check the credential for | 275 | * @param issuer_attribute the issuer attribute |
276 | * @param subject_key the subject public key | ||
277 | * @param subject_attribute the attribute claimed by the subject | ||
98 | * @param proc function to call on result | 278 | * @param proc function to call on result |
99 | * @param proc_cls closure for processor | 279 | * @param proc_cls closure for processor |
100 | * @return handle to the queued request | 280 | * @return handle to the queued request |
101 | */ | 281 | */ |
102 | struct GNUNET_CREDENTIAL_LookupRequest * | 282 | struct GNUNET_CREDENTIAL_Request* |
103 | GNUNET_CREDENTIAL_lookup (struct GNUNET_CREDENTIAL_Handle *handle, | 283 | GNUNET_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 | ||
292 | struct GNUNET_CREDENTIAL_Request* | ||
293 | GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle, | ||
294 | const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key, | ||
295 | const char *issuer_attribute, | ||
296 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key, | ||
297 | GNUNET_CREDENTIAL_CredentialResultProcessor proc, | ||
298 | void *proc_cls); | ||
109 | 299 | ||
110 | /** | 300 | /** |
111 | * Issue a credential to an identity | 301 | * Delegate an attribute |
112 | * | 302 | * |
113 | * @param handle handle to the Credential service | 303 | * @param handle handle to the Credential service |
114 | * @param issuer the identity that issues the credential | 304 | * @param issuer the ego that should be used to delegate the attribute |
115 | * @param subject the subject of the credential | 305 | * @param attribute the name of the attribute to delegate |
116 | * @param credential the name of the credential | 306 | * @param subject the subject of the delegation |
117 | * @param value the value of the credential | 307 | * @param delegated_attribute the name of the attribute that is delegated to |
308 | * @return handle to the queued request | ||
309 | */ | ||
310 | struct GNUNET_CREDENTIAL_Request * | ||
311 | GNUNET_CREDENTIAL_add_delegation (struct GNUNET_CREDENTIAL_Handle *handle, | ||
312 | struct GNUNET_IDENTITY_Ego *issuer, | ||
313 | const char *attribute, | ||
314 | struct GNUNET_CRYPTO_EcdsaPublicKey *subject, | ||
315 | const char *delegated_attribute, | ||
316 | GNUNET_CREDENTIAL_DelegateResultProcessor proc, | ||
317 | void *proc_cls); | ||
318 | |||
319 | /** | ||
320 | * Remove a delegation | ||
321 | * | ||
322 | * @param handle handle to the Credential service | ||
323 | * @param issuer the ego that was used to delegate the attribute | ||
324 | * @param attribute the name of the attribute that is delegated | ||
118 | * @return handle to the queued request | 325 | * @return handle to the queued request |
119 | */ | 326 | */ |
120 | struct GNUNET_CREDENTIAL_IssueRequest * | 327 | struct GNUNET_CREDENTIAL_Request * |
121 | GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle, | 328 | GNUNET_CREDENTIAL_remove_delegation (struct GNUNET_CREDENTIAL_Handle *handle, |
122 | struct GNUNET_IDENTITY_Ego *issuer, | 329 | struct GNUNET_IDENTITY_Ego *issuer, |
123 | struct GNUNET_IDENTITY_Ego *subject, | 330 | const char *attribute, |
124 | const char *credential, | 331 | GNUNET_CREDENTIAL_RemoveDelegateResultProcessor proc, |
125 | struct GNUNET_CREDENTIAL_Value *value, | 332 | void *proc_cls); |
126 | GNUNET_CREDENTIAL_IssueResultProcessor proc, | 333 | |
127 | void *proc_cls); | 334 | |
335 | |||
336 | /** | ||
337 | * Issue an attribute to a subject | ||
338 | * | ||
339 | * @param handle handle to the Credential service | ||
340 | * @param issuer the ego that should be used to issue the attribute | ||
341 | * @param subject the subject of the attribute | ||
342 | * @param attribute the name of the attribute | ||
343 | * @param expiration the TTL of the credential | ||
344 | * @return handle to the queued request | ||
345 | */ | ||
346 | struct GNUNET_CREDENTIAL_Credential* | ||
347 | GNUNET_CREDENTIAL_credential_issue ( | ||
348 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | ||
349 | struct GNUNET_CRYPTO_EcdsaPublicKey *subject, | ||
350 | const char *attribute, | ||
351 | struct GNUNET_TIME_Absolute *expiration); | ||
352 | |||
128 | 353 | ||
129 | /** | 354 | /** |
130 | * Remove a credential | 355 | * Remove a credential |
@@ -135,14 +360,15 @@ GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle, | |||
135 | * @param credential the name of the credential | 360 | * @param credential the name of the credential |
136 | * @return handle to the queued request | 361 | * @return handle to the queued request |
137 | */ | 362 | */ |
138 | struct GNUNET_CREDENTIAL_IssueRequest * | 363 | /** |
139 | GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle, | 364 | struct GNUNET_CREDENTIAL_IssueRequest * |
140 | struct GNUNET_IDENTITY_Ego *issuer, | 365 | GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle, |
141 | struct GNUNET_IDENTITY_Ego *subject, | 366 | struct GNUNET_IDENTITY_Ego *issuer, |
142 | const char *credential, | 367 | struct GNUNET_IDENTITY_Ego *subject, |
143 | GNUNET_CREDENTIAL_IssueResultProcessor proc, | 368 | const char *credential, |
144 | void *proc_cls); | 369 | GNUNET_CREDENTIAL_IssueResultProcessor proc, |
145 | 370 | void *proc_cls); | |
371 | */ | ||
146 | 372 | ||
147 | 373 | ||
148 | /** | 374 | /** |
@@ -151,7 +377,7 @@ GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle, | |||
151 | * @param lr the lookup request to cancel | 377 | * @param lr the lookup request to cancel |
152 | */ | 378 | */ |
153 | void | 379 | void |
154 | GNUNET_CREDENTIAL_lookup_cancel (struct GNUNET_CREDENTIAL_LookupRequest *lr); | 380 | GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *vr); |
155 | 381 | ||
156 | 382 | ||
157 | #if 0 /* keep Emacsens' auto-indent happy */ | 383 | #if 0 /* keep Emacsens' auto-indent happy */ |
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index e886a561c..2fd67ae1b 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h | |||
@@ -395,6 +395,11 @@ struct GNUNET_CRYPTO_PaillierCiphertext | |||
395 | unsigned char bits[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8]; | 395 | unsigned char bits[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8]; |
396 | }; | 396 | }; |
397 | 397 | ||
398 | /** | ||
399 | * @brief type for ABE master keys | ||
400 | */ | ||
401 | struct GNUNET_CRYPTO_AbeMasterKey; | ||
402 | |||
398 | 403 | ||
399 | /* **************** Functions and Macros ************* */ | 404 | /* **************** Functions and Macros ************* */ |
400 | 405 | ||
@@ -2137,6 +2142,83 @@ GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash, | |||
2137 | const struct GNUNET_CRYPTO_RsaPublicKey *public_key); | 2142 | const struct GNUNET_CRYPTO_RsaPublicKey *public_key); |
2138 | 2143 | ||
2139 | 2144 | ||
2145 | /** | ||
2146 | * @ingroup crypto | ||
2147 | * Create a new CP-ABE master key. Caller must free return value. | ||
2148 | * | ||
2149 | * @return fresh private key; free using #GNUNET_free | ||
2150 | */ | ||
2151 | struct GNUNET_CRYPTO_AbeMasterKey * | ||
2152 | GNUNET_CRYPTO_cpabe_create_master_key (void); | ||
2153 | void | ||
2154 | GNUNET_CRYPTO_cpabe_delete_master_key (struct GNUNET_CRYPTO_AbeMasterKey *key); | ||
2155 | |||
2156 | /** | ||
2157 | * @ingroup crypto | ||
2158 | * Create a new CP-ABE key. Caller must free return value. | ||
2159 | * | ||
2160 | * @return fresh private key; free using #GNUNET_free | ||
2161 | */ | ||
2162 | struct GNUNET_CRYPTO_AbeKey * | ||
2163 | GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *msk, | ||
2164 | char **attrs); | ||
2165 | void | ||
2166 | GNUNET_CRYPTO_cpabe_delete_key (struct GNUNET_CRYPTO_AbeKey *key, | ||
2167 | int delete_pub); | ||
2168 | |||
2169 | |||
2170 | /** | ||
2171 | * @ingroup crypto | ||
2172 | * Encrypt a block using sessionkey. | ||
2173 | * | ||
2174 | * @param block the block to encrypt | ||
2175 | * @param size the size of the @a block | ||
2176 | * @param sessionkey the key used to encrypt | ||
2177 | * @param iv the initialization vector to use, use INITVALUE | ||
2178 | * for streams. | ||
2179 | * @return the size of the encrypted block, -1 for errors | ||
2180 | */ | ||
2181 | ssize_t | ||
2182 | GNUNET_CRYPTO_cpabe_encrypt (const void *block, | ||
2183 | size_t size, | ||
2184 | const char *policy, | ||
2185 | const struct GNUNET_CRYPTO_AbeMasterKey *key, | ||
2186 | void **result); | ||
2187 | |||
2188 | /** | ||
2189 | * @ingroup crypto | ||
2190 | * Encrypt a block using sessionkey. | ||
2191 | * | ||
2192 | * @param block the block to encrypt | ||
2193 | * @param size the size of the @a block | ||
2194 | * @param sessionkey the key used to encrypt | ||
2195 | * @param iv the initialization vector to use, use INITVALUE | ||
2196 | * for streams. | ||
2197 | * @return the size of the encrypted block, -1 for errors | ||
2198 | */ | ||
2199 | ssize_t | ||
2200 | GNUNET_CRYPTO_cpabe_decrypt (const void *block, | ||
2201 | size_t size, | ||
2202 | const struct GNUNET_CRYPTO_AbeKey *key, | ||
2203 | void **result); | ||
2204 | |||
2205 | ssize_t | ||
2206 | GNUNET_CRYPTO_cpabe_serialize_key (const struct GNUNET_CRYPTO_AbeKey *key, | ||
2207 | void **result); | ||
2208 | |||
2209 | struct GNUNET_CRYPTO_AbeKey* | ||
2210 | GNUNET_CRYPTO_cpabe_deserialize_key (const void *data, | ||
2211 | size_t len); | ||
2212 | |||
2213 | ssize_t | ||
2214 | GNUNET_CRYPTO_cpabe_serialize_master_key (const struct GNUNET_CRYPTO_AbeMasterKey *key, | ||
2215 | void **result); | ||
2216 | |||
2217 | struct GNUNET_CRYPTO_AbeMasterKey* | ||
2218 | GNUNET_CRYPTO_cpabe_deserialize_master_key (const void *data, | ||
2219 | size_t len); | ||
2220 | |||
2221 | |||
2140 | #if 0 /* keep Emacsens' auto-indent happy */ | 2222 | #if 0 /* keep Emacsens' auto-indent happy */ |
2141 | { | 2223 | { |
2142 | #endif | 2224 | #endif |
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index 985ae1f7a..d03b4db3b 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h | |||
@@ -109,9 +109,29 @@ extern "C" | |||
109 | #define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546 | 109 | #define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546 |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * Record type for credential | ||
113 | */ | ||
114 | #define GNUNET_GNSRECORD_TYPE_CREDENTIAL 65547 | ||
115 | |||
116 | /** | ||
117 | * Record type for policies | ||
118 | */ | ||
119 | #define GNUNET_GNSRECORD_TYPE_POLICY 65548 | ||
120 | |||
121 | /** | ||
112 | * Record type for reverse lookups | 122 | * Record type for reverse lookups |
113 | */ | 123 | */ |
114 | #define GNUNET_GNSRECORD_TYPE_REVERSE 65548 | 124 | #define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549 |
125 | |||
126 | /** | ||
127 | * Record type for ABE records | ||
128 | */ | ||
129 | #define GNUNET_GNSRECORD_TYPE_ABE_KEY 65550 | ||
130 | |||
131 | /** | ||
132 | * Record type for ABE master keys | ||
133 | */ | ||
134 | #define GNUNET_GNSRECORD_TYPE_ABE_MASTER 65551 | ||
115 | 135 | ||
116 | /** | 136 | /** |
117 | * Flags that can be set for a record. | 137 | * Flags that can be set for a record. |
diff --git a/src/include/gnunet_identity_attribute_lib.h b/src/include/gnunet_identity_attribute_lib.h new file mode 100644 index 000000000..a6c9e1f1c --- /dev/null +++ b/src/include/gnunet_identity_attribute_lib.h | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author Martin Schanzenbach | ||
23 | * | ||
24 | * @file | ||
25 | * Identity attribute definitions | ||
26 | * | ||
27 | * @defgroup identity-provider Identity Provider service | ||
28 | * @{ | ||
29 | */ | ||
30 | #ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H | ||
31 | #define GNUNET_IDENTITY_ATTRIBUTE_LIB_H | ||
32 | |||
33 | #ifdef __cplusplus | ||
34 | extern "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 | */ | ||
59 | struct 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 | |||
91 | struct 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 | |||
104 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry | ||
105 | { | ||
106 | /** | ||
107 | * DLL | ||
108 | */ | ||
109 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *prev; | ||
110 | |||
111 | /** | ||
112 | * DLL | ||
113 | */ | ||
114 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *next; | ||
115 | |||
116 | /** | ||
117 | * The attribute claim | ||
118 | */ | ||
119 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim; | ||
120 | }; | ||
121 | |||
122 | /** | ||
123 | * Create a new attribute claim. | ||
124 | * | ||
125 | * @param name the attribute name | ||
126 | * @param type the attribute type | ||
127 | * @param data the attribute value | ||
128 | * @param data_size the attribute value size | ||
129 | * @return the new attribute | ||
130 | */ | ||
131 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim * | ||
132 | GNUNET_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 | */ | ||
145 | size_t | ||
146 | GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); | ||
147 | |||
148 | void | ||
149 | GNUNET_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 | */ | ||
160 | size_t | ||
161 | GNUNET_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 | */ | ||
172 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList * | ||
173 | GNUNET_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 | */ | ||
184 | size_t | ||
185 | GNUNET_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 | */ | ||
197 | size_t | ||
198 | GNUNET_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 | */ | ||
209 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim * | ||
210 | GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data, | ||
211 | size_t data_size); | ||
212 | |||
213 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList* | ||
214 | GNUNET_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 | */ | ||
222 | uint32_t | ||
223 | GNUNET_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 | */ | ||
235 | int | ||
236 | GNUNET_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 | */ | ||
249 | char * | ||
250 | GNUNET_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 | */ | ||
260 | const char* | ||
261 | GNUNET_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 | ||
38 | extern "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 | */ | ||
56 | typedef 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 | */ | ||
74 | typedef 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 | */ | ||
89 | typedef 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 | */ | ||
101 | typedef 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 | */ | ||
109 | struct 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 | ||
38 | extern "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 | */ | ||
52 | typedef 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 | */ | ||
60 | struct GNUNET_IDENTITY_PROVIDER_PluginFunctions | ||
61 | { | ||
62 | |||
63 | /** | ||
64 | * Closure to pass to all plugin functions. | ||
65 | */ | ||
66 | void *cls; | ||
67 | |||
68 | /** | ||
69 | * Store a ticket in the database. | ||
70 | * | ||
71 | * @param cls closure (internal context for the plugin) | ||
72 | * @param ticket the ticket to store | ||
73 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
74 | */ | ||
75 | int (*store_ticket) (void *cls, | ||
76 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
77 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); | ||
78 | |||
79 | /** | ||
80 | * Delete a ticket from the database. | ||
81 | * | ||
82 | * @param cls closure (internal context for the plugin) | ||
83 | * @param ticket the ticket to store | ||
84 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
85 | */ | ||
86 | int (*delete_ticket) (void *cls, | ||
87 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); | ||
88 | |||
89 | |||
90 | |||
91 | /** | ||
92 | * Iterate over all tickets | ||
93 | * | ||
94 | * @param cls closure (internal context for the plugin) | ||
95 | * @param identity the identity | ||
96 | * @param audience GNUNET_YES if the identity is the audience of the ticket | ||
97 | * else it is considered the issuer | ||
98 | * @param iter function to call with the result | ||
99 | * @param iter_cls closure for @a iter | ||
100 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
101 | */ | ||
102 | int (*iterate_tickets) (void *cls, | ||
103 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
104 | int audience, | ||
105 | uint64_t offset, | ||
106 | GNUNET_IDENTITY_PROVIDER_TicketIterator iter, void *iter_cls); | ||
107 | |||
108 | int (*get_ticket_attributes) (void* cls, | ||
109 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
110 | GNUNET_IDENTITY_PROVIDER_TicketIterator iter, | ||
111 | void *iter_cls); | ||
112 | }; | ||
113 | |||
114 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
115 | { | ||
116 | #endif | ||
117 | #ifdef __cplusplus | ||
118 | } | ||
119 | #endif | ||
120 | |||
121 | #endif | ||
122 | |||
123 | /** @} */ /* end of group */ | ||
diff --git a/src/include/gnunet_identity_provider_service.h b/src/include/gnunet_identity_provider_service.h index e533f6f8c..6bc05d0f4 100644 --- a/src/include/gnunet_identity_provider_service.h +++ b/src/include/gnunet_identity_provider_service.h | |||
@@ -39,7 +39,7 @@ extern "C" | |||
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #include "gnunet_util_lib.h" | 41 | #include "gnunet_util_lib.h" |
42 | 42 | #include "gnunet_identity_attribute_lib.h" | |
43 | 43 | ||
44 | /** | 44 | /** |
45 | * Version number of GNUnet Identity Provider API. | 45 | * Version number of GNUnet Identity Provider API. |
@@ -57,169 +57,309 @@ struct GNUNET_IDENTITY_PROVIDER_Handle; | |||
57 | struct GNUNET_IDENTITY_PROVIDER_Token; | 57 | struct GNUNET_IDENTITY_PROVIDER_Token; |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * Handle for a ticket | 60 | * The ticket |
61 | */ | 61 | */ |
62 | struct GNUNET_IDENTITY_PROVIDER_Ticket; | 62 | struct 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 | */ |
67 | struct GNUNET_IDENTITY_PROVIDER_Operation; | 83 | struct 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 | */ |
76 | typedef void | 92 | struct GNUNET_IDENTITY_PROVIDER_Handle * |
77 | (*GNUNET_IDENTITY_PROVIDER_ExchangeCallback)(void *cls, | 93 | GNUNET_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 | */ |
94 | typedef void | 105 | typedef 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 | */ |
107 | struct GNUNET_IDENTITY_PROVIDER_Handle * | 122 | struct GNUNET_IDENTITY_PROVIDER_Operation * |
108 | GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); | 123 | GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h, |
124 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, | ||
125 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr, | ||
126 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont, | ||
127 | void *cont_cls); | ||
109 | 128 | ||
110 | 129 | ||
111 | /** | 130 | /** |
112 | * Issue a token for a specific audience. | 131 | * Process an attribute that was stored in the idp. |
113 | * | 132 | * |
114 | * @param id identity provider service to use | 133 | * @param cls closure |
115 | * @param iss issuer (identity) | 134 | * @param attr the attribute |
116 | * @param aud audience (identity) | ||
117 | * @param scope the identity attributes requested, comman separated | ||
118 | * @param expiration the token expiration | ||
119 | * @param nonce the nonce that will be included in token and ticket | ||
120 | * @param cb callback to call with result | ||
121 | * @param cb_cls closure | ||
122 | * @return handle to abort the operation | ||
123 | */ | 135 | */ |
124 | struct GNUNET_IDENTITY_PROVIDER_Operation * | 136 | typedef void |
125 | GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id, | 137 | (*GNUNET_IDENTITY_PROVIDER_AttributeResult) (void *cls, |
126 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key, | 138 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, |
127 | const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | 139 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr); |
128 | const char* scope, | 140 | |
129 | struct GNUNET_TIME_Absolute expiration, | ||
130 | uint64_t nonce, | ||
131 | GNUNET_IDENTITY_PROVIDER_IssueCallback cb, | ||
132 | void *cb_cls); | ||
133 | 141 | ||
134 | 142 | ||
135 | /** | 143 | /** |
136 | * Exchange a ticket for a token. Intended to be used by audience that | 144 | * List all attributes for a local identity. |
137 | * received a ticket. | 145 | * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle` |
146 | * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and | ||
147 | * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once | ||
148 | * immediately, and then again after | ||
149 | * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked. | ||
138 | * | 150 | * |
139 | * @param id identity provider service to use | 151 | * On error (disconnect), @a error_cb will be invoked. |
140 | * @param ticket the ticket to exchange | 152 | * On normal completion, @a finish_cb proc will be |
141 | * @param aud_privkey the audience of the ticket | 153 | * invoked. |
142 | * @param cont function to call once the operation finished | 154 | * |
143 | * @param cont_cls closure for @a cont | 155 | * @param h handle to the idp |
144 | * @return handle to abort the operation | 156 | * @param identity identity to access |
157 | * @param error_cb function to call on error (i.e. disconnect), | ||
158 | * the handle is afterwards invalid | ||
159 | * @param error_cb_cls closure for @a error_cb | ||
160 | * @param proc function to call on each attribute; it | ||
161 | * will be called repeatedly with a value (if available) | ||
162 | * @param proc_cls closure for @a proc | ||
163 | * @param finish_cb function to call on completion | ||
164 | * the handle is afterwards invalid | ||
165 | * @param finish_cb_cls closure for @a finish_cb | ||
166 | * @return an iterator handle to use for iteration | ||
145 | */ | 167 | */ |
146 | struct GNUNET_IDENTITY_PROVIDER_Operation * | 168 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator * |
147 | GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id, | 169 | GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h, |
148 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | 170 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, |
149 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey, | 171 | GNUNET_SCHEDULER_TaskCallback error_cb, |
150 | GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont, | 172 | void *error_cb_cls, |
151 | void *cont_cls); | 173 | GNUNET_IDENTITY_PROVIDER_AttributeResult proc, |
174 | void *proc_cls, | ||
175 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
176 | void *finish_cb_cls); | ||
152 | 177 | ||
153 | 178 | ||
154 | /** | 179 | /** |
155 | * Disconnect from identity provider service. | 180 | * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start |
181 | * for the next record. | ||
156 | * | 182 | * |
157 | * @param h identity provider service to disconnect | 183 | * @param it the iterator |
158 | */ | 184 | */ |
159 | void | 185 | void |
160 | GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); | 186 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it); |
161 | 187 | ||
162 | 188 | ||
163 | /** | 189 | /** |
164 | * Cancel an identity provider operation. Note that the operation MAY still | 190 | * Stops iteration and releases the idp handle for further calls. Must |
165 | * be executed; this merely cancels the continuation; if the request | 191 | * be called on any iteration that has not yet completed prior to calling |
166 | * was already transmitted, the service may still choose to complete | 192 | * #GNUNET_IDENTITY_PROVIDER_disconnect. |
167 | * the operation. | ||
168 | * | 193 | * |
169 | * @param op operation to cancel | 194 | * @param it the iterator |
170 | */ | 195 | */ |
171 | void | 196 | void |
172 | GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op); | 197 | GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it); |
173 | 198 | ||
174 | 199 | ||
175 | /** | 200 | /** |
176 | * Convenience API | 201 | * Method called when a token has been issued. |
202 | * On success returns a ticket that can be given to the audience to retrive the | ||
203 | * token | ||
204 | * | ||
205 | * @param cls closure | ||
206 | * @param ticket the ticket | ||
177 | */ | 207 | */ |
208 | typedef void | ||
209 | (*GNUNET_IDENTITY_PROVIDER_TicketCallback)(void *cls, | ||
210 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); | ||
178 | 211 | ||
179 | /** | 212 | /** |
180 | * Destroy token | 213 | * Issues a ticket to another identity. The identity may use |
214 | * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket | ||
215 | * and retrieve the attributes specified in the AttributeList. | ||
181 | * | 216 | * |
182 | * @param token the token | 217 | * @param id the identity provider to use |
218 | * @param iss the issuing identity | ||
219 | * @param rp the subject of the ticket (the relying party) | ||
220 | * @param attr the attributes that the relying party is given access to | ||
221 | * @param cb the callback | ||
222 | * @param cb_cls the callback closure | ||
223 | * @return handle to abort the operation | ||
183 | */ | 224 | */ |
184 | void | 225 | struct GNUNET_IDENTITY_PROVIDER_Operation * |
185 | GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token); | 226 | GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *id, |
227 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, | ||
228 | const struct GNUNET_CRYPTO_EcdsaPublicKey *rp, | ||
229 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
230 | GNUNET_IDENTITY_PROVIDER_TicketCallback cb, | ||
231 | void *cb_cls); | ||
186 | 232 | ||
187 | /** | 233 | /** |
188 | * Returns string representation of token. A JSON-Web-Token. | 234 | * Revoked an issued ticket. The relying party will be unable to retrieve |
235 | * updated attributes. | ||
189 | * | 236 | * |
190 | * @param token the token | 237 | * @param id the identity provider to use |
191 | * @return The JWT (must be freed) | 238 | * @param identity the issuing identity |
239 | * @param ticket the ticket to revoke | ||
240 | * @param cb the callback | ||
241 | * @param cb_cls the callback closure | ||
242 | * @return handle to abort the operation | ||
192 | */ | 243 | */ |
193 | char * | 244 | struct GNUNET_IDENTITY_PROVIDER_Operation * |
194 | GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token); | 245 | GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *id, |
246 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
247 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
248 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb, | ||
249 | void *cb_cls); | ||
250 | |||
251 | |||
195 | 252 | ||
196 | /** | 253 | /** |
197 | * Returns string representation of ticket. Base64-Encoded | 254 | * Consumes an issued ticket. The ticket is persisted |
255 | * and used to retrieve identity information from the issuer | ||
198 | * | 256 | * |
199 | * @param ticket the ticket | 257 | * @param id the identity provider to use |
200 | * @return the Base64-Encoded ticket | 258 | * @param identity the identity that is the subject of the issued ticket (the audience) |
259 | * @param ticket the issued ticket to consume | ||
260 | * @param cb the callback to call | ||
261 | * @param cb_cls the callback closure | ||
262 | * @return handle to abort the operation | ||
263 | */ | ||
264 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
265 | GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *id, | ||
266 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
267 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
268 | GNUNET_IDENTITY_PROVIDER_AttributeResult cb, | ||
269 | void *cb_cls); | ||
270 | |||
271 | /** | ||
272 | * Lists all tickets that have been issued to remote | ||
273 | * identites (relying parties) | ||
274 | * | ||
275 | * @param h the identity provider to use | ||
276 | * @param identity the issuing identity | ||
277 | * @param error_cb function to call on error (i.e. disconnect), | ||
278 | * the handle is afterwards invalid | ||
279 | * @param error_cb_cls closure for @a error_cb | ||
280 | * @param proc function to call on each ticket; it | ||
281 | * will be called repeatedly with a value (if available) | ||
282 | * @param proc_cls closure for @a proc | ||
283 | * @param finish_cb function to call on completion | ||
284 | * the handle is afterwards invalid | ||
285 | * @param finish_cb_cls closure for @a finish_cb | ||
286 | * @return an iterator handle to use for iteration | ||
287 | */ | ||
288 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator * | ||
289 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
290 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
291 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
292 | void *error_cb_cls, | ||
293 | GNUNET_IDENTITY_PROVIDER_TicketCallback proc, | ||
294 | void *proc_cls, | ||
295 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
296 | void *finish_cb_cls); | ||
297 | |||
298 | /** | ||
299 | * Lists all tickets that have been issued to remote | ||
300 | * identites (relying parties) | ||
301 | * | ||
302 | * @param id the identity provider to use | ||
303 | * @param identity the issuing identity | ||
304 | * @param error_cb function to call on error (i.e. disconnect), | ||
305 | * the handle is afterwards invalid | ||
306 | * @param error_cb_cls closure for @a error_cb | ||
307 | * @param proc function to call on each ticket; it | ||
308 | * will be called repeatedly with a value (if available) | ||
309 | * @param proc_cls closure for @a proc | ||
310 | * @param finish_cb function to call on completion | ||
311 | * the handle is afterwards invalid | ||
312 | * @param finish_cb_cls closure for @a finish_cb | ||
313 | * @return an iterator handle to use for iteration | ||
201 | */ | 314 | */ |
202 | char * | 315 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator * |
203 | GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); | 316 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h, |
317 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
318 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
319 | void *error_cb_cls, | ||
320 | GNUNET_IDENTITY_PROVIDER_TicketCallback proc, | ||
321 | void *proc_cls, | ||
322 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
323 | void *finish_cb_cls); | ||
204 | 324 | ||
205 | /** | 325 | /** |
206 | * Created a ticket from a string (Base64 encoded ticket) | 326 | * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start |
327 | * for the next record. | ||
207 | * | 328 | * |
208 | * @param input Base64 encoded ticket | 329 | * @param it the iterator |
209 | * @param ticket pointer where the ticket is stored | ||
210 | * @return GNUNET_OK | ||
211 | */ | 330 | */ |
212 | int | 331 | void |
213 | GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, | 332 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it); |
214 | struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket); | ||
215 | 333 | ||
216 | /** | 334 | /** |
217 | * Destroys a ticket | 335 | * Stops iteration and releases the idp handle for further calls. Must |
336 | * be called on any iteration that has not yet completed prior to calling | ||
337 | * #GNUNET_IDENTITY_PROVIDER_disconnect. | ||
218 | * | 338 | * |
219 | * @param ticket the ticket to destroy | 339 | * @param it the iterator |
220 | */ | 340 | */ |
221 | void | 341 | void |
222 | GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); | 342 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it); |
343 | |||
344 | /** | ||
345 | * Disconnect from identity provider service. | ||
346 | * | ||
347 | * @param h identity provider service to disconnect | ||
348 | */ | ||
349 | void | ||
350 | GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); | ||
351 | |||
352 | |||
353 | /** | ||
354 | * Cancel an identity provider operation. Note that the operation MAY still | ||
355 | * be executed; this merely cancels the continuation; if the request | ||
356 | * was already transmitted, the service may still choose to complete | ||
357 | * the operation. | ||
358 | * | ||
359 | * @param op operation to cancel | ||
360 | */ | ||
361 | void | ||
362 | GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op); | ||
223 | 363 | ||
224 | #if 0 /* keep Emacsens' auto-indent happy */ | 364 | #if 0 /* keep Emacsens' auto-indent happy */ |
225 | { | 365 | { |
diff --git a/src/include/gnunet_jsonapi_lib.h b/src/include/gnunet_jsonapi_lib.h index f95bff836..2f6b810f0 100644 --- a/src/include/gnunet_jsonapi_lib.h +++ b/src/include/gnunet_jsonapi_lib.h | |||
@@ -248,7 +248,7 @@ GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource | |||
248 | * @param res the JSON resource | 248 | * @param res the JSON resource |
249 | * @return the resource id | 249 | * @return the resource id |
250 | */ | 250 | */ |
251 | char* | 251 | const char* |
252 | GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource); | 252 | GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource); |
253 | 253 | ||
254 | 254 | ||
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 9cfd00e39..436adc5a4 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -2628,13 +2628,47 @@ extern "C" | |||
2628 | * | 2628 | * |
2629 | * IDENTITY PROVIDER MESSAGE TYPES | 2629 | * IDENTITY PROVIDER MESSAGE TYPES |
2630 | */ | 2630 | */ |
2631 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE 961 | 2631 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE 961 |
2632 | 2632 | ||
2633 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE 962 | 2633 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE 962 |
2634 | 2634 | ||
2635 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT 963 | 2635 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START 963 |
2636 | 2636 | ||
2637 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT 964 | 2637 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP 964 |
2638 | |||
2639 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT 965 | ||
2640 | |||
2641 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 966 | ||
2642 | |||
2643 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET 967 | ||
2644 | |||
2645 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 968 | ||
2646 | |||
2647 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET 969 | ||
2648 | |||
2649 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT 970 | ||
2650 | |||
2651 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET 971 | ||
2652 | |||
2653 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT 972 | ||
2654 | |||
2655 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START 973 | ||
2656 | |||
2657 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP 974 | ||
2658 | |||
2659 | #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT 975 | ||
2660 | |||
2661 | /************************************************** | ||
2662 | * | ||
2663 | * CREDENTIAL MESSAGE TYPES | ||
2664 | */ | ||
2665 | #define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY 981 | ||
2666 | |||
2667 | #define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 982 | ||
2668 | |||
2669 | #define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 983 | ||
2670 | |||
2671 | #define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 984 | ||
2638 | 2672 | ||
2639 | /******************************************************************************/ | 2673 | /******************************************************************************/ |
2640 | 2674 | ||
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h index c1e0d005c..03bc4575e 100644 --- a/src/include/gnunet_signatures.h +++ b/src/include/gnunet_signatures.h | |||
@@ -185,6 +185,11 @@ extern "C" | |||
185 | */ | 185 | */ |
186 | #define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27 | 186 | #define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27 |
187 | 187 | ||
188 | /** | ||
189 | * Signature for a GNUnet credential | ||
190 | */ | ||
191 | #define GNUNET_SIGNATURE_PURPOSE_CREDENTIAL 28 | ||
192 | |||
188 | #if 0 /* keep Emacsens' auto-indent happy */ | 193 | #if 0 /* keep Emacsens' auto-indent happy */ |
189 | { | 194 | { |
190 | #endif | 195 | #endif |
diff --git a/src/jsonapi/jsonapi_document.c b/src/jsonapi/jsonapi_document.c index 600b7ee6a..3a60940f6 100644 --- a/src/jsonapi/jsonapi_document.c +++ b/src/jsonapi/jsonapi_document.c | |||
@@ -332,28 +332,20 @@ GNUNET_JSONAPI_document_to_json (const struct GNUNET_JSONAPI_Document *doc, | |||
332 | GNUNET_JSONAPI_KEY_ERRORS, | 332 | GNUNET_JSONAPI_KEY_ERRORS, |
333 | res_json); | 333 | res_json); |
334 | } else { | 334 | } else { |
335 | switch (doc->res_count) | 335 | if (0 == doc->res_count) |
336 | { | 336 | { |
337 | case 0: | 337 | res_json = json_null(); |
338 | res_json = json_null(); | 338 | } else { |
339 | break; | 339 | res_json = json_array (); |
340 | case 1: | 340 | for (res = doc->res_list_head; |
341 | res != NULL; | ||
342 | res = res->next) | ||
343 | { | ||
341 | GNUNET_assert (GNUNET_OK == | 344 | GNUNET_assert (GNUNET_OK == |
342 | GNUNET_JSONAPI_resource_to_json (doc->res_list_head, | 345 | GNUNET_JSONAPI_resource_to_json (res, |
343 | &res_json)); | 346 | &res_json_tmp)); |
344 | break; | 347 | json_array_append_new (res_json, res_json_tmp); |
345 | default: | 348 | } |
346 | res_json = json_array (); | ||
347 | for (res = doc->res_list_head; | ||
348 | res != NULL; | ||
349 | res = res->next) | ||
350 | { | ||
351 | GNUNET_assert (GNUNET_OK == | ||
352 | GNUNET_JSONAPI_resource_to_json (res, | ||
353 | &res_json_tmp)); | ||
354 | json_array_append (res_json, res_json_tmp); | ||
355 | } | ||
356 | break; | ||
357 | } | 349 | } |
358 | json_object_set_new (*root_json, | 350 | json_object_set_new (*root_json, |
359 | GNUNET_JSONAPI_KEY_DATA, | 351 | GNUNET_JSONAPI_KEY_DATA, |
diff --git a/src/jsonapi/jsonapi_resource.c b/src/jsonapi/jsonapi_resource.c index 85bca10ee..be28ad5df 100644 --- a/src/jsonapi/jsonapi_resource.c +++ b/src/jsonapi/jsonapi_resource.c | |||
@@ -92,9 +92,9 @@ GNUNET_JSONAPI_resource_new (const char *type, const char *id) | |||
92 | { | 92 | { |
93 | struct GNUNET_JSONAPI_Resource *res; | 93 | struct GNUNET_JSONAPI_Resource *res; |
94 | 94 | ||
95 | if ( (NULL == type) || (0 == strlen (type)) ) | 95 | if (NULL == type) |
96 | return NULL; | 96 | return NULL; |
97 | if ( (NULL == id) || (0 == strlen (id)) ) | 97 | if (NULL == id) |
98 | return NULL; | 98 | return NULL; |
99 | 99 | ||
100 | res = GNUNET_new (struct GNUNET_JSONAPI_Resource); | 100 | res = GNUNET_new (struct GNUNET_JSONAPI_Resource); |
@@ -245,7 +245,7 @@ GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource | |||
245 | * @param res the JSON resource | 245 | * @param res the JSON resource |
246 | * @return the resource id | 246 | * @return the resource id |
247 | */ | 247 | */ |
248 | char* | 248 | const char* |
249 | GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource) | 249 | GNUNET_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] |
2 | UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-rest.sock | ||
2 | BINARY=gnunet-rest-server | 3 | BINARY=gnunet-rest-server |
3 | REST_PORT=7776 | 4 | REST_PORT=7776 |
4 | REST_ALLOW_HEADERS=Authorization,Accept,Content-Type | 5 | REST_ALLOW_HEADERS=Authorization,Accept,Content-Type |
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index c26e3e84b..cc9ff4745 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am | |||
@@ -119,11 +119,22 @@ libgnunetutil_la_LIBADD = \ | |||
119 | $(LTLIBINTL) \ | 119 | $(LTLIBINTL) \ |
120 | -lltdl $(Z_LIBS) -lunistring $(XLIB) | 120 | -lltdl $(Z_LIBS) -lunistring $(XLIB) |
121 | 121 | ||
122 | if HAVE_PBC | ||
123 | if HAVE_ABE | ||
124 | libgnunetutil_la_SOURCES += \ | ||
125 | crypto_abe.c | ||
126 | libgnunetutil_la_LIBADD += \ | ||
127 | $(ABE_LIBADD) \ | ||
128 | -lgabe \ | ||
129 | -lpbc \ | ||
130 | -lglib-2.0 | ||
131 | endif | ||
132 | endif | ||
133 | |||
122 | libgnunetutil_la_LDFLAGS = \ | 134 | libgnunetutil_la_LDFLAGS = \ |
123 | $(GN_LIB_LDFLAGS) \ | 135 | $(GN_LIB_LDFLAGS) \ |
124 | -version-info 13:0:0 | 136 | -version-info 13:0:0 |
125 | 137 | ||
126 | |||
127 | libgnunetutil_taler_wallet_la_SOURCES = \ | 138 | libgnunetutil_taler_wallet_la_SOURCES = \ |
128 | common_allocation.c \ | 139 | common_allocation.c \ |
129 | common_endian.c \ | 140 | common_endian.c \ |
@@ -553,6 +564,17 @@ test_speedup_SOURCES = \ | |||
553 | test_speedup_LDADD = \ | 564 | test_speedup_LDADD = \ |
554 | libgnunetutil.la | 565 | libgnunetutil.la |
555 | 566 | ||
567 | if HAVE_PBC | ||
568 | if HAVE_ABE | ||
569 | test_crypto_abe_SOURCES = \ | ||
570 | test_crypto_abe.c | ||
571 | test_crypto_abe_LDADD = \ | ||
572 | libgnunetutil.la | ||
573 | check_PROGRAMS += \ | ||
574 | test_crypto_abe | ||
575 | endif | ||
576 | endif | ||
577 | |||
556 | perf_crypto_hash_SOURCES = \ | 578 | perf_crypto_hash_SOURCES = \ |
557 | perf_crypto_hash.c | 579 | perf_crypto_hash.c |
558 | perf_crypto_hash_LDADD = \ | 580 | perf_crypto_hash_LDADD = \ |
diff --git a/src/util/crypto_abe.c b/src/util/crypto_abe.c new file mode 100644 index 000000000..fcaa826ed --- /dev/null +++ b/src/util/crypto_abe.c | |||
@@ -0,0 +1,416 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. Copyright (C) 2001-2014 Christian Grothoff | ||
3 | (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | |||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file util/crypto_random.c | ||
24 | * @brief functions to gather random numbers | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include "platform.h" | ||
30 | #include <pbc/pbc.h> | ||
31 | #include <gabe.h> | ||
32 | |||
33 | #include "gnunet_crypto_lib.h" | ||
34 | |||
35 | struct GNUNET_CRYPTO_AbeMasterKey | ||
36 | { | ||
37 | gabe_pub_t* pub; | ||
38 | gabe_msk_t* msk; | ||
39 | }; | ||
40 | |||
41 | struct GNUNET_CRYPTO_AbeKey | ||
42 | { | ||
43 | gabe_pub_t* pub; | ||
44 | gabe_prv_t* prv; | ||
45 | }; | ||
46 | |||
47 | static int | ||
48 | init_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 | |||
79 | static int | ||
80 | aes_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 | |||
115 | static int | ||
116 | aes_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 | |||
148 | struct GNUNET_CRYPTO_AbeMasterKey* | ||
149 | GNUNET_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 | |||
159 | void | ||
160 | GNUNET_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 | |||
169 | struct GNUNET_CRYPTO_AbeKey* | ||
170 | GNUNET_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 | |||
186 | void | ||
187 | GNUNET_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 | |||
197 | ssize_t | ||
198 | write_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 | |||
225 | ssize_t | ||
226 | read_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 | |||
255 | ssize_t | ||
256 | GNUNET_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 | |||
287 | ssize_t | ||
288 | GNUNET_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 | |||
325 | ssize_t | ||
326 | GNUNET_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 | |||
347 | struct GNUNET_CRYPTO_AbeKey* | ||
348 | GNUNET_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 | |||
371 | ssize_t | ||
372 | GNUNET_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 | |||
393 | struct GNUNET_CRYPTO_AbeMasterKey* | ||
394 | GNUNET_CRYPTO_cpabe_deserialize_master_key (const void *data, | ||
395 | size_t len) | ||
396 | { | ||
397 | struct GNUNET_CRYPTO_AbeMasterKey *key; | ||
398 | char *msk; | ||
399 | char *pub; | ||
400 | int msk_len; | ||
401 | int pub_len; | ||
402 | |||
403 | key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey); | ||
404 | read_cpabe (data, | ||
405 | &pub, | ||
406 | &pub_len, | ||
407 | &msk, | ||
408 | &msk_len); | ||
409 | key->pub = gabe_pub_unserialize (pub, pub_len); | ||
410 | key->msk = gabe_msk_unserialize (key->pub, msk, msk_len); | ||
411 | |||
412 | GNUNET_free (pub); | ||
413 | GNUNET_free (msk); | ||
414 | |||
415 | return key; | ||
416 | } | ||
diff --git a/src/util/test_crypto_abe.c b/src/util/test_crypto_abe.c new file mode 100644 index 000000000..cb36dccae --- /dev/null +++ b/src/util/test_crypto_abe.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2002, 2003, 2004, 2006 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | |||
20 | */ | ||
21 | /** | ||
22 | * @author Martin Schanzenbach | ||
23 | * @file util/test_crypto_abe.c | ||
24 | * @brief test for ABE ciphers | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | |||
29 | #define TESTSTRING "Hello World!" | ||
30 | |||
31 | static int | ||
32 | testAbecipher () | ||
33 | { | ||
34 | struct GNUNET_CRYPTO_AbeMasterKey *msk; | ||
35 | struct GNUNET_CRYPTO_AbeKey *key; | ||
36 | char *result; | ||
37 | char **attrs; | ||
38 | int size; | ||
39 | char *res; | ||
40 | msk = GNUNET_CRYPTO_cpabe_create_master_key (); | ||
41 | size = GNUNET_CRYPTO_cpabe_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, | ||
42 | "testattr", //Policy | ||
43 | msk, | ||
44 | (void*)&result); | ||
45 | GNUNET_assert (-1 != size); | ||
46 | attrs = GNUNET_malloc (2 * sizeof (char*)); | ||
47 | attrs[0] = "testattr"; | ||
48 | attrs[1] = NULL; | ||
49 | key = GNUNET_CRYPTO_cpabe_create_key (msk, | ||
50 | attrs); | ||
51 | |||
52 | size = GNUNET_CRYPTO_cpabe_decrypt (result, size, | ||
53 | key, | ||
54 | (void*)&res); | ||
55 | if (strlen (TESTSTRING) + 1 != size) | ||
56 | { | ||
57 | printf ("abeciphertest failed: decryptBlock returned %d\n", size); | ||
58 | return 1; | ||
59 | } | ||
60 | if (0 != strcmp (res, TESTSTRING)) | ||
61 | { | ||
62 | printf ("abeciphertest failed: %s != %s\n", res, TESTSTRING); | ||
63 | return 1; | ||
64 | } | ||
65 | else | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | |||
70 | int | ||
71 | main (int argc, char *argv[]) | ||
72 | { | ||
73 | int failureCount = 0; | ||
74 | |||
75 | GNUNET_log_setup ("test-crypto-abe", "WARNING", NULL); | ||
76 | failureCount += testAbecipher (); | ||
77 | |||
78 | if (failureCount != 0) | ||
79 | { | ||
80 | printf ("%d TESTS FAILED!\n", failureCount); | ||
81 | return -1; | ||
82 | } | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | /* end of test_crypto_aes.c */ | ||