summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-01-04 16:07:55 +0100
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-01-04 16:07:55 +0100
commit056ca89d207cd1865a90fe3fcd430a4381097da5 (patch)
tree928a3f7bf520ec99ac1bdbceb423dd68d375acbb
parentb4f6c5a8b521d4942d19f5a34929bebaa60a6210 (diff)
parent78705d5a49d7066a01b832546d2507456a3c5d2c (diff)
Merge remote-tracking branch 'origin/identity_abe'
-rw-r--r--README9
-rw-r--r--configure.ac25
-rw-r--r--contrib/Dockerfile63
-rw-r--r--contrib/docker-entrypoint.sh3
-rw-r--r--po/POTFILES.in134
-rw-r--r--src/Makefile.am14
-rw-r--r--src/abe/Makefile.am50
-rw-r--r--src/abe/abe.c499
-rw-r--r--src/abe/test_cpabe.c87
-rw-r--r--src/credential/Makefile.am112
-rw-r--r--src/credential/credential.conf.in5
-rw-r--r--src/credential/credential.h221
-rw-r--r--src/credential/credential_api.c511
-rw-r--r--src/credential/credential_misc.c168
-rw-r--r--src/credential/credential_misc.h35
-rw-r--r--src/credential/credential_serialization.c460
-rw-r--r--src/credential/credential_serialization.h159
-rw-r--r--src/credential/gnunet-credential.c588
-rw-r--r--src/credential/gnunet-service-credential.c1160
-rw-r--r--src/credential/plugin_gnsrecord_credential.c353
-rw-r--r--src/credential/plugin_rest_credential.c1146
-rwxr-xr-xsrc/credential/test_credential_collect.sh47
-rwxr-xr-xsrc/credential/test_credential_collect_rest.sh90
-rw-r--r--src/credential/test_credential_defaults.conf24
-rwxr-xr-xsrc/credential/test_credential_issue.sh44
-rwxr-xr-xsrc/credential/test_credential_issue_rest.sh53
-rw-r--r--src/credential/test_credential_lookup.conf28
-rwxr-xr-xsrc/credential/test_credential_verify.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_and.sh81
-rwxr-xr-xsrc/credential/test_credential_verify_rest.sh87
-rwxr-xr-xsrc/credential/test_credential_verify_simple.sh50
-rw-r--r--src/exit/gnunet-daemon-exit.c2
-rw-r--r--src/gns/gns_api.c11
-rw-r--r--src/gns/plugin_gnsrecord_gns.c67
-rw-r--r--src/identity-attribute/Makefile.am44
-rw-r--r--src/identity-attribute/identity_attribute.c421
-rw-r--r--src/identity-attribute/identity_attribute.h56
-rw-r--r--src/identity-attribute/plugin_identity_attribute_gnuid.c184
-rw-r--r--src/identity-provider/Makefile.am74
-rw-r--r--src/identity-provider/gnunet-identity-token.c179
-rw-r--r--src/identity-provider/gnunet-idp.c439
-rw-r--r--src/identity-provider/gnunet-service-identity-provider.c3064
-rw-r--r--src/identity-provider/identity-provider.conf4
-rw-r--r--src/identity-provider/identity_provider.h307
-rw-r--r--src/identity-provider/identity_provider_api.c1213
-rw-r--r--src/identity-provider/identity_token.c964
-rw-r--r--src/identity-provider/identity_token.h346
-rw-r--r--src/identity-provider/jwt.c180
-rw-r--r--src/identity-provider/plugin_gnsrecord_identity_provider.c (renamed from src/identity/plugin_gnsrecord_identity.c)48
-rw-r--r--src/identity-provider/plugin_identity_provider_sqlite.c736
-rw-r--r--src/identity-provider/plugin_rest_identity_provider.c1119
-rw-r--r--src/identity-provider/test_idp.conf28
-rwxr-xr-xsrc/identity-provider/test_idp.sh31
-rwxr-xr-xsrc/identity-provider/test_idp_attribute.sh40
-rwxr-xr-xsrc/identity-provider/test_idp_consume.sh43
-rw-r--r--src/identity-provider/test_idp_defaults.conf24
-rwxr-xr-xsrc/identity-provider/test_idp_issue.sh42
-rwxr-xr-xsrc/identity-provider/test_idp_revoke.sh60
-rw-r--r--src/identity/Makefile.am11
-rw-r--r--src/identity/plugin_rest_identity.c3
-rw-r--r--src/include/gnunet_abe_lib.h193
-rw-r--r--src/include/gnunet_credential_service.h297
-rw-r--r--src/include/gnunet_gnsrecord_lib.h22
-rw-r--r--src/include/gnunet_identity_attribute_lib.h277
-rw-r--r--src/include/gnunet_identity_attribute_plugin.h149
-rw-r--r--src/include/gnunet_identity_provider_plugin.h123
-rw-r--r--src/include/gnunet_identity_provider_service.h333
-rw-r--r--src/include/gnunet_jsonapi_lib.h2
-rw-r--r--src/include/gnunet_protocols.h42
-rw-r--r--src/include/gnunet_rest_lib.h4
-rw-r--r--src/include/gnunet_rest_plugin.h2
-rw-r--r--src/include/gnunet_signatures.h5
-rw-r--r--src/jsonapi/jsonapi_document.c32
-rw-r--r--src/jsonapi/jsonapi_resource.c6
-rw-r--r--src/namestore/plugin_rest_namestore.c27
-rw-r--r--src/rest/rest.conf1
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/crypto_abe.c416
78 files changed, 14264 insertions, 3795 deletions
diff --git a/README b/README
index db64bc17a..ef30fe7e3 100644
--- a/README
+++ b/README
@@ -15,8 +15,11 @@ GNU package (http://www.gnu.org/).
This is an ALPHA release. There are known and significant bugs as
well as many missing features in this release.
+GNUnet is free software released under the GNU General Public License
+(v3 or later). For details see the COPYING file in this directory.
+
Additional documentation about GNUnet can be found at
-https://gnunet.org/.
+https://gnunet.org/ and in the doc/ folder.
Dependencies:
@@ -63,6 +66,8 @@ How to install?
The fastest way is to use a binary package if it is available for your
system. For a more detailed description, read the installation
instructions on the webpage at https://gnunet.org/installation.
+Generic installation instructions are in the INSTALL file in this
+directory.
Note that some functions of GNUnet require "root" access. GNUnet will
install (tiny) SUID binaries for those functions is you run "make
@@ -300,7 +305,7 @@ Stay tuned
* https://gnunet.org/
* https://gnunet.org/bugs/
-* https://gnunet.org/svn/
+* https://gnunet.org/git/
* http://www.gnu.org/software/gnunet/
* http://mail.gnu.org/mailman/listinfo/gnunet-developers
* http://mail.gnu.org/mailman/listinfo/help-gnunet
diff --git a/configure.ac b/configure.ac
index eae03b01b..017b4836c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -446,6 +446,27 @@ AC_CHECK_LIB(ogg, ogg_stream_flush_fill,
ogg=0)
+PKG_CHECK_MODULES([GLIB], [glib-2.0])
+# check for pbc library
+pbc=0
+AC_CHECK_HEADER([pbc/pbc.h],pbc=1)
+AC_CHECK_HEADER([gabe.h],abe=1)
+AM_CONDITIONAL(HAVE_PBC, [test "$pbc" = 1])
+AM_CONDITIONAL(HAVE_ABE, [test "$abe" = 1])
+if test "x$pbc" = x1
+then
+ AC_DEFINE([HAVE_PBC],[1],[Have pbc library])
+else
+ AC_DEFINE([HAVE_PBC],[0],[Lacking pbc library])
+fi
+if test "x$abe" = x1
+then
+ AC_DEFINE([HAVE_ABE],[1],[Have ABE library])
+else
+ AC_DEFINE([HAVE_ABE],[0],[Lacking ABE library])
+fi
+
+
gst=0
PKG_CHECK_MODULES(
@@ -1570,6 +1591,8 @@ src/gnsrecord/Makefile
src/hello/Makefile
src/identity/Makefile
src/identity/identity.conf
+src/credential/Makefile
+src/credential/credential.conf
src/include/Makefile
src/integration-tests/Makefile
src/json/Makefile
@@ -1635,6 +1658,8 @@ src/vpn/vpn.conf
src/zonemaster/Makefile
src/zonemaster/zonemaster.conf
src/rest/Makefile
+src/abe/Makefile
+src/identity-attribute/Makefile
src/identity-provider/Makefile
pkgconfig/Makefile
pkgconfig/gnunetarm.pc
diff --git a/contrib/Dockerfile b/contrib/Dockerfile
new file mode 100644
index 000000000..5a193a46d
--- /dev/null
+++ b/contrib/Dockerfile
@@ -0,0 +1,63 @@
+from fedora:26
+
+# Install the required build tools
+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
+
+WORKDIR /usr/src
+
+# Install gnurl from source at version gnurl-7.54.0
+RUN git clone https://git.taler.net/gnurl.git --branch gnurl-7.54.0
+WORKDIR /usr/src/gnurl
+RUN autoreconf -i
+RUN ./configure --enable-ipv6 --with-gnutls --without-libssh2 \
+--without-libmetalink --without-winidn --without-librtmp \
+--without-nghttp2 --without-nss --without-cyassl \
+--without-polarssl --without-ssl --without-winssl \
+--without-darwinssl --disable-sspi --disable-ntlm-wb --disable-ldap \
+--disable-rtsp --disable-dict --disable-telnet --disable-tftp \
+--disable-pop3 --disable-imap --disable-smtp --disable-gopher \
+--disable-file --disable-ftp --disable-smb
+RUN make install
+WORKDIR /usr/src
+
+RUN dnf -y install wget flex bison
+
+# Install libpbc
+RUN wget https://crypto.stanford.edu/pbc/files/pbc-0.5.14.tar.gz
+RUN tar xvzpf pbc-0.5.14.tar.gz
+WORKDIR /usr/src/pbc-0.5.14
+RUN ./configure --prefix=/usr
+RUN make install
+WORKDIR /usr/src
+
+RUN dnf -y install glib2-devel
+
+# Install libbswabe
+RUN git clone https://github.com/schanzen/libgabe.git
+WORKDIR /usr/src/libgabe
+RUN ./configure --prefix=/usr
+RUN make install
+
+# Install WebUI
+WORKDIR /usr/src/
+RUN git clone https://github.com/schanzen/gnunet-webui.git
+WORKDIR /usr/src/gnunet-webui
+RUN git checkout gnuidentity
+
+RUN mkdir /usr/src/gnunet
+WORKDIR /usr/src/gnunet
+ADD . .
+ARG NUM_JOBS
+RUN ./bootstrap
+RUN ./configure --prefix=/usr/local
+RUN make -j$NUM_JOBS
+RUN make install
+
+RUN groupadd gnunetdns
+RUN adduser --system -m --home-dir /var/lib/gnunet gnunet
+RUN chown gnunet:gnunet /var/lib/gnunet
+RUN echo '[arm]\nSYSTEM_ONLY = YES\nUSER_ONLY = NO\n' > /etc/gnunet.conf
+
+ADD docker-entrypoint.sh .
+
+CMD ["sh", "docker-entrypoint.sh"]
diff --git a/contrib/docker-entrypoint.sh b/contrib/docker-entrypoint.sh
new file mode 100644
index 000000000..807d86d6f
--- /dev/null
+++ b/contrib/docker-entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+gnunet-arm -s > $HOME/gnunet.log 2>&1
+exec bash \ No newline at end of file
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4a4cfbd96..2fcb74c09 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,15 +1,24 @@
+src/abe/abe.c
src/arm/arm_api.c
src/arm/arm_monitor_api.c
src/arm/gnunet-arm.c
src/arm/gnunet-service-arm.c
src/arm/mockup-service.c
+src/ats-tests/ats-testing-experiment.c
+src/ats-tests/ats-testing-log.c
+src/ats-tests/ats-testing-preferences.c
+src/ats-tests/ats-testing-traffic.c
+src/ats-tests/ats-testing.c
+src/ats-tests/gnunet-ats-sim.c
+src/ats-tests/gnunet-solver-eval.c
+src/ats-tool/gnunet-ats.c
src/ats/ats_api_connectivity.c
src/ats/ats_api_performance.c
src/ats/ats_api_scanner.c
src/ats/ats_api_scheduling.c
src/ats/gnunet-ats-solver-eval.c
-src/ats/gnunet-service-ats_addresses.c
src/ats/gnunet-service-ats.c
+src/ats/gnunet-service-ats_addresses.c
src/ats/gnunet-service-ats_connectivity.c
src/ats/gnunet-service-ats_normalization.c
src/ats/gnunet-service-ats_performance.c
@@ -20,14 +29,6 @@ src/ats/gnunet-service-ats_scheduling.c
src/ats/plugin_ats_mlp.c
src/ats/plugin_ats_proportional.c
src/ats/plugin_ats_ril.c
-src/ats-tests/ats-testing.c
-src/ats-tests/ats-testing-experiment.c
-src/ats-tests/ats-testing-log.c
-src/ats-tests/ats-testing-preferences.c
-src/ats-tests/ats-testing-traffic.c
-src/ats-tests/gnunet-ats-sim.c
-src/ats-tests/gnunet-solver-eval.c
-src/ats-tool/gnunet-ats.c
src/auction/gnunet-auction-create.c
src/auction/gnunet-auction-info.c
src/auction/gnunet-auction-join.c
@@ -39,8 +40,8 @@ src/block/plugin_block_test.c
src/cadet/cadet_api.c
src/cadet/cadet_test_lib.c
src/cadet/desirability_table.c
-src/cadet/gnunet-cadet.c
src/cadet/gnunet-cadet-profiler.c
+src/cadet/gnunet-cadet.c
src/cadet/gnunet-service-cadet.c
src/cadet/gnunet-service-cadet_channel.c
src/cadet/gnunet-service-cadet_connection.c
@@ -56,15 +57,15 @@ src/consensus/gnunet-service-consensus.c
src/consensus/plugin_block_consensus.c
src/conversation/conversation_api.c
src/conversation/conversation_api_call.c
-src/conversation/gnunet-conversation.c
src/conversation/gnunet-conversation-test.c
-src/conversation/gnunet_gst.c
-src/conversation/gnunet_gst_test.c
-src/conversation/gnunet-helper-audio-playback.c
+src/conversation/gnunet-conversation.c
src/conversation/gnunet-helper-audio-playback-gst.c
-src/conversation/gnunet-helper-audio-record.c
+src/conversation/gnunet-helper-audio-playback.c
src/conversation/gnunet-helper-audio-record-gst.c
+src/conversation/gnunet-helper-audio-record.c
src/conversation/gnunet-service-conversation.c
+src/conversation/gnunet_gst.c
+src/conversation/gnunet_gst_test.c
src/conversation/microphone.c
src/conversation/plugin_gnsrecord_conversation.c
src/conversation/speaker.c
@@ -75,6 +76,13 @@ src/core/gnunet-service-core.c
src/core/gnunet-service-core_kx.c
src/core/gnunet-service-core_sessions.c
src/core/gnunet-service-core_typemap.c
+src/credential/credential_api.c
+src/credential/credential_misc.c
+src/credential/credential_serialization.c
+src/credential/gnunet-credential.c
+src/credential/gnunet-service-credential.c
+src/credential/plugin_gnsrecord_credential.c
+src/credential/plugin_rest_credential.c
src/curl/curl.c
src/curl/curl_reschedule.c
src/datacache/datacache.c
@@ -94,7 +102,6 @@ src/dht/dht_api.c
src/dht/dht_test_lib.c
src/dht/gnunet-dht-get.c
src/dht/gnunet-dht-monitor.c
-src/dht/gnunet_dht_profiler.c
src/dht/gnunet-dht-put.c
src/dht/gnunet-service-dht.c
src/dht/gnunet-service-dht_clients.c
@@ -103,6 +110,7 @@ src/dht/gnunet-service-dht_hello.c
src/dht/gnunet-service-dht_neighbours.c
src/dht/gnunet-service-dht_nse.c
src/dht/gnunet-service-dht_routing.c
+src/dht/gnunet_dht_profiler.c
src/dht/plugin_block_dht.c
src/dns/dns_api.c
src/dns/dnsparser.c
@@ -117,8 +125,8 @@ src/dv/gnunet-dv.c
src/dv/gnunet-service-dv.c
src/dv/plugin_transport_dv.c
src/exit/gnunet-daemon-exit.c
-src/exit/gnunet-helper-exit.c
src/exit/gnunet-helper-exit-windows.c
+src/exit/gnunet-helper-exit.c
src/fragmentation/defragmentation.c
src/fragmentation/fragmentation.c
src/fs/fs_api.c
@@ -143,8 +151,8 @@ src/fs/gnunet-auto-share.c
src/fs/gnunet-daemon-fsprofiler.c
src/fs/gnunet-directory.c
src/fs/gnunet-download.c
-src/fs/gnunet-fs.c
src/fs/gnunet-fs-profiler.c
+src/fs/gnunet-fs.c
src/fs/gnunet-helper-fs-publish.c
src/fs/gnunet-publish.c
src/fs/gnunet-search.c
@@ -162,10 +170,10 @@ src/fs/plugin_block_fs.c
src/gns/gns_api.c
src/gns/gnunet-bcd.c
src/gns/gnunet-dns2gns.c
-src/gns/gnunet-gns.c
src/gns/gnunet-gns-helper-service-w32.c
src/gns/gnunet-gns-import.c
src/gns/gnunet-gns-proxy.c
+src/gns/gnunet-gns.c
src/gns/gnunet-service-gns.c
src/gns/gnunet-service-gns_interceptor.c
src/gns/gnunet-service-gns_resolver.c
@@ -174,41 +182,44 @@ src/gns/nss/nss_gns_query.c
src/gns/plugin_block_gns.c
src/gns/plugin_gnsrecord_gns.c
src/gns/plugin_rest_gns.c
+src/gns/w32nsp-install.c
+src/gns/w32nsp-resolve.c
+src/gns/w32nsp-uninstall.c
+src/gns/w32nsp.c
src/gnsrecord/gnsrecord.c
src/gnsrecord/gnsrecord_crypto.c
src/gnsrecord/gnsrecord_misc.c
src/gnsrecord/gnsrecord_serialization.c
src/gnsrecord/plugin_gnsrecord_dns.c
-src/gns/w32nsp.c
-src/gns/w32nsp-install.c
-src/gns/w32nsp-resolve.c
-src/gns/w32nsp-uninstall.c
src/hello/address.c
src/hello/gnunet-hello.c
src/hello/hello.c
src/hostlist/gnunet-daemon-hostlist.c
src/hostlist/gnunet-daemon-hostlist_client.c
src/hostlist/gnunet-daemon-hostlist_server.c
+src/identity-attribute/identity_attribute.c
+src/identity-attribute/plugin_identity_attribute_gnuid.c
+src/identity-provider/gnunet-idp.c
+src/identity-provider/gnunet-service-identity-provider.c
+src/identity-provider/identity_provider_api.c
+src/identity-provider/jwt.c
+src/identity-provider/plugin_gnsrecord_identity_provider.c
+src/identity-provider/plugin_identity_provider_sqlite.c
+src/identity-provider/plugin_rest_identity_provider.c
src/identity/gnunet-identity.c
src/identity/gnunet-service-identity.c
src/identity/identity_api.c
src/identity/identity_api_lookup.c
-src/identity/plugin_gnsrecord_identity.c
src/identity/plugin_rest_identity.c
-src/identity-provider/gnunet-identity-token.c
-src/identity-provider/gnunet-service-identity-provider.c
-src/identity-provider/identity_provider_api.c
-src/identity-provider/identity_token.c
-src/identity-provider/plugin_rest_identity_provider.c
+src/json/json.c
+src/json/json_generator.c
+src/json/json_helper.c
+src/json/json_mhd.c
src/jsonapi/jsonapi.c
src/jsonapi/jsonapi_document.c
src/jsonapi/jsonapi_error.c
src/jsonapi/jsonapi_relationship.c
src/jsonapi/jsonapi_resource.c
-src/json/json.c
-src/json/json_generator.c
-src/json/json_helper.c
-src/json/json_mhd.c
src/multicast/gnunet-multicast.c
src/multicast/gnunet-service-multicast.c
src/multicast/multicast_api.c
@@ -222,8 +233,8 @@ src/namecache/namecache_api.c
src/namecache/plugin_namecache_flat.c
src/namecache/plugin_namecache_postgres.c
src/namecache/plugin_namecache_sqlite.c
-src/namestore/gnunet-namestore.c
src/namestore/gnunet-namestore-fcfsd.c
+src/namestore/gnunet-namestore.c
src/namestore/gnunet-service-namestore.c
src/namestore/namestore_api.c
src/namestore/namestore_api_monitor.c
@@ -238,10 +249,10 @@ src/nat-auto/gnunet-service-nat-auto.c
src/nat-auto/gnunet-service-nat-auto_legacy.c
src/nat-auto/nat_auto_api.c
src/nat-auto/nat_auto_api_test.c
-src/nat/gnunet-helper-nat-client.c
src/nat/gnunet-helper-nat-client-windows.c
-src/nat/gnunet-helper-nat-server.c
+src/nat/gnunet-helper-nat-client.c
src/nat/gnunet-helper-nat-server-windows.c
+src/nat/gnunet-helper-nat-server.c
src/nat/gnunet-nat.c
src/nat/gnunet-service-nat.c
src/nat/gnunet-service-nat_externalip.c
@@ -250,15 +261,15 @@ src/nat/gnunet-service-nat_mini.c
src/nat/gnunet-service-nat_stun.c
src/nat/nat_api.c
src/nat/nat_api_stun.c
-src/nse/gnunet-nse.c
src/nse/gnunet-nse-profiler.c
+src/nse/gnunet-nse.c
src/nse/gnunet-service-nse.c
src/nse/nse_api.c
+src/peerinfo-tool/gnunet-peerinfo.c
+src/peerinfo-tool/gnunet-peerinfo_plugins.c
src/peerinfo/gnunet-service-peerinfo.c
src/peerinfo/peerinfo_api.c
src/peerinfo/peerinfo_api_notify.c
-src/peerinfo-tool/gnunet-peerinfo.c
-src/peerinfo-tool/gnunet-peerinfo_plugins.c
src/peerstore/gnunet-peerstore.c
src/peerstore/gnunet-service-peerstore.c
src/peerstore/peerstore_api.c
@@ -309,13 +320,13 @@ src/rps/gnunet-service-rps_custommap.c
src/rps/gnunet-service-rps_sampler.c
src/rps/gnunet-service-rps_sampler_elem.c
src/rps/gnunet-service-rps_view.c
-src/rps/rps_api.c
src/rps/rps-test_util.c
+src/rps/rps_api.c
src/scalarproduct/gnunet-scalarproduct.c
-src/scalarproduct/gnunet-service-scalarproduct_alice.c
-src/scalarproduct/gnunet-service-scalarproduct_bob.c
src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
+src/scalarproduct/gnunet-service-scalarproduct_alice.c
+src/scalarproduct/gnunet-service-scalarproduct_bob.c
src/scalarproduct/scalarproduct_api.c
src/secretsharing/gnunet-secretsharing-profiler.c
src/secretsharing/gnunet-service-secretsharing.c
@@ -342,15 +353,16 @@ src/statistics/gnunet-statistics.c
src/statistics/statistics_api.c
src/template/gnunet-service-template.c
src/template/gnunet-template.c
+src/testbed-logger/gnunet-service-testbed-logger.c
+src/testbed-logger/testbed_logger_api.c
src/testbed/generate-underlay-topology.c
src/testbed/gnunet-daemon-latency-logger.c
src/testbed/gnunet-daemon-testbed-blacklist.c
src/testbed/gnunet-daemon-testbed-underlay.c
src/testbed/gnunet-helper-testbed.c
-src/testbed/gnunet_mpi_test.c
src/testbed/gnunet-service-test-barriers.c
-src/testbed/gnunet-service-testbed_barriers.c
src/testbed/gnunet-service-testbed.c
+src/testbed/gnunet-service-testbed_barriers.c
src/testbed/gnunet-service-testbed_cache.c
src/testbed/gnunet-service-testbed_connectionpool.c
src/testbed/gnunet-service-testbed_cpustatus.c
@@ -358,20 +370,19 @@ src/testbed/gnunet-service-testbed_links.c
src/testbed/gnunet-service-testbed_meminfo.c
src/testbed/gnunet-service-testbed_oc.c
src/testbed/gnunet-service-testbed_peers.c
-src/testbed/gnunet_testbed_mpi_spawn.c
src/testbed/gnunet-testbed-profiler.c
-src/testbed-logger/gnunet-service-testbed-logger.c
-src/testbed-logger/testbed_logger_api.c
-src/testbed/testbed_api_barriers.c
+src/testbed/gnunet_mpi_test.c
+src/testbed/gnunet_testbed_mpi_spawn.c
src/testbed/testbed_api.c
+src/testbed/testbed_api_barriers.c
src/testbed/testbed_api_hosts.c
src/testbed/testbed_api_operations.c
src/testbed/testbed_api_peers.c
src/testbed/testbed_api_sd.c
src/testbed/testbed_api_services.c
src/testbed/testbed_api_statistics.c
-src/testbed/testbed_api_testbed.c
src/testbed/testbed_api_test.c
+src/testbed/testbed_api_testbed.c
src/testbed/testbed_api_topology.c
src/testbed/testbed_api_underlay.c
src/testing/gnunet-testing.c
@@ -380,34 +391,39 @@ src/testing/testing.c
src/topology/friends.c
src/topology/gnunet-daemon-topology.c
src/transport/gnunet-helper-transport-bluetooth.c
-src/transport/gnunet-helper-transport-wlan.c
src/transport/gnunet-helper-transport-wlan-dummy.c
-src/transport/gnunet-service-transport_ats.c
+src/transport/gnunet-helper-transport-wlan.c
src/transport/gnunet-service-transport.c
+src/transport/gnunet-service-transport_ats.c
src/transport/gnunet-service-transport_hello.c
src/transport/gnunet-service-transport_manipulation.c
src/transport/gnunet-service-transport_neighbours.c
src/transport/gnunet-service-transport_plugins.c
src/transport/gnunet-service-transport_validation.c
-src/transport/gnunet-transport.c
src/transport/gnunet-transport-certificate-creation.c
src/transport/gnunet-transport-profiler.c
src/transport/gnunet-transport-wlan-receiver.c
src/transport/gnunet-transport-wlan-sender.c
+src/transport/gnunet-transport.c
src/transport/plugin_transport_http_client.c
src/transport/plugin_transport_http_common.c
src/transport/plugin_transport_http_server.c
src/transport/plugin_transport_smtp.c
src/transport/plugin_transport_tcp.c
src/transport/plugin_transport_template.c
-src/transport/plugin_transport_udp_broadcasting.c
src/transport/plugin_transport_udp.c
+src/transport/plugin_transport_udp_broadcasting.c
src/transport/plugin_transport_unix.c
src/transport/plugin_transport_wlan.c
src/transport/tcp_connection_legacy.c
src/transport/tcp_server_legacy.c
src/transport/tcp_server_mst_legacy.c
src/transport/tcp_service_legacy.c
+src/transport/transport-testing-filenames.c
+src/transport/transport-testing-loggers.c
+src/transport/transport-testing-main.c
+src/transport/transport-testing-send.c
+src/transport/transport-testing.c
src/transport/transport_api_address_to_string.c
src/transport/transport_api_blacklist.c
src/transport/transport_api_core.c
@@ -416,11 +432,6 @@ src/transport/transport_api_manipulation.c
src/transport/transport_api_monitor_peers.c
src/transport/transport_api_monitor_plugins.c
src/transport/transport_api_offer_hello.c
-src/transport/transport-testing.c
-src/transport/transport-testing-filenames.c
-src/transport/transport-testing-loggers.c
-src/transport/transport-testing-main.c
-src/transport/transport-testing-send.c
src/tun/regex.c
src/tun/tun.c
src/util/bandwidth.c
@@ -434,10 +445,11 @@ src/util/configuration_loader.c
src/util/container_bloomfilter.c
src/util/container_heap.c
src/util/container_meta_data.c
-src/util/container_multihashmap32.c
src/util/container_multihashmap.c
+src/util/container_multihashmap32.c
src/util/container_multipeermap.c
src/util/container_multishortmap.c
+src/util/crypto_abe.c
src/util/crypto_crc.c
src/util/crypto_ecc.c
src/util/crypto_ecc_dlog.c
@@ -454,8 +466,8 @@ src/util/crypto_symmetric.c
src/util/disk.c
src/util/getopt.c
src/util/getopt_helpers.c
-src/util/gnunet-config.c
src/util/gnunet-config-diff.c
+src/util/gnunet-config.c
src/util/gnunet-ecc.c
src/util/gnunet-helper-w32-console.c
src/util/gnunet-resolver.c
@@ -486,8 +498,8 @@ src/util/time.c
src/util/w32cat.c
src/util/win.c
src/util/winproc.c
-src/vpn/gnunet-helper-vpn.c
src/vpn/gnunet-helper-vpn-windows.c
+src/vpn/gnunet-helper-vpn.c
src/vpn/gnunet-service-vpn.c
src/vpn/gnunet-vpn.c
src/vpn/vpn_api.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 7f1a00177..6d0284157 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,11 +12,12 @@ endif
if HAVE_EXPERIMENTAL
EXP_DIR = \
rps
-endif
-
-if HAVE_JSON
-if HAVE_MHD
- PROVIDER_DIR = identity-provider
+# dv (FTBFS)
+if HAVE_ABE
+ EXP_DIR += abe \
+ credential \
+ identity-attribute \
+ identity-provider
endif
endif
@@ -128,7 +129,6 @@ SUBDIRS = \
psyc \
social \
$(AUCTION_DIR) \
- $(EXP_DIR) \
- $(PROVIDER_DIR)
+ $(EXP_DIR)
endif
diff --git a/src/abe/Makefile.am b/src/abe/Makefile.am
new file mode 100644
index 000000000..308e6c67c
--- /dev/null
+++ b/src/abe/Makefile.am
@@ -0,0 +1,50 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/gnunet
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+dist_pkgcfg_DATA = \
+ abe.conf
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+ XLIB = -lgcov
+endif
+
+libgnunetabe_la_SOURCES = abe.c
+
+libgnunetabe_la_LIBADD = \
+ $(GCLIBADD)\
+ $(LIBGCRYPT_LIBS) \
+ $(LTLIBICONV) \
+ $(LTLIBINTL) \
+ $(ABE_LIBADD) \
+ -lgabe \
+ -lpbc \
+ -lglib-2.0 \
+ -lltdl $(Z_LIBS) -lunistring $(XLIB)
+
+libgnunetabe_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS) \
+ -version-info 1:0:0
+
+lib_LTLIBRARIES = libgnunetabe.la
+
+if ENABLE_TEST_RUN
+AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
+TESTS = $(check_PROGRAMS)
+endif
+
+check_PROGRAMS = test_cpabe
+
+test_cpabe_SOURCES = \
+ test_cpabe.c
+test_cpabe_LDADD = \
+ libgnunetabe.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+check_PROGRAMS += \
+ test_cpabe
diff --git a/src/abe/abe.c b/src/abe/abe.c
new file mode 100644
index 000000000..3f1f6dc5b
--- /dev/null
+++ b/src/abe/abe.c
@@ -0,0 +1,499 @@
+/*
+ This file is part of GNUnet. Copyright (C) 2001-2018 Christian Grothoff
+ (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+/**
+ * @file abe/abe.c
+ * @brief functions for Attribute-Based Encryption
+ * @author Martin Schanzenbach
+ */
+
+
+#include "platform.h"
+#include <pbc/pbc.h>
+#include <gabe.h>
+
+#include "gnunet_crypto_lib.h"
+#include "gnunet_abe_lib.h"
+
+struct GNUNET_ABE_AbeMasterKey
+{
+ gabe_pub_t* pub;
+ gabe_msk_t* msk;
+};
+
+struct GNUNET_ABE_AbeKey
+{
+ gabe_pub_t* pub;
+ gabe_prv_t* prv;
+};
+
+static int
+init_aes( element_t k, int enc,
+ gcry_cipher_hd_t* handle,
+ struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+ unsigned char* iv)
+{
+ int rc;
+ int key_len;
+ unsigned char* key_buf;
+
+ key_len = element_length_in_bytes(k) < 33 ? 3 : element_length_in_bytes(k);
+ key_buf = (unsigned char*) malloc(key_len);
+ element_to_bytes(key_buf, k);
+
+ memcpy (key->aes_key, key_buf, GNUNET_CRYPTO_AES_KEY_LENGTH);
+ GNUNET_assert (0 ==
+ gcry_cipher_open (handle, GCRY_CIPHER_AES256,
+ GCRY_CIPHER_MODE_CFB, 0));
+ rc = gcry_cipher_setkey (*handle,
+ key->aes_key,
+ sizeof (key->aes_key));
+ GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
+ memset (iv, 0, 16); //TODO make reasonable
+ rc = gcry_cipher_setiv (*handle,
+ iv,
+ 16);
+ GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
+
+ free(key_buf);
+ return rc;
+}
+
+static int
+aes_128_cbc_encrypt( char* pt,
+ int size,
+ element_t k,
+ char **ct )
+{
+ gcry_cipher_hd_t handle;
+ struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+ unsigned char iv[16];
+ char* buf;
+ int padding;
+ int buf_size;
+ uint8_t len[4];
+ init_aes(k, 1, &handle, &skey, iv);
+
+ /* TODO make less crufty */
+
+ /* stuff in real length (big endian) before padding */
+ len[0] = (size & 0xff000000)>>24;
+ len[1] = (size & 0xff0000)>>16;
+ len[2] = (size & 0xff00)>>8;
+ len[3] = (size & 0xff)>>0;
+ padding = 16 - ((4+size) % 16);
+ buf_size = 4 + size + padding;
+ buf = GNUNET_malloc (buf_size);
+ GNUNET_memcpy (buf, len, 4);
+ GNUNET_memcpy (buf+4, pt, size);
+ *ct = GNUNET_malloc (buf_size);
+
+ GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf, buf_size));
+ gcry_cipher_close (handle);
+ //AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
+ GNUNET_free (buf);
+ return buf_size;
+}
+
+static int
+aes_128_cbc_decrypt( char* ct,
+ int size,
+ element_t k,
+ char **pt )
+{
+ struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+ gcry_cipher_hd_t handle;
+ unsigned char iv[16];
+ char* tmp;
+ uint32_t len;
+
+ init_aes(k, 1, &handle, &skey, iv);
+
+ tmp = GNUNET_malloc (size);
+
+ //AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
+ GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size));
+ gcry_cipher_close (handle);
+ /* TODO make less crufty */
+
+ /* get real length */
+ len = 0;
+ len = len
+ | ((tmp[0])<<24) | ((tmp[1])<<16)
+ | ((tmp[2])<<8) | ((tmp[3])<<0);
+ /* truncate any garbage from the padding */
+ *pt = GNUNET_malloc (len);
+ GNUNET_memcpy (*pt, tmp+4, len);
+ GNUNET_free (tmp);
+ return len;
+}
+
+/**
+ * @ingroup abe
+ * Create a new CP-ABE master key. Caller must free return value.
+ *
+ * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
+ */
+struct GNUNET_ABE_AbeMasterKey*
+GNUNET_ABE_cpabe_create_master_key (void)
+{
+ struct GNUNET_ABE_AbeMasterKey* key;
+ key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
+ gabe_setup(&key->pub, &key->msk);
+ GNUNET_assert (NULL != key->pub);
+ GNUNET_assert (NULL != key->msk);
+ return key;
+}
+
+/**
+ * @ingroup abe
+ * Delete a CP-ABE master key.
+ *
+ * @param key the master key
+ * @return fresh private key; free using #GNUNET_free
+ */
+void
+GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key)
+{
+ gabe_msk_free (key->msk);
+ gabe_pub_free (key->pub);
+ //GNUNET_free (key->msk);
+ //gabe_msk_free (key->msk); //For some reason free of pub implicit?
+ GNUNET_free (key);
+}
+
+/**
+ * @ingroup abe
+ * Create a new CP-ABE key. Caller must free return value.
+ *
+ * @param key the master key
+ * @param attrs the attributes to append to the key
+ * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
+ */
+struct GNUNET_ABE_AbeKey*
+GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
+ char **attrs)
+{
+ struct GNUNET_ABE_AbeKey *prv_key;
+ int size;
+ char *tmp;
+
+ prv_key = GNUNET_new (struct GNUNET_ABE_AbeKey);
+ prv_key->prv = gabe_keygen(key->pub, key->msk, attrs);
+ size = gabe_pub_serialize(key->pub, &tmp);
+ prv_key->pub = gabe_pub_unserialize(tmp, size);
+ GNUNET_free (tmp);
+ GNUNET_assert (NULL != prv_key->prv);
+ return prv_key;
+}
+
+/**
+ * @ingroup abe
+ * Delete a CP-ABE key.
+ *
+ * @param key the key to delete
+ * @param delete_pub GNUNE_YES if the public key should also be freed (bug in gabe)
+ * @return fresh private key; free using #GNUNET_free
+ */
+void
+GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
+ int delete_pub)
+{
+ //Memory management in gabe is buggy
+ gabe_prv_free (key->prv);
+ if (GNUNET_YES == delete_pub)
+ gabe_pub_free (key->pub);
+ GNUNET_free (key);
+}
+
+static ssize_t
+write_cpabe (void **result,
+ uint32_t file_len,
+ char* cph_buf,
+ int cph_buf_len,
+ char* aes_buf,
+ int aes_buf_len)
+{
+ char *ptr;
+ uint32_t *len;
+
+ *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
+ ptr = *result;
+ len = (uint32_t*) ptr;
+ *len = htonl (file_len);
+ ptr += 4;
+ len = (uint32_t*) ptr;
+ *len = htonl (aes_buf_len);
+ ptr += 4;
+ memcpy (ptr, aes_buf, aes_buf_len);
+ ptr += aes_buf_len;
+ len = (uint32_t*) ptr;
+ *len = htonl (cph_buf_len);
+ ptr += 4;
+ memcpy (ptr, cph_buf, cph_buf_len);
+ return 12 + cph_buf_len + aes_buf_len;
+}
+
+static ssize_t
+read_cpabe (const void *data,
+ char** cph_buf,
+ int *cph_buf_len,
+ char** aes_buf,
+ int *aes_buf_len)
+{
+ int buf_len;
+ char *ptr;
+ uint32_t *len;
+
+ ptr = (char*)data;
+ len = (uint32_t*)ptr;
+ buf_len = ntohl (*len);
+ ptr += 4;
+ len = (uint32_t*)ptr;
+ *aes_buf_len = ntohl (*len);
+ ptr += 4;
+ *aes_buf = GNUNET_malloc (*aes_buf_len);
+ memcpy(*aes_buf, ptr, *aes_buf_len);
+ ptr += *aes_buf_len;
+ len = (uint32_t*)ptr;
+ *cph_buf_len = ntohl (*len);
+ ptr += 4;
+ *cph_buf = GNUNET_malloc (*cph_buf_len);
+ memcpy(*cph_buf, ptr, *cph_buf_len);
+
+ return buf_len;
+}
+
+/**
+ * @ingroup abe
+ * Encrypt a block using sessionkey.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param policy the ABE policy
+ * @param key the key used to encrypt
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_encrypt (const void *block,
+ size_t size,
+ const char *policy,
+ const struct GNUNET_ABE_AbeMasterKey *key,
+ void **result)
+{
+ gabe_cph_t* cph;
+ char* plt;
+ char* cph_buf;
+ char* aes_buf;
+ element_t m;
+ int cph_buf_len;
+ int aes_buf_len;
+ ssize_t result_len;
+
+ if( !(cph = gabe_enc(key->pub, m, (char*)policy)) )
+ return GNUNET_SYSERR;
+ cph_buf_len = gabe_cph_serialize(cph,
+ &cph_buf);
+ gabe_cph_free(cph);
+ GNUNET_free (cph);
+ plt = GNUNET_memdup (block, size);
+ aes_buf_len = aes_128_cbc_encrypt(plt, size, m, &aes_buf);
+ GNUNET_free (plt);
+ element_clear(m);
+ result_len = write_cpabe(result, size, cph_buf, cph_buf_len, aes_buf, aes_buf_len);
+ GNUNET_free(cph_buf);
+ GNUNET_free(aes_buf);
+ return result_len;
+}
+
+/**
+ * @ingroup abe
+ * Decrypt a block using the ABE key.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param key the key used to decrypt
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_decrypt (const void *block,
+ size_t size,
+ const struct GNUNET_ABE_AbeKey *key,
+ void **result)
+{
+ char* aes_buf;
+ char* cph_buf;
+ gabe_cph_t* cph;
+ element_t m;
+ int cph_buf_size;
+ int aes_buf_size;
+ int plt_len;
+
+ read_cpabe(block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
+ cph = gabe_cph_unserialize(key->pub, cph_buf, cph_buf_size);
+ if( !gabe_dec(key->pub, key->prv, cph, m) ) {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s\n", gabe_error());
+ GNUNET_free (aes_buf);
+ GNUNET_free (cph_buf);
+ gabe_cph_free(cph);
+ GNUNET_free (cph);
+ element_clear (m);
+ return GNUNET_SYSERR;
+ }
+ gabe_cph_free(cph);
+ GNUNET_free (cph);
+ plt_len = aes_128_cbc_decrypt(aes_buf, aes_buf_size, m, (char**)result);
+ GNUNET_free (cph_buf);
+ GNUNET_free (aes_buf);
+ element_clear (m);
+ //freeing is buggy in gabe
+ //gabe_prv_free (prv);
+ //gabe_pub_free (pub);
+ return plt_len;
+}
+
+/**
+ * @ingroup abe
+ * Serialize an ABE key.
+ *
+ * @param key the key to serialize
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
+ void **result)
+{
+ ssize_t len;
+ char *pub;
+ char *prv;
+ int pub_len;
+ int prv_len;
+
+ pub_len = gabe_pub_serialize (key->pub, &pub);
+ prv_len = gabe_prv_serialize (key->prv, &prv);
+
+ len = pub_len + prv_len + 12;
+ write_cpabe (result, len, pub, pub_len, prv, prv_len);
+
+ GNUNET_free (pub);
+ GNUNET_free (prv);
+
+ return len;
+}
+
+/**
+ * @ingroup abe
+ * Deserialize a serialized ABE key.
+ *
+ * @param data the data to deserialize
+ * @param len the length of the data.
+ * @return the ABE key. NULL of unsuccessful
+ */
+struct GNUNET_ABE_AbeKey*
+GNUNET_ABE_cpabe_deserialize_key (const void *data,
+ size_t len)
+{
+ struct GNUNET_ABE_AbeKey *key;
+ char *pub;
+ char *prv;
+ int prv_len;
+ int pub_len;
+
+ key = GNUNET_new (struct GNUNET_ABE_AbeKey);
+ read_cpabe (data,
+ &pub,
+ &pub_len,
+ &prv,
+ &prv_len);
+ key->pub = gabe_pub_unserialize (pub, pub_len);
+ key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
+
+ GNUNET_free (pub);
+ GNUNET_free (prv);
+ return key;
+}
+
+/**
+ * @ingroup abe
+ * Serialize an ABE master key.
+ *
+ * @param key the key to serialize
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_serialize_master_key (const struct GNUNET_ABE_AbeMasterKey *key,
+ void **result)
+{
+ ssize_t len;
+ char *pub;
+ char *msk;
+ int pub_len;
+ int msk_len;
+
+ pub_len = gabe_pub_serialize (key->pub, &pub);
+ msk_len = gabe_msk_serialize (key->msk, &msk);
+
+ len = pub_len + msk_len + 12;
+ write_cpabe (result, len, pub, pub_len, msk, msk_len);
+
+ GNUNET_free (pub);
+ GNUNET_free (msk);
+
+ return len;
+}
+
+/**
+ * @ingroup abe
+ * Deserialize an ABE master key.
+ *
+ * @param data the data to deserialize
+ * @param len the length of the data.
+ * @return the ABE key. NULL of unsuccessful
+ */
+struct GNUNET_ABE_AbeMasterKey*
+GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
+ size_t len)
+{
+ struct GNUNET_ABE_AbeMasterKey *key;
+ char *msk;
+ char *pub;
+ int msk_len;
+ int pub_len;
+
+ key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
+ read_cpabe (data,
+ &pub,
+ &pub_len,
+ &msk,
+ &msk_len);
+ key->pub = gabe_pub_unserialize (pub, pub_len);
+ key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
+
+ GNUNET_free (pub);
+ GNUNET_free (msk);
+
+ return key;
+}
diff --git a/src/abe/test_cpabe.c b/src/abe/test_cpabe.c
new file mode 100644
index 000000000..9b2062b23
--- /dev/null
+++ b/src/abe/test_cpabe.c
@@ -0,0 +1,87 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2002, 2003, 2004, 2006 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+/**
+ * @author Martin Schanzenbach
+ * @file util/test_crypto_abe.c
+ * @brief test for ABE ciphers
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_abe_lib.h"
+
+#define TESTSTRING "Hello World!"
+
+static int
+testAbecipher ()
+{
+ struct GNUNET_ABE_AbeMasterKey *msk;
+ struct GNUNET_ABE_AbeKey *key;
+ char *result;
+ char **attrs;
+ int size;
+ char *res;
+ msk = GNUNET_ABE_cpabe_create_master_key ();
+ size = GNUNET_ABE_cpabe_encrypt (TESTSTRING, strlen (TESTSTRING) + 1,
+ "testattr", //Policy
+ msk,
+ (void*)&result);
+ GNUNET_assert (-1 != size);
+ attrs = GNUNET_malloc (2 * sizeof (char*));
+ attrs[0] = "testattr";
+ attrs[1] = NULL;
+ key = GNUNET_ABE_cpabe_create_key (msk,
+ attrs);
+
+ size = GNUNET_ABE_cpabe_decrypt (result, size,
+ key,
+ (void*)&res);
+ if (strlen (TESTSTRING) + 1 != size)
+ {
+ printf ("abeciphertest failed: decryptBlock returned %d\n", size);
+ return 1;
+ }
+ if (0 != strcmp (res, TESTSTRING))
+ {
+ printf ("abeciphertest failed: %s != %s\n", res, TESTSTRING);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int failureCount = 0;
+
+ GNUNET_log_setup ("test-crypto-abe", "WARNING", NULL);
+ failureCount += testAbecipher ();
+
+ if (failureCount != 0)
+ {
+ printf ("%d TESTS FAILED!\n", failureCount);
+ return -1;
+ }
+ return 0;
+}
+
+/* end of test_crypto_aes.c */
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
new file mode 100644
index 000000000..ca11c5e4f
--- /dev/null
+++ b/src/credential/Makefile.am
@@ -0,0 +1,112 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+EXTRA_DIST = \
+ test_credential_defaults.conf \
+ test_credential_lookup.conf
+
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+endif
+
+pkgcfgdir = $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+plugindir = $(libdir)/gnunet
+
+pkgcfg_DATA = \
+ credential.conf
+
+
+# /usr/lib - compiles a layer which can be used to be communicagte with the service
+lib_LTLIBRARIES = \
+ libgnunetcredential.la
+
+# /usr/lib/gnunet/libexec - Business logic . Separate process
+libexec_PROGRAMS = \
+ gnunet-service-credential
+
+bin_PROGRAMS = \
+ gnunet-credential
+
+plugin_LTLIBRARIES = \
+ libgnunet_plugin_gnsrecord_credential.la
+
+
+if HAVE_MHD
+if HAVE_JSON
+plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la
+endif
+endif
+
+
+gnunet_credential_SOURCES = \
+ gnunet-credential.c
+gnunet_credential_LDADD = \
+ libgnunetcredential.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(GN_LIBINTL)
+
+
+libgnunet_plugin_gnsrecord_credential_la_SOURCES = \
+ plugin_gnsrecord_credential.c
+libgnunet_plugin_gnsrecord_credential_la_LIBADD = \
+ libgnunetcredential.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(LTLIBINTL)
+libgnunet_plugin_gnsrecord_credential_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+
+gnunet_service_credential_SOURCES = \
+ gnunet-service-credential.c
+gnunet_service_credential_LDADD = \
+ libgnunetcredential.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(GN_LIBINTL)
+
+
+libgnunetcredential_la_SOURCES = \
+ credential_api.c \
+ credential_serialization.c \
+ credential_misc.c
+libgnunetcredential_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+libgnunetcredential_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS)
+
+
+libgnunet_plugin_rest_credential_la_SOURCES = \
+ plugin_rest_credential.c
+libgnunet_plugin_rest_credential_la_LIBADD = \
+ libgnunetcredential.la \
+ $(top_builddir)/src/rest/libgnunetrest.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
+ $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+ $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_credential_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+check_SCRIPTS = \
+ test_credential_issue.sh \
+ test_credential_verify_simple.sh \
+ test_credential_verify.sh \
+ test_credential_verify_and.sh
+
+if ENABLE_TEST_RUN
+if HAVE_SQLITE
+ AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
+ TESTS = $(check_SCRIPTS)
+endif
+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 @@
+[credential]
+BINARY = gnunet-service-credential
+UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-credential.sock
+USER_SERVICE = YES
+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..66a4636fc
--- /dev/null
+++ b/src/credential/credential.h
@@ -0,0 +1,221 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2012-2013 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+/**
+ * @file credential/credential.h
+ * @brief IPC messages between CREDENTIAL API and CREDENTIAL service
+ * @author Martin Schanzenbach
+ */
+#ifndef CREDENTIAL_H
+#define CREDENTIAL_H
+
+#include "gnunet_credential_service.h"
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message from client to Credential service to collect credentials.
+ */
+struct CollectMessage
+{
+ /**
+ * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Subject public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key;
+
+ /**
+ * Trust anchor
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Length of the issuer attribute
+ */
+ uint16_t issuer_attribute_len;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /* Followed by the zero-terminated attribute */
+
+};
+
+
+/**
+ * Message from client to Credential service to verify attributes.
+ */
+struct VerifyMessage
+{
+ /**
+ * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Subject public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Trust anchor
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Number of credentials
+ */
+ uint32_t c_count;
+
+ /**
+ * Length of the issuer attribute
+ */
+ uint16_t issuer_attribute_len;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /* Followed by the zero-terminated attribute and credentials to look up */
+
+};
+
+
+/**
+ * Message from CREDENTIAL service to client: new results.
+ */
+struct DelegationChainResultMessage
+{
+ /**
+ * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * Indicates if credential has been found at all
+ */
+ uint32_t cred_found GNUNET_PACKED;
+
+ /**
+ * The number of delegations in the response
+ */
+ uint32_t d_count GNUNET_PACKED;
+
+ /**
+ * The number of credentials in the response
+ */
+ uint32_t c_count GNUNET_PACKED;
+
+ /* followed by ad_count GNUNET_CREDENTIAL_RecordData structs*/
+
+};
+
+struct DelegationRecordData
+{
+ /**
+ * Subject key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Subject attributes
+ */
+ uint32_t subject_attribute_len GNUNET_PACKED;
+};
+
+
+struct ChainEntry
+{
+ /**
+ * Issuer key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Subject key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Issuer attributes
+ */
+ uint32_t issuer_attribute_len GNUNET_PACKED;
+
+ /**
+ * Subject attributes
+ */
+ uint32_t subject_attribute_len GNUNET_PACKED;
+};
+
+
+struct CredentialEntry
+{
+
+ /**
+ * The signature for this credential by the issuer
+ */
+ struct GNUNET_CRYPTO_EcdsaSignature signature;
+
+ /**
+ * Signature meta
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+ /**
+ * Public key of the issuer
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Public key of the subject this credential was issued to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Expiration time of this credential
+ */
+ uint64_t expiration GNUNET_PACKED;
+
+ /**
+ * Issuer attribute length
+ */
+ uint32_t issuer_attribute_len;
+
+ /**
+ * Followed by the attribute string
+ */
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
+
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
new file mode 100644
index 000000000..677cb9ad4
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,511 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2009-2013, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file credential/credential_api.c
+ * @brief library to access the CREDENTIAL service
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_arm_service.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
+#include "credential_serialization.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_identity_service.h"
+
+
+#define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
+
+/**
+ * Handle to a verify request
+ */
+struct GNUNET_CREDENTIAL_Request
+{
+
+ /**
+ * DLL
+ */
+ struct GNUNET_CREDENTIAL_Request *next;
+
+ /**
+ * DLL
+ */
+ struct GNUNET_CREDENTIAL_Request *prev;
+
+ /**
+ * handle to credential service
+ */
+ struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
+ /**
+ * processor to call on verify result
+ */
+ GNUNET_CREDENTIAL_CredentialResultProcessor verify_proc;
+
+ /**
+ * @e verify_proc closure
+ */
+ void *proc_cls;
+
+ /**
+ * Envelope with the message for this queue entry.
+ */
+ struct GNUNET_MQ_Envelope *env;
+
+ /**
+ * request id
+ */
+ uint32_t r_id;
+
+};
+
+
+/**
+ * Connection to the CREDENTIAL service.
+ */
+struct GNUNET_CREDENTIAL_Handle
+{
+
+ /**
+ * Configuration to use.
+ */
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Connection to service (if available).
+ */
+ struct GNUNET_MQ_Handle *mq;
+
+ /**
+ * Head of linked list of active verify requests.
+ */
+ struct GNUNET_CREDENTIAL_Request *request_head;
+
+ /**
+ * Tail of linked list of active verify requests.
+ */
+ struct GNUNET_CREDENTIAL_Request *request_tail;
+
+ /**
+ * Reconnect task
+ */
+ struct GNUNET_SCHEDULER_Task *reconnect_task;
+
+ /**
+ * How long do we wait until we try to reconnect?
+ */
+ struct GNUNET_TIME_Relative reconnect_backoff;
+
+ /**
+ * Request Id generator. Incremented by one for each request.
+ */
+ uint32_t r_id_gen;
+
+};
+
+
+/**
+ * Reconnect to CREDENTIAL service.
+ *
+ * @param handle the handle to the CREDENTIAL service
+ */
+static void
+reconnect (struct GNUNET_CREDENTIAL_Handle *handle);
+
+
+/**
+ * Reconnect to CREDENTIAL
+ *
+ * @param cls the handle
+ */
+static void
+reconnect_task (void *cls)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = cls;
+
+ handle->reconnect_task = NULL;
+ reconnect (handle);
+}
+
+
+/**
+ * Disconnect from service and then reconnect.
+ *
+ * @param handle our handle
+ */
+static void
+force_reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
+{
+ GNUNET_MQ_destroy (handle->mq);
+ handle->mq = NULL;
+ handle->reconnect_backoff
+ = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
+ handle->reconnect_task
+ = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
+ &reconnect_task,
+ handle);
+}
+
+
+/**
+ * Generic error handler, called with the appropriate error code and
+ * the same closure specified at the creation of the message queue.
+ * Not every message queue implementation supports an error handler.
+ *
+ * @param cls closure with the `struct GNUNET_CREDENTIAL_Handle *`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+ enum GNUNET_MQ_Error error)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = cls;
+
+ force_reconnect (handle);
+}
+
+/**
+ * Check validity of message received from the CREDENTIAL service
+ *
+ * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
+ * @param vr_msg the incoming message
+ */
+static int
+check_result (void *cls,
+ const struct DelegationChainResultMessage *vr_msg)
+{
+ //TODO
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handler for messages received from the CREDENTIAL service
+ *
+ * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
+ * @param vr_msg the incoming message
+ */
+static void
+handle_result (void *cls,
+ const struct DelegationChainResultMessage *vr_msg)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = cls;
+ uint32_t r_id = ntohl (vr_msg->id);
+ struct GNUNET_CREDENTIAL_Request *vr;
+ size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg);
+ uint32_t d_count = ntohl (vr_msg->d_count);
+ uint32_t c_count = ntohl (vr_msg->c_count);
+ struct GNUNET_CREDENTIAL_Delegation d_chain[d_count];
+ struct GNUNET_CREDENTIAL_Credential creds[c_count];
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc;
+ void *proc_cls;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received verify reply from CREDENTIAL service\n");
+ for (vr = handle->request_head; NULL != vr; vr = vr->next)
+ if (vr->r_id == r_id)
+ break;
+ if (NULL == vr)
+ return;
+ proc = vr->verify_proc;
+ proc_cls = vr->proc_cls;
+ GNUNET_CONTAINER_DLL_remove (handle->request_head,
+ handle->request_tail,
+ vr);
+ GNUNET_MQ_discard (vr->env);
+ GNUNET_free (vr);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen,
+ (const char*) &vr_msg[1],
+ d_count,
+ d_chain,
+ c_count,
+ creds));
+ if (GNUNET_NO == ntohl (vr_msg->cred_found))
+ {
+ proc (proc_cls,
+ 0,
+ NULL,
+ 0,
+ NULL); // TODO
+ } else {
+ proc (proc_cls,
+ d_count,
+ d_chain,
+ c_count,
+ creds);
+ }
+}
+
+
+/**
+ * Reconnect to CREDENTIAL service.
+ *
+ * @param handle the handle to the CREDENTIAL service
+ */
+static void
+reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
+{
+ struct GNUNET_MQ_MessageHandler handlers[] = {
+ GNUNET_MQ_hd_var_size (result,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
+ struct DelegationChainResultMessage,
+ handle),
+ GNUNET_MQ_hd_var_size (result,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT,
+ struct DelegationChainResultMessage,
+ handle),
+ GNUNET_MQ_handler_end ()
+ };
+ struct GNUNET_CREDENTIAL_Request *vr;
+
+ GNUNET_assert (NULL == handle->mq);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to connect to CREDENTIAL\n");
+ handle->mq = GNUNET_CLIENT_connect (handle->cfg,
+ "credential",
+ handlers,
+ &mq_error_handler,
+ handle);
+ if (NULL == handle->mq)
+ return;
+ for (vr = handle->request_head; NULL != vr; vr = vr->next)
+ GNUNET_MQ_send_copy (handle->mq,
+ vr->env);
+}
+
+
+/**
+ * Initialize the connection with the CREDENTIAL service.
+ *
+ * @param cfg configuration to use
+ * @return handle to the CREDENTIAL service, or NULL on error
+ */
+struct GNUNET_CREDENTIAL_Handle *
+GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle;
+
+ handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
+ handle->cfg = cfg;
+ reconnect (handle);
+ if (NULL == handle->mq)
+ {
+ GNUNET_free (handle);
+ return NULL;
+ }
+ return handle;
+}
+
+
+/**
+ * Shutdown connection with the CREDENTIAL service.
+ *
+ * @param handle handle of the CREDENTIAL connection to stop
+ */
+void
+GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle)
+{
+ if (NULL != handle->mq)
+ {
+ GNUNET_MQ_destroy (handle->mq);
+ handle->mq = NULL;
+ }
+ if (NULL != handle->reconnect_task)
+ {
+ GNUNET_SCHEDULER_cancel (handle->reconnect_task);
+ handle->reconnect_task = NULL;
+ }
+ GNUNET_assert (NULL == handle->request_head);
+ GNUNET_free (handle);
+}
+
+
+/**
+ * Cancel pending verify request
+ *
+ * @param lr the verify request to cancel
+ */
+void
+GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *lr)
+{
+ struct GNUNET_CREDENTIAL_Handle *handle = lr->credential_handle;
+
+ GNUNET_CONTAINER_DLL_remove (handle->request_head,
+ handle->request_tail,
+ lr);
+ GNUNET_MQ_discard (lr->env);
+ GNUNET_free (lr);
+}
+
+
+/**
+ * Performs attribute collection.
+ * Collects all credentials of subject to fulfill the
+ * attribute, if possible
+ *
+ * @param handle handle to the Credential service
+ * @param issuer_key the issuer public key
+ * @param issuer_attribute the issuer attribute
+ * @param subject_key the subject public key
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const char *issuer_attribute,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+ void *proc_cls)
+{
+ /* IPC to shorten credential names, return shorten_handle */
+ struct CollectMessage *c_msg;
+ struct GNUNET_CREDENTIAL_Request *vr;
+ size_t nlen;
+
+ if (NULL == issuer_attribute)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ //DEBUG LOG
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to collect `%s' in CREDENTIAL\n",
+ issuer_attribute);
+ nlen = strlen (issuer_attribute) + 1;
+ if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
+ vr->credential_handle = handle;
+ vr->verify_proc = proc;
+ vr->proc_cls = proc_cls;
+ vr->r_id = handle->r_id_gen++;
+ vr->env = GNUNET_MQ_msg_extra (c_msg,
+ nlen,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT);
+ c_msg->id = htonl (vr->r_id);
+ c_msg->subject_key = *subject_key;
+ c_msg->issuer_key = *issuer_key;
+ c_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
+ GNUNET_memcpy (&c_msg[1],
+ issuer_attribute,
+ strlen (issuer_attribute));
+ GNUNET_CONTAINER_DLL_insert (handle->request_head,
+ handle->request_tail,
+ vr);
+ if (NULL != handle->mq)
+ GNUNET_MQ_send_copy (handle->mq,
+ vr->env);
+ return vr;
+}
+/**
+ * Performs attribute verification.
+ * Checks if there is a delegation chain from
+ * attribute ``issuer_attribute'' issued by the issuer
+ * with public key ``issuer_key'' maps to the attribute
+ * ``subject_attribute'' claimed by the subject with key
+ * ``subject_key''
+ *
+ * @param handle handle to the Credential service
+ * @param issuer_key the issuer public key
+ * @param issuer_attribute the issuer attribute
+ * @param subject_key the subject public key
+ * @param credential_count number of credentials provided
+ * @param credentials subject credentials
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const char *issuer_attribute,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
+ uint32_t credential_count,
+ const struct GNUNET_CREDENTIAL_Credential *credentials,
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+ void *proc_cls)
+{
+ /* IPC to shorten credential names, return shorten_handle */
+ struct VerifyMessage *v_msg;
+ struct GNUNET_CREDENTIAL_Request *vr;
+ size_t nlen;
+ size_t clen;
+
+ if (NULL == issuer_attribute || NULL == credentials)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
+ credentials);
+
+ //DEBUG LOG
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to verify `%s' in CREDENTIAL\n",
+ issuer_attribute);
+ nlen = strlen (issuer_attribute) + 1 + clen;
+ if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
+ vr->credential_handle = handle;
+ vr->verify_proc = proc;
+ vr->proc_cls = proc_cls;
+ vr->r_id = handle->r_id_gen++;
+ vr->env = GNUNET_MQ_msg_extra (v_msg,
+ nlen,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
+ v_msg->id = htonl (vr->r_id);
+ v_msg->subject_key = *subject_key;
+ v_msg->c_count = htonl(credential_count);
+ v_msg->issuer_key = *issuer_key;
+ v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
+ GNUNET_memcpy (&v_msg[1],
+ issuer_attribute,
+ strlen (issuer_attribute));
+ GNUNET_CREDENTIAL_credentials_serialize (credential_count,
+ credentials,
+ clen,
+ ((char*)&v_msg[1])
+ + strlen (issuer_attribute) + 1);
+ GNUNET_CONTAINER_DLL_insert (handle->request_head,
+ handle->request_tail,
+ vr);
+ if (NULL != handle->mq)
+ GNUNET_MQ_send_copy (handle->mq,
+ vr->env);
+ return vr;
+}
+
+/* end of credential_api.c */
diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c
new file mode 100644
index 000000000..c94c33919
--- /dev/null
+++ b/src/credential/credential_misc.c
@@ -0,0 +1,168 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2009-2013, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_misc.c
+ * @brief Misc API for credentials
+ *
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
+#include <inttypes.h>
+
+char*
+GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ char *cred_str;
+ char *subject_pkey;
+ char *issuer_pkey;
+ char *signature;
+
+
+ subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
+ issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
+ GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
+ sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+ &signature);
+ GNUNET_asprintf (&cred_str,
+ "%s.%s -> %s | %s | %"SCNu64,
+ issuer_pkey,
+ cred->issuer_attribute,
+ subject_pkey,
+ signature,
+ cred->expiration.abs_value_us);
+ GNUNET_free (subject_pkey);
+ GNUNET_free (issuer_pkey);
+ GNUNET_free (signature);
+ return cred_str;
+}
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_from_string (const char* s)
+{
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
+ if (enclen % 5 > 0)
+ enclen += 5 - enclen % 5;
+ enclen /= 5; /* 260/5 = 52 */
+ char subject_pkey[enclen + 1];
+ char issuer_pkey[enclen + 1];
+ char name[253 + 1];
+ char signature[256]; //TODO max payload size
+
+ struct GNUNET_CRYPTO_EcdsaSignature *sig;
+ struct GNUNET_TIME_Absolute etime_abs;
+
+ if (5 != SSCANF (s,
+ "%52s.%253s -> %52s | %s | %"SCNu64,
+ issuer_pkey,
+ name,
+ subject_pkey,
+ signature,
+ &etime_abs.abs_value_us))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unable to parse CRED record string `%s'\n"),
+ s);
+ return NULL;
+ }
+ cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1);
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
+ strlen (subject_pkey),
+ &cred->subject_key);
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
+ strlen (issuer_pkey),
+ &cred->issuer_key);
+ GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature,
+ strlen (signature),
+ (char**)&sig));
+ cred->signature = *sig;
+ cred->expiration = etime_abs;
+ GNUNET_free (sig);
+ GNUNET_memcpy (&cred[1],
+ name,
+ strlen (name)+1);
+ cred->issuer_attribute_len = strlen ((char*)&cred[1]);
+ cred->issuer_attribute = (char*)&cred[1];
+ return cred;
+}
+
+/**
+ * Issue an attribute to a subject
+ *
+ * @param issuer the ego that should be used to issue the attribute
+ * @param subject the subject of the attribute
+ * @param attribute the name of the attribute
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Credential *
+GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
+ struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
+ const char *attribute,
+ struct GNUNET_TIME_Absolute *expiration)
+{
+ struct CredentialEntry *crd;
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ size_t size;
+
+ size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
+ crd = GNUNET_malloc (size);
+ cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1);
+ crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+
+ crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+ GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
+ &crd->issuer_key);
+ crd->subject_key = *subject;
+ crd->expiration = GNUNET_htonll (expiration->abs_value_us);
+ crd->issuer_attribute_len = htonl (strlen (attribute)+1);
+ GNUNET_memcpy ((char*)&crd[1],
+ attribute,
+ strlen (attribute)+1);
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_sign (issuer,
+ &crd->purpose,
+ &crd->signature))
+ {
+ GNUNET_break (0);
+ GNUNET_free (crd);
+ return NULL;
+ }
+ cred->signature = crd->signature;
+ cred->expiration = *expiration;
+ GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
+ &cred->issuer_key);
+
+ cred->subject_key = *subject;
+ GNUNET_memcpy (&cred[1],
+ attribute,
+ strlen (attribute)+1);
+ cred->issuer_attribute = (char*)&cred[1];
+ GNUNET_free (crd);
+ return cred;
+}
+
+
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 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2012-2013 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+/**
+ * @file credential/credential_misc.h
+ * @brief Credential helper functions
+ */
+#ifndef CREDENTIAL_MISC_H
+#define CREDENTIAL_MISC_H
+
+
+
+char*
+GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred);
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_from_string (const char* str);
+
+#endif
diff --git a/src/credential/credential_serialization.c b/src/credential/credential_serialization.c
new file mode 100644
index 000000000..1d23bb08c
--- /dev/null
+++ b/src/credential/credential_serialization.c
@@ -0,0 +1,460 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2009-2013, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_serialization.c
+ * @brief API to serialize and deserialize delegation chains
+ * and credentials
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain
+ *
+ * @param ds_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
+ const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
+{
+ unsigned int i;
+ size_t ret;
+
+ ret = sizeof (struct DelegationRecordData) * (ds_count);
+
+ for (i=0; i<ds_count;i++)
+ {
+ GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
+ ret += dsr[i].subject_attribute_len;
+ }
+ return ret;
+}
+
+/**
+ * Serizalize the given delegation chain entries and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
+ size_t dest_size,
+ char *dest)
+{
+ struct DelegationRecordData rec;
+ unsigned int i;
+ size_t off;
+
+ off = 0;
+ for (i=0;i<d_count;i++)
+ {
+ rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
+ rec.subject_key = dsr[i].subject_key;
+ if (off + sizeof (rec) > dest_size)
+ return -1;
+ GNUNET_memcpy (&dest[off],
+ &rec,
+ sizeof (rec));
+ off += sizeof (rec);
+ if (0 == dsr[i].subject_attribute_len)
+ continue;
+ if (off + dsr[i].subject_attribute_len > dest_size)
+ return -1;
+ GNUNET_memcpy (&dest[off],
+ dsr[i].subject_attribute,
+ dsr[i].subject_attribute_len);
+ off += dsr[i].subject_attribute_len;
+ }
+ return off;
+}
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized delegation chain and cred
+ * @param src the serialized data
+ * @param d_count the number of delegation chain entries
+ * @param dsr where to put the delegation chain entries
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
+ const char *src,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_DelegationSet *dsr)
+{
+ struct DelegationRecordData rec;
+ unsigned int i;
+ size_t off;
+
+ off = 0;
+ for (i=0;i<d_count;i++)
+ {
+ if (off + sizeof (rec) > len)
+ return GNUNET_SYSERR;
+ GNUNET_memcpy (&rec, &src[off], sizeof (rec));
+ dsr[i].subject_key = rec.subject_key;
+ off += sizeof (rec);
+ dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
+ if (off + dsr[i].subject_attribute_len > len)
+ return GNUNET_SYSERR;
+ dsr[i].subject_attribute = (char*)&src[off];
+ off += dsr[i].subject_attribute_len;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd)
+{
+ unsigned int i;
+ size_t ret;
+
+ ret = sizeof (struct CredentialEntry) * (c_count);
+
+ for (i=0; i<c_count;i++)
+ {
+ GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
+ ret += cd[i].issuer_attribute_len;
+ }
+ return ret;
+}
+/**
+ * Serizalize the given credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd,
+ size_t dest_size,
+ char *dest)
+{
+ struct CredentialEntry c_rec;
+ unsigned int i;
+ size_t off;
+
+ off = 0;
+ for (i=0;i<c_count;i++)
+ {
+ c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
+ c_rec.issuer_key = cd[i].issuer_key;
+ c_rec.subject_key = cd[i].subject_key;
+ c_rec.signature = cd[i].signature;
+ c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+ c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+ c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
+ if (off + sizeof (c_rec) > dest_size)
+ return -1;
+ GNUNET_memcpy (&dest[off],
+ &c_rec,
+ sizeof (c_rec));
+ off += sizeof (c_rec);
+ if (off + cd[i].issuer_attribute_len > dest_size)
+ return -1;
+ GNUNET_memcpy (&dest[off],
+ cd[i].issuer_attribute,
+ cd[i].issuer_attribute_len);
+ off += cd[i].issuer_attribute_len;
+ }
+
+ return off;
+}
+
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized creds
+ * @param src the serialized data
+ * @param c_count the number of credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+ const char *src,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cd)
+{
+ struct CredentialEntry c_rec;
+ unsigned int i;
+ size_t off;
+
+ off = 0;
+ for (i=0;i<c_count;i++)
+ {
+ if (off + sizeof (c_rec) > len)
+ return GNUNET_SYSERR;
+ GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
+ cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
+ cd[i].issuer_key = c_rec.issuer_key;
+ cd[i].subject_key = c_rec.subject_key;
+ cd[i].signature = c_rec.signature;
+ cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
+ off += sizeof (c_rec);
+ if (off + cd[i].issuer_attribute_len > len)
+ return GNUNET_SYSERR;
+ cd[i].issuer_attribute = &src[off];
+ off += cd[i].issuer_attribute_len;
+ }
+ return GNUNET_OK;
+}
+
+
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd)
+{
+ unsigned int i;
+ size_t ret;
+
+ ret = sizeof (struct ChainEntry) * (d_count);
+
+ for (i=0; i<d_count;i++)
+ {
+ GNUNET_assert ((ret +
+ dd[i].issuer_attribute_len +
+ dd[i].subject_attribute_len) >= ret);
+ ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
+ }
+ return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
+ return ret;
+}
+
+/**
+ * Serizalize the given delegation chain entries and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd,
+ size_t dest_size,
+ char *dest)
+{
+ struct ChainEntry rec;
+ unsigned int i;
+ size_t off;
+
+ off = 0;
+ for (i=0;i<d_count;i++)
+ {
+ rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
+ rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
+ rec.issuer_key = dd[i].issuer_key;
+ rec.subject_key = dd[i].subject_key;
+ if (off + sizeof (rec) > dest_size)
+ return -1;
+ GNUNET_memcpy (&dest[off],
+ &rec,
+ sizeof (rec));
+ off += sizeof (rec);
+ if (off + dd[i].issuer_attribute_len > dest_size)
+ return -1;
+ GNUNET_memcpy (&dest[off],
+ dd[i].issuer_attribute,
+ dd[i].issuer_attribute_len);
+ off += dd[i].issuer_attribute_len;
+ if (0 == dd[i].subject_attribute_len)
+ continue;
+ if (off + dd[i].subject_attribute_len > dest_size)
+ return -1;
+ GNUNET_memcpy (&dest[off],
+ dd[i].subject_attribute,
+ dd[i].subject_attribute_len);
+ off += dd[i].subject_attribute_len;
+ }
+ return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
+ cd,
+ dest_size-off,
+ &dest[off]);
+}
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized delegation chain and cred
+ * @param src the serialized data
+ * @param d_count the number of delegation chain entries
+ * @param dd where to put the delegation chain entries
+ * @param c_count the number of credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
+ const char *src,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cd)
+{
+ struct ChainEntry rec;
+ unsigned int i;
+ size_t off;
+
+ off = 0;
+ for (i=0;i<d_count;i++)
+ {
+ if (off + sizeof (rec) > len)
+ return GNUNET_SYSERR;
+ GNUNET_memcpy (&rec, &src[off], sizeof (rec));
+ dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
+ dd[i].issuer_key = rec.issuer_key;
+ dd[i].subject_key = rec.subject_key;
+ off += sizeof (rec);
+ if (off + dd[i].issuer_attribute_len > len)
+ return GNUNET_SYSERR;
+ dd[i].issuer_attribute = &src[off];
+ off += dd[i].issuer_attribute_len;
+ dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
+ if (off + dd[i].subject_attribute_len > len)
+ return GNUNET_SYSERR;
+ dd[i].subject_attribute = &src[off];
+ off += dd[i].subject_attribute_len;
+ }
+ return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
+ &src[off],
+ c_count,
+ cd);
+}
+int
+GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
+ char **data)
+{
+ size_t size;
+ struct CredentialEntry *cdata;
+
+ size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
+ *data = GNUNET_malloc (size);
+ cdata = (struct CredentialEntry*)*data;
+ cdata->subject_key = cred->subject_key;
+ cdata->issuer_key = cred->issuer_key;
+ cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
+ cdata->signature = cred->signature;
+ cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
+ cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+ cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+ GNUNET_memcpy (&cdata[1],
+ cred->issuer_attribute,
+ strlen (cred->issuer_attribute));
+
+ if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
+ &cdata->purpose,
+ &cdata->signature,
+ &cdata->issuer_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid credential\n");
+ //return NULL;
+ }
+ return size;
+}
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_deserialize (const char* data,
+ size_t data_size)
+{
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ struct CredentialEntry *cdata;
+ char *issuer_attribute;
+
+ if (data_size < sizeof (struct CredentialEntry))
+ return NULL;
+ cdata = (struct CredentialEntry*)data;
+ if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
+ &cdata->purpose,
+ &cdata->signature,
+ &cdata->issuer_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid credential\n");
+ //return NULL;
+ }
+ issuer_attribute = (char*)&cdata[1];
+
+ cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
+
+ cred->issuer_key = cdata->issuer_key;
+ cred->subject_key = cdata->subject_key;
+ GNUNET_memcpy (&cred[1],
+ issuer_attribute,
+ ntohl (cdata->issuer_attribute_len));
+ cred->signature = cdata->signature;
+ cred->issuer_attribute = (char*)&cred[1];
+ cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
+ return cred;
+}
+
+
+/* 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 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2009-2013, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_serialization.h
+ * @brief API to serialize and deserialize delegation chains
+ * and credentials
+ * @author Martin Schanzenbach
+ */
+#ifndef CREDENTIAL_SERIALIZATION_H
+#define CREDENTIAL_SERIALIZATION_H
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_service.h"
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation record
+ *
+ * @param ds_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_Delegation
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
+ const struct GNUNET_CREDENTIAL_DelegationSet *dsr);
+
+/**
+ * Serizalize the given delegation record entries
+ *
+ * @param d_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_Delegation
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
+ size_t dest_size,
+ char *dest);
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized delegation recird
+ * @param src the serialized data
+ * @param d_count the number of delegation chain entries
+ * @param dsr where to put the delegation chain entries
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
+ const char *src,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_DelegationSet *dsr);
+
+ /**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+ size_t
+ GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd);
+
+ /**
+ * Serizalize the given delegation chain entries and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ ssize_t
+ GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
+ const struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd,
+ size_t dest_size,
+ char *dest);
+
+
+ /**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized delegation chain and cred
+ * @param src the serialized data
+ * @param d_count the number of delegation chain entries
+ * @param dd where to put the delegation chain entries
+ * @param c_count number of credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+ int
+ GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
+ const char *src,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dd,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cd);
+ size_t
+ GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd);
+
+ssize_t
+GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
+ const struct GNUNET_CREDENTIAL_Credential *cd,
+ size_t dest_size,
+ char *dest);
+
+
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+ const char *src,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cd);
+
+
+int
+GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
+ char **data);
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_deserialize (const char* data,
+ size_t data_size);
+#endif
+/* end of credential_serialization.h */
diff --git a/src/credential/gnunet-credential.c b/src/credential/gnunet-credential.c
new file mode 100644
index 000000000..03f959b95
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,588 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2012-2013 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file gnunet-credential.c
+ * @brief command line tool to access command line Credential service
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include <gnunet_util_lib.h>
+#include <gnunet_credential_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include "credential_misc.h"
+#include "credential_serialization.h"
+
+/**
+ * Configuration we are using.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * EgoLookup
+ */
+static struct GNUNET_IDENTITY_EgoLookup *el;
+
+/**
+ * Handle to Credential service.
+ */
+static struct GNUNET_CREDENTIAL_Handle *credential;
+
+/**
+ * Desired timeout for the lookup (default is no timeout).
+ */
+static struct GNUNET_TIME_Relative timeout;
+
+/**
+ * Handle to verify request
+ */
+static struct GNUNET_CREDENTIAL_Request *verify_request;
+
+/**
+ * Handle to collect request
+ */
+static struct GNUNET_CREDENTIAL_Request *collect_request;
+
+/**
+ * Task scheduled to handle timeout.
+ */
+static struct GNUNET_SCHEDULER_Task *tt;
+
+/**
+ * Subject pubkey string
+ */
+static char *subject_key;
+
+/**
+ * Subject credential string
+ */
+static char *subject_credential;
+
+/**
+ * Credential TTL
+ */
+static char *expiration;
+
+/**
+ * Subject key
+ */
+struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
+
+/**
+ * Issuer key
+ */
+struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
+
+
+/**
+ * Issuer pubkey string
+ */
+static char *issuer_key;
+
+/**
+ * ego
+ */
+static char *ego_name;
+
+/**
+ * Issuer attribute
+ */
+static char *issuer_attr;
+
+/**
+ * Verify mode
+ */
+static int verify;
+
+/**
+ * Issue mode
+ */
+static int create_cred;
+
+/**
+ * Collect mode
+ */
+static int collect;
+
+/**
+ * Task run on shutdown. Cleans up everything.
+ *
+ * @param cls unused
+ */
+static void
+do_shutdown (void *cls)
+{
+ if (NULL != verify_request)
+ {
+ GNUNET_CREDENTIAL_request_cancel (verify_request);
+ verify_request = NULL;
+ }
+ if (NULL != credential)
+ {
+ GNUNET_CREDENTIAL_disconnect (credential);
+ credential = NULL;
+ }
+ if (NULL != tt)
+ {
+ GNUNET_SCHEDULER_cancel (tt);
+ tt = NULL;
+ }
+}
+
+
+/**
+ * Task run on timeout. Triggers shutdown.
+ *
+ * @param cls unused
+ */
+static void
+do_timeout (void *cls)
+{
+ tt = NULL;
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+static void
+handle_collect_result (void *cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dc,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ int i;
+ char* line;
+
+ verify_request = NULL;
+ if (NULL != cred)
+ {
+ for (i=0;i<c_count;i++)
+ {
+ line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
+ printf ("%s\n",
+ line);
+ GNUNET_free (line);
+ }
+ }
+
+
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+static void
+handle_verify_result (void *cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dc,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ int i;
+ char* iss_key;
+ char* sub_key;
+
+ verify_request = NULL;
+ if (NULL == cred)
+ printf ("Failed.\n");
+ else
+ {
+ printf("Delegation Chain:\n");
+ for (i=0;i<d_count;i++)
+ {
+ iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
+ sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
+ if (0 != dc[i].subject_attribute_len)
+ {
+ printf ("(%d) %s.%s <- %s.%s\n", i,
+ iss_key, dc[i].issuer_attribute,
+ sub_key, dc[i].subject_attribute);
+ } else {
+ printf ("(%d) %s.%s <- %s\n", i,
+ iss_key, dc[i].issuer_attribute,
+ sub_key);
+ }
+ GNUNET_free (iss_key);
+ GNUNET_free (sub_key);
+ }
+ printf("\nCredentials:\n");
+ for (i=0;i<c_count;i++)
+ {
+ iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
+ sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].subject_key);
+ printf ("%s.%s <- %s\n",
+ iss_key, cred[i].issuer_attribute,
+ sub_key);
+ GNUNET_free (iss_key);
+ GNUNET_free (sub_key);
+
+ }
+ printf ("Successful.\n");
+ }
+
+
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+/**
+ * Callback invoked from identity service with ego information.
+ * An @a ego of NULL means the ego was not found.
+ *
+ * @param cls closure with the configuration
+ * @param ego an ego known to identity service, or NULL
+ */
+static void
+identity_cb (void *cls,
+ const struct GNUNET_IDENTITY_Ego *ego)
+{
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
+ struct GNUNET_CREDENTIAL_Credential *crd;
+ struct GNUNET_TIME_Absolute etime_abs;
+ struct GNUNET_TIME_Relative etime_rel;
+ char *res;
+
+ el = NULL;
+ if (NULL == ego)
+ {
+ if (NULL != ego_name)
+ {
+ fprintf (stderr,
+ _("Ego `%s' not known to identity service\n"),
+ ego_name);
+ }
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ if (GNUNET_YES == collect)
+ {
+
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
+ strlen (issuer_key),
+ &issuer_pkey))
+ {
+ fprintf (stderr,
+ _("Issuer public key `%s' is not well-formed\n"),
+ issuer_key);
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+
+ collect_request = GNUNET_CREDENTIAL_collect(credential,
+ &issuer_pkey,
+ issuer_attr, //TODO argument
+ privkey,
+ &handle_collect_result,
+ NULL);
+ return;
+ }
+
+ //Else issue
+
+ if (NULL == expiration)
+ {
+ fprintf (stderr,
+ "Please specify a TTL\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
+ &etime_rel))
+ {
+ etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
+ } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
+ &etime_abs))
+ {
+ fprintf (stderr,
+ "%s is not a valid ttl!\n",
+ expiration);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+
+ privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+ GNUNET_free_non_null (ego_name);
+ ego_name = NULL;
+ crd = GNUNET_CREDENTIAL_credential_issue (privkey,
+ &subject_pkey,
+ issuer_attr,
+ &etime_abs);
+
+ res = GNUNET_CREDENTIAL_credential_to_string (crd);
+ GNUNET_free (crd);
+ printf ("%s\n", res);
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+
+ cfg = c;
+
+
+ tt = GNUNET_SCHEDULER_add_delayed (timeout,
+ &do_timeout, NULL);
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
+
+ if (GNUNET_YES == collect) {
+ if (NULL == issuer_key)
+ {
+ fprintf (stderr,
+ _("Issuer public key not well-formed\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+
+ }
+
+ credential = GNUNET_CREDENTIAL_connect (cfg);
+
+ if (NULL == credential)
+ {
+ fprintf (stderr,
+ _("Failed to connect to CREDENTIAL\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ if (NULL == issuer_attr)
+ {
+ fprintf (stderr,
+ _("You must provide issuer the attribute\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+
+ if (NULL == ego_name)
+ {
+ fprintf (stderr,
+ _("ego required\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+
+ }
+ el = GNUNET_IDENTITY_ego_lookup (cfg,
+ ego_name,
+ &identity_cb,
+ (void *) cfg);
+ return;
+
+ }
+
+ if (NULL == subject_key)
+ {
+ fprintf (stderr,
+ _("Subject public key needed\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
+ strlen (subject_key),
+ &subject_pkey))
+ {
+ fprintf (stderr,
+ _("Subject public key `%s' is not well-formed\n"),
+ subject_key);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_YES == verify) {
+ if (NULL == issuer_key)
+ {
+ fprintf (stderr,
+ _("Issuer public key not well-formed\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
+ strlen (issuer_key),
+ &issuer_pkey))
+ {
+ fprintf (stderr,
+ _("Issuer public key `%s' is not well-formed\n"),
+ issuer_key);
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ credential = GNUNET_CREDENTIAL_connect (cfg);
+
+ if (NULL == credential)
+ {
+ fprintf (stderr,
+ _("Failed to connect to CREDENTIAL\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ if (NULL == issuer_attr || NULL == subject_credential)
+ {
+ fprintf (stderr,
+ _("You must provide issuer and subject attributes\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+
+ //Subject credentials are comma separated
+ char *tmp = GNUNET_strdup (subject_credential);
+ char *tok = strtok (tmp, ",");
+ if (NULL == tok)
+ {
+ fprintf (stderr,
+ "Invalid subject credentials\n");
+ GNUNET_free (tmp);
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ int count = 1;
+ int i;
+ while (NULL != (tok = strtok(NULL, ",")))
+ count++;
+ struct GNUNET_CREDENTIAL_Credential credentials[count];
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ GNUNET_free (tmp);
+ tmp = GNUNET_strdup (subject_credential);
+ tok = strtok (tmp, ",");
+ for (i=0;i<count;i++)
+ {
+ cred = GNUNET_CREDENTIAL_credential_from_string (tok);
+ GNUNET_memcpy (&credentials[i],
+ cred,
+ sizeof (struct GNUNET_CREDENTIAL_Credential));
+ credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
+ tok = strtok(NULL, ",");
+ GNUNET_free (cred);
+ }
+
+ verify_request = GNUNET_CREDENTIAL_verify(credential,
+ &issuer_pkey,
+ issuer_attr, //TODO argument
+ &subject_pkey,
+ count,
+ credentials,
+ &handle_verify_result,
+ NULL);
+ for (i=0;i<count;i++)
+ {
+ GNUNET_free ((char*)credentials[i].issuer_attribute);
+ }
+ } else if (GNUNET_YES == create_cred) {
+ if (NULL == ego_name)
+ {
+ fprintf (stderr,
+ _("Issuer ego required\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+
+ }
+ el = GNUNET_IDENTITY_ego_lookup (cfg,
+ ego_name,
+ &identity_cb,
+ (void *) cfg);
+ return;
+ } else {
+ fprintf (stderr,
+ _("Please specify name to lookup, subject key and issuer key!\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ }
+ return;
+}
+
+
+/**
+ * The main function for gnunet-gns.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_option_flag ('I',
+ "issue",
+ gettext_noop ("create credential"),
+ &create_cred),
+ GNUNET_GETOPT_option_flag ('V',
+ "verify",
+ gettext_noop ("verify credential against attribute"),
+ &verify),
+ GNUNET_GETOPT_option_string ('s',
+ "subject",
+ "PKEY",
+ gettext_noop ("The public key of the subject to lookup the credential for"),
+ &subject_key),
+ GNUNET_GETOPT_option_string ('b',
+ "credential",
+ "CRED",
+ gettext_noop ("The name of the credential presented by the subject"),
+ &subject_credential),
+ GNUNET_GETOPT_option_string ('i',
+ "issuer",
+ "PKEY",
+ gettext_noop ("The public key of the authority to verify the credential against"),
+ &issuer_key),
+ GNUNET_GETOPT_option_string ('e',
+ "ego",
+ "EGO",
+ gettext_noop ("The ego to use"),
+ &ego_name),
+ GNUNET_GETOPT_option_string ('a',
+ "attribute",
+ "ATTR",
+ gettext_noop ("The issuer attribute to verify against or to issue"),
+ &issuer_attr),
+ GNUNET_GETOPT_option_string ('T',
+ "ttl",
+ "EXP",
+ gettext_noop ("The time to live for the credential"),
+ &expiration),
+ GNUNET_GETOPT_option_flag ('g',
+ "collect",
+ gettext_noop ("collect credentials"),
+ &collect),
+ GNUNET_GETOPT_OPTION_END
+ };
+ int ret;
+
+ timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+ if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+ return 2;
+
+ GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
+ ret =
+ (GNUNET_OK ==
+ GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
+ _("GNUnet credential resolver tool"),
+ options,
+ &run, NULL)) ? 0 : 1;
+ GNUNET_free ((void*) argv);
+ return ret;
+}
+
+/* end of gnunet-credential.c */
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c
new file mode 100644
index 000000000..be88839e9
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1160 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2011-2013 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file credential/gnunet-service-credential.c
+ * @brief GNUnet Credential Service (main service)
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_statistics_service.h"
+#include "credential.h"
+#include "credential_serialization.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+
+#include <gnunet_dnsparser_lib.h>
+#include <gnunet_identity_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_namestore_service.h>
+#include <gnunet_gns_service.h>
+
+
+#define GNUNET_CREDENTIAL_MAX_LENGTH 255
+
+struct VerifyRequestHandle;
+
+struct DelegationSetQueueEntry;
+
+
+struct DelegationChainEntry
+{
+ /**
+ * DLL
+ */
+ struct DelegationChainEntry *next;
+
+ /**
+ * DLL
+ */
+ struct DelegationChainEntry *prev;
+
+ /**
+ * The issuer
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * The subject
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * The issued attribute
+ */
+ char *issuer_attribute;
+
+ /**
+ * The delegated attribute
+ */
+ char *subject_attribute;
+};
+
+/**
+ * DLL for record
+ */
+struct CredentialRecordEntry
+{
+ /**
+ * DLL
+ */
+ struct CredentialRecordEntry *next;
+
+ /**
+ * DLL
+ */
+ struct CredentialRecordEntry *prev;
+
+ /**
+ * Number of references in delegation chains
+ */
+ uint32_t refcount;
+
+ /**
+ * Payload
+ */
+ struct GNUNET_CREDENTIAL_Credential *credential;
+};
+
+/**
+ * DLL used for delegations
+ * Used for OR delegations
+ */
+struct DelegationQueueEntry
+{
+ /**
+ * DLL
+ */
+ struct DelegationQueueEntry *next;
+
+ /**
+ * DLL
+ */
+ struct DelegationQueueEntry *prev;
+
+ /**
+ * Sets under this Queue
+ */
+ struct DelegationSetQueueEntry *set_entries_head;
+
+ /**
+ * Sets under this Queue
+ */
+ struct DelegationSetQueueEntry *set_entries_tail;
+
+ /**
+ * Parent set
+ */
+ struct DelegationSetQueueEntry *parent_set;
+
+ /**
+ * Required solutions
+ */
+ uint32_t required_solutions;
+};
+
+/**
+ * DLL for delegation sets
+ * Used for AND delegation set
+ */
+struct DelegationSetQueueEntry
+{
+ /**
+ * DLL
+ */
+ struct DelegationSetQueueEntry *next;
+
+ /**
+ * DLL
+ */
+ struct DelegationSetQueueEntry *prev;
+
+ /**
+ * GNS handle
+ */
+ struct GNUNET_GNS_LookupRequest *lookup_request;
+
+ /**
+ * Verify handle
+ */
+ struct VerifyRequestHandle *handle;
+
+ /**
+ * Parent attribute delegation
+ */
+ struct DelegationQueueEntry *parent;
+
+ /**
+ * Issuer key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
+
+ /**
+ * Queue entries of this set
+ */
+ struct DelegationQueueEntry *queue_entries_head;
+
+ /**
+ * Queue entries of this set
+ */
+ struct DelegationQueueEntry *queue_entries_tail;
+
+ /**
+ * Parent QueueEntry
+ */
+ struct DelegationQueueEntry *parent_queue_entry;
+
+ /**
+ * Issuer attribute delegated to
+ */
+ char *issuer_attribute;
+
+ /**
+ * The current attribute to look up
+ */
+ char *lookup_attribute;
+
+ /**
+ * Trailing attribute context
+ */
+ char *attr_trailer;
+
+ /**
+ * Still to resolve delegation as string
+ */
+ char *unresolved_attribute_delegation;
+
+ /**
+ * The delegation chain entry
+ */
+ struct DelegationChainEntry *delegation_chain_entry;
+
+};
+
+
+/**
+ * Handle to a lookup operation from api
+ */
+struct VerifyRequestHandle
+{
+
+ /**
+ * We keep these in a DLL.
+ */
+ struct VerifyRequestHandle *next;
+
+ /**
+ * We keep these in a DLL.
+ */
+ struct VerifyRequestHandle *prev;
+
+ /**
+ * Handle to the requesting client
+ */
+ struct GNUNET_SERVICE_Client *client;
+
+ /**
+ * GNS handle
+ */
+ struct GNUNET_GNS_LookupRequest *lookup_request;
+
+ /**
+ * Size of delegation tree
+ */
+ uint32_t delegation_chain_size;
+
+ /**
+ * Children of this attribute
+ */
+ struct DelegationChainEntry *delegation_chain_head;
+
+ /**
+ * Children of this attribute
+ */
+ struct DelegationChainEntry *delegation_chain_tail;
+
+ /**
+ * Issuer public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Issuer attribute
+ */
+ char *issuer_attribute;
+
+ /**
+ * Subject public key
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Credential DLL
+ */
+ struct CredentialRecordEntry *cred_chain_head;
+
+ /**
+ * Credential DLL
+ */
+ struct CredentialRecordEntry *cred_chain_tail;
+
+ /**
+ * Credential DLL size
+ */
+ uint32_t cred_chain_size;
+
+ /**
+ * Root Delegation Set
+ */
+ struct DelegationSetQueueEntry *root_set;
+
+ /**
+ * Current Delegation Pointer
+ */
+ struct DelegationQueueEntry *current_delegation;
+
+ /**
+ * request id
+ */
+ uint32_t request_id;
+
+ /**
+ * Pending lookups
+ */
+ uint64_t pending_lookups;
+
+ /**
+ * Credential iterator
+ */
+ struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
+
+ /**
+ * Collect task
+ */
+ struct GNUNET_SCHEDULER_Task *collect_next_task;
+
+};
+
+
+/**
+ * Head of the DLL.
+ */
+static struct VerifyRequestHandle *vrh_head;
+
+/**
+ * Tail of the DLL.
+ */
+static struct VerifyRequestHandle *vrh_tail;
+
+/**
+ * Handle to the statistics service
+ */
+static struct GNUNET_STATISTICS_Handle *statistics;
+
+/**
+ * Handle to GNS service.
+ */
+static struct GNUNET_GNS_Handle *gns;
+
+
+/**
+ * Handle to namestore service
+ */
+static struct GNUNET_NAMESTORE_Handle *namestore;
+
+static void
+cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
+{
+ struct DelegationQueueEntry *dq_entry;
+ struct DelegationSetQueueEntry *child;
+
+ if (NULL == ds_entry)
+ return;
+
+ for (dq_entry = ds_entry->queue_entries_head;
+ NULL != dq_entry;
+ dq_entry = ds_entry->queue_entries_head)
+ {
+ GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
+ ds_entry->queue_entries_tail,
+ dq_entry);
+ for (child = dq_entry->set_entries_head;
+ NULL != child;
+ child = dq_entry->set_entries_head)
+ {
+ GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
+ dq_entry->set_entries_tail,
+ child);
+ cleanup_delegation_set (child);
+ }
+ GNUNET_free (dq_entry);
+ }
+ GNUNET_free_non_null (ds_entry->issuer_key);
+ GNUNET_free_non_null (ds_entry->lookup_attribute);
+ GNUNET_free_non_null (ds_entry->issuer_attribute);
+ GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation);
+ GNUNET_free_non_null (ds_entry->attr_trailer);
+ if (NULL != ds_entry->lookup_request)
+ {
+ GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
+ ds_entry->lookup_request = NULL;
+ }
+ if (NULL != ds_entry->delegation_chain_entry)
+ {
+ GNUNET_free_non_null (ds_entry->delegation_chain_entry->subject_attribute);
+ GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute);
+ GNUNET_free (ds_entry->delegation_chain_entry);
+ }
+ GNUNET_free (ds_entry);
+}
+
+static void
+cleanup_handle (struct VerifyRequestHandle *vrh)
+{
+ struct CredentialRecordEntry *cr_entry;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Cleaning up...\n");
+ if (NULL != vrh->lookup_request)
+ {
+ GNUNET_GNS_lookup_cancel (vrh->lookup_request);
+ vrh->lookup_request = NULL;
+ }
+ cleanup_delegation_set (vrh->root_set);
+ GNUNET_free_non_null (vrh->issuer_attribute);
+ for (cr_entry = vrh->cred_chain_head;
+ NULL != vrh->cred_chain_head;
+ cr_entry = vrh->cred_chain_head)
+ {
+ GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ cr_entry);
+ GNUNET_free_non_null (cr_entry->credential);
+ GNUNET_free (cr_entry);
+ }
+ GNUNET_free (vrh);
+}
+
+static void
+shutdown_task (void *cls)
+{
+ struct VerifyRequestHandle *vrh;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Shutting down!\n");
+
+ while (NULL != (vrh = vrh_head))
+ {
+ //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
+ GNUNET_CONTAINER_DLL_remove (vrh_head,
+ vrh_tail,
+ vrh);
+ cleanup_handle (vrh);
+ }
+
+ if (NULL != gns)
+ {
+ GNUNET_GNS_disconnect (gns);
+ gns = NULL;
+ }
+ if (NULL != namestore)
+ {
+ GNUNET_NAMESTORE_disconnect (namestore);
+ namestore = NULL;
+ }
+ if (NULL != statistics)
+ {
+ GNUNET_STATISTICS_destroy (statistics,
+ GNUNET_NO);
+ statistics = NULL;
+ }
+
+}
+
+
+
+static void
+send_lookup_response (struct VerifyRequestHandle *vrh)
+{
+ struct GNUNET_MQ_Envelope *env;
+ struct DelegationChainResultMessage *rmsg;
+ struct DelegationChainEntry *dce;
+ struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
+ struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
+ struct CredentialRecordEntry *cd;
+ struct CredentialRecordEntry *tmp;
+ size_t size;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending response\n");
+ dce = vrh->delegation_chain_head;
+ for (uint32_t i=0;i<vrh->delegation_chain_size;i++)
+ {
+ dd[i].issuer_key = dce->issuer_key;
+ dd[i].subject_key = dce->subject_key;
+ dd[i].issuer_attribute = dce->issuer_attribute;
+ dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
+ dd[i].subject_attribute_len = 0;
+ dd[i].subject_attribute = NULL;
+ if (NULL != dce->subject_attribute)
+ {
+ dd[i].subject_attribute = dce->subject_attribute;
+ dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
+ }
+ dce = dce->next;
+ }
+
+ /**
+ * Remove all credentials not needed
+ */
+ for (cd = vrh->cred_chain_head; NULL != cd;)
+ {
+ if (cd->refcount > 0)
+ {
+ cd = cd->next;
+ continue;
+ }
+ tmp = cd;
+ cd = cd->next;
+ GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ tmp);
+ GNUNET_free (tmp->credential);
+ GNUNET_free (tmp);
+ vrh->cred_chain_size--;
+ }
+
+ /**
+ * Get serialized record data
+ * Append at the end of rmsg
+ */
+ cd = vrh->cred_chain_head;
+ for (uint32_t i=0;i<vrh->cred_chain_size;i++)
+ {
+ cred[i].issuer_key = cd->credential->issuer_key;
+ cred[i].subject_key = cd->credential->subject_key;
+ cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
+ cred[i].issuer_attribute = cd->credential->issuer_attribute;
+ cred[i].expiration = cd->credential->expiration;
+ cred[i].signature = cd->credential->signature;
+ cd = cd->next;
+ }
+ size = GNUNET_CREDENTIAL_delegation_chain_get_size (vrh->delegation_chain_size,
+ dd,
+ vrh->cred_chain_size,
+ cred);
+ env = GNUNET_MQ_msg_extra (rmsg,
+ size,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
+ //Assign id so that client can find associated request
+ rmsg->id = vrh->request_id;
+ rmsg->d_count = htonl (vrh->delegation_chain_size);
+ rmsg->c_count = htonl (vrh->cred_chain_size);
+
+ if (0 < vrh->cred_chain_size)
+ rmsg->cred_found = htonl (GNUNET_YES);
+ else
+ rmsg->cred_found = htonl (GNUNET_NO);
+
+ GNUNET_assert (-1 !=
+ GNUNET_CREDENTIAL_delegation_chain_serialize (vrh->delegation_chain_size,
+ dd,
+ vrh->cred_chain_size,
+ cred,
+ size,
+ (char*)&rmsg[1]));
+
+ GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
+ env);
+ GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
+ cleanup_handle(vrh);
+
+ GNUNET_STATISTICS_update (statistics,
+ "Completed verifications", 1,
+ GNUNET_NO);
+}
+
+
+static void
+backward_resolution (void* cls,
+ uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+
+ struct VerifyRequestHandle *vrh;
+ const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
+ struct CredentialRecordEntry *cred_pointer;
+ struct DelegationSetQueueEntry *current_set;
+ struct DelegationSetQueueEntry *ds_entry;
+ struct DelegationSetQueueEntry *tmp_set;
+ struct DelegationQueueEntry *dq_entry;
+ char *expanded_attr;
+ char *lookup_attribute;
+
+
+ current_set = cls;
+ current_set->lookup_request = NULL;
+ vrh = current_set->handle;
+ vrh->pending_lookups--;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got %d attrs\n", rd_count);
+
+ // Each OR
+ for (uint32_t i=0; i < rd_count; i++)
+ {
+ if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
+ continue;
+
+ sets = rd[i].data;
+ struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found new attribute delegation with %d sets. Creating new Job...\n",
+ ntohl (sets->set_count));
+
+ if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
+ (const char*)&sets[1],
+ ntohl(sets->set_count),
+ set))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to deserialize!\n");
+ continue;
+ }
+ dq_entry = GNUNET_new (struct DelegationQueueEntry);
+ dq_entry->required_solutions = ntohl(sets->set_count);
+ dq_entry->parent_set = current_set;
+ GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
+ current_set->queue_entries_tail,
+ dq_entry);
+ // Each AND
+ for (uint32_t j=0; j<ntohl(sets->set_count); j++)
+ {
+ ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
+ if (NULL != current_set->attr_trailer)
+ {
+ if (0 == set[j].subject_attribute_len)
+ {
+ GNUNET_asprintf (&expanded_attr,
+ "%s",
+ current_set->attr_trailer);
+
+ } else {
+ GNUNET_asprintf (&expanded_attr,
+ "%s.%s",
+ set[j].subject_attribute,
+ current_set->attr_trailer);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Expanded to %s\n", expanded_attr);
+ ds_entry->unresolved_attribute_delegation = expanded_attr;
+ } else {
+ if (0 != set[j].subject_attribute_len)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not Expanding %s\n", set[j].subject_attribute);
+ ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
+ }
+ }
+
+ //Add a credential chain entry
+ ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
+ ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ GNUNET_memcpy (ds_entry->issuer_key,
+ &set[j].subject_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ if (0 < set[j].subject_attribute_len)
+ ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
+ ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
+ ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
+
+ ds_entry->parent_queue_entry = dq_entry; //current_delegation;
+ GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
+ dq_entry->set_entries_tail,
+ ds_entry);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking for cred match\n");
+ /**
+ * Check if this delegation already matches one of our credentials
+ */
+ for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
+ cred_pointer = cred_pointer->next)
+ {
+ if(0 != memcmp (&set->subject_key,
+ &cred_pointer->credential->issuer_key,
+ sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ continue;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking if %s matches %s\n",
+ ds_entry->unresolved_attribute_delegation,
+ cred_pointer->credential->issuer_attribute);
+
+ if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
+ cred_pointer->credential->issuer_attribute))
+ continue;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found issuer\n");
+ cred_pointer->refcount++;
+ //Backtrack
+ for (tmp_set = ds_entry;
+ NULL != tmp_set->parent_queue_entry;
+ tmp_set = tmp_set->parent_queue_entry->parent_set)
+ {
+ tmp_set->parent_queue_entry->required_solutions--;
+ if (NULL != tmp_set->delegation_chain_entry)
+ {
+ vrh->delegation_chain_size++;
+ GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
+ vrh->delegation_chain_tail,
+ tmp_set->delegation_chain_entry);
+ }
+ if (0 < tmp_set->parent_queue_entry->required_solutions)
+ break;
+ }
+
+ if (NULL == tmp_set->parent_queue_entry)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "All solutions found\n");
+ //Found match
+ send_lookup_response (vrh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not all solutions found yet.\n");
+ continue;
+
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Building new lookup request from %s\n",
+ ds_entry->unresolved_attribute_delegation);
+ //Continue with backward resolution
+ char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
+ strcpy (issuer_attribute_name,
+ ds_entry->unresolved_attribute_delegation);
+ char *next_attr = strtok (issuer_attribute_name, ".");
+ GNUNET_asprintf (&lookup_attribute,
+ "%s.gnu",
+ next_attr);
+ GNUNET_asprintf (&ds_entry->lookup_attribute,
+ "%s",
+ next_attr);
+ if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
+ {
+ ds_entry->attr_trailer = NULL;
+ } else {
+ next_attr += strlen (next_attr) + 1;
+ ds_entry->attr_trailer = GNUNET_strdup (next_attr);
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up %s\n", ds_entry->lookup_attribute);
+ if (NULL != ds_entry->attr_trailer)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s still to go...\n", ds_entry->attr_trailer);
+
+ vrh->pending_lookups++;
+ ds_entry->handle = vrh;
+ ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
+ lookup_attribute,
+ ds_entry->issuer_key, //issuer_key,
+ GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
+ GNUNET_GNS_LO_DEFAULT,
+ &backward_resolution,
+ ds_entry);
+ GNUNET_free (lookup_attribute);
+ }
+ }
+
+ if(0 == vrh->pending_lookups)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We are all out of attributes...\n");
+ send_lookup_response (vrh);
+ return;
+
+ }
+}
+
+
+/**
+ * Result from GNS lookup.
+ *
+ * @param cls the closure (our client lookup handle)
+ */
+static void
+delegation_chain_resolution_start (void* cls)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ struct DelegationSetQueueEntry *ds_entry;
+ struct CredentialRecordEntry *cr_entry;
+ vrh->lookup_request = NULL;
+
+ if (0 == vrh->cred_chain_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No credentials found\n");
+ send_lookup_response (vrh);
+ return;
+ }
+
+ for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = cr_entry->next)
+ {
+ if (0 != memcmp (&cr_entry->credential->issuer_key,
+ &vrh->issuer_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ continue;
+ if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
+ continue;
+ cr_entry->refcount++;
+ //Found match prematurely
+ send_lookup_response (vrh);
+ return;
+
+ }
+
+ /**
+ * Check for attributes from the issuer and follow the chain
+ * till you get the required subject's attributes
+ */
+ char issuer_attribute_name[strlen (vrh->issuer_attribute)];
+ strcpy (issuer_attribute_name,
+ vrh->issuer_attribute);
+ strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
+ ".gnu");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up %s\n", issuer_attribute_name);
+ ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ memcpy (ds_entry->issuer_key,
+ &vrh->issuer_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
+ ds_entry->handle = vrh;
+ ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
+ vrh->root_set = ds_entry;
+ vrh->pending_lookups = 1;
+ //Start with backward resolution
+ ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
+ issuer_attribute_name,
+ &vrh->issuer_key, //issuer_key,
+ GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
+ GNUNET_GNS_LO_DEFAULT,
+ &backward_resolution,
+ ds_entry);
+}
+
+static int
+check_verify (void *cls,
+ const struct VerifyMessage *v_msg)
+{
+ size_t msg_size;
+ const char* attr;
+
+ msg_size = ntohs (v_msg->header.size);
+ if (msg_size < sizeof (struct VerifyMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ attr = (const char *) &v_msg[1];
+
+ if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+static void
+handle_verify (void *cls,
+ const struct VerifyMessage *v_msg)
+{
+ struct VerifyRequestHandle *vrh;
+ struct GNUNET_SERVICE_Client *client = cls;
+ struct CredentialRecordEntry *cr_entry;
+ uint32_t credentials_count;
+ uint32_t credential_data_size;
+ char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ char *attrptr = attr;
+ char *credential_data;
+ const char *utf_in;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received VERIFY message\n");
+ utf_in = (const char *) &v_msg[1];
+ GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
+ GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
+ issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
+ vrh = GNUNET_new (struct VerifyRequestHandle);
+ GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
+ vrh->client = client;
+ vrh->request_id = v_msg->id;
+ vrh->issuer_key = v_msg->issuer_key;
+ vrh->subject_key = v_msg->subject_key;
+ vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
+ if (NULL == issuer_attribute)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No issuer attribute provided!\n");
+ send_lookup_response (vrh);
+ return;
+ }
+ /**
+ * First, collect credentials
+ * TODO: cleanup!
+ */
+ credentials_count = ntohl(v_msg->c_count);
+ credential_data_size = ntohs (v_msg->header.size)
+ - sizeof (struct VerifyMessage)
+ - ntohs (v_msg->issuer_attribute_len)
+ - 1;
+ struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
+ credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
+ if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize (credential_data_size,
+ credential_data,
+ credentials_count,
+ credentials))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Cannot deserialize credentials!\n");
+ send_lookup_response (vrh);
+ return;
+ }
+
+ for (uint32_t i=0;i<credentials_count;i++) {
+ cr_entry = GNUNET_new (struct CredentialRecordEntry);
+ cr_entry->credential = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) +
+ credentials[i].issuer_attribute_len);
+ GNUNET_memcpy (cr_entry->credential,
+ &credentials[i],
+ sizeof (struct GNUNET_CREDENTIAL_Credential));
+ GNUNET_memcpy (&cr_entry->credential[1],
+ credentials[i].issuer_attribute,
+ credentials[i].issuer_attribute_len);
+ cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
+ GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ cr_entry);
+ vrh->cred_chain_size++;
+ }
+
+ delegation_chain_resolution_start (vrh);
+
+}
+
+static void
+handle_cred_collection_error_cb (void *cls)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got disconnected from namestore database.\n");
+ vrh->cred_collection_iter = NULL;
+ send_lookup_response (vrh);
+}
+
+static void
+collect_next (void *cls)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ vrh->collect_next_task = NULL;
+ GNUNET_assert (NULL != vrh->cred_collection_iter);
+ GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
+}
+
+static void
+handle_cred_collection_cb (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
+ const char *label,
+ unsigned int rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ struct GNUNET_CREDENTIAL_Credential *crd;
+ struct CredentialRecordEntry *cr_entry;
+ int cred_record_count;
+
+ cred_record_count = 0;
+ for (uint32_t i=0; i < rd_count; i++)
+ {
+ if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
+ continue;
+ cred_record_count++;
+ crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
+ rd[i].data_size);
+ if (NULL == crd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid credential found\n");
+ continue;
+ }
+ cr_entry = GNUNET_new (struct CredentialRecordEntry);
+ cr_entry->credential = crd;
+ GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ cr_entry);
+ vrh->cred_chain_size++;
+ }
+ vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
+ vrh);
+}
+
+static void
+handle_cred_collection_finished_cb (void *cls)
+{
+ struct VerifyRequestHandle *vrh = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Done collecting credentials.\n");
+ vrh->cred_collection_iter = NULL;
+ delegation_chain_resolution_start (vrh);
+}
+
+static void
+handle_collect (void *cls,
+ const struct CollectMessage *c_msg)
+{
+ char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+ struct VerifyRequestHandle *vrh;
+ struct GNUNET_SERVICE_Client *client = cls;
+ char *attrptr = attr;
+ const char *utf_in;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received COLLECT message\n");
+
+ utf_in = (const char *) &c_msg[1];
+ GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
+
+ GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
+ issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
+ vrh = GNUNET_new (struct VerifyRequestHandle);
+ GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
+ vrh->client = client;
+ vrh->request_id = c_msg->id;
+ vrh->issuer_key = c_msg->issuer_key;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
+ &vrh->subject_key);
+ vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
+
+ if (NULL == issuer_attribute)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No issuer attribute provided!\n");
+ send_lookup_response (vrh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting credentials for subject\n");
+ /**
+ * First, get attribute from subject
+ */
+ vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
+ &c_msg->subject_key,
+ &handle_cred_collection_error_cb,
+ vrh,
+ &handle_cred_collection_cb,
+ vrh,
+ &handle_cred_collection_finished_cb,
+ vrh);
+}
+
+
+static int
+check_collect (void *cls,
+ const struct CollectMessage *c_msg)
+{
+ size_t msg_size;
+ const char* attr;
+
+ msg_size = ntohs (c_msg->header.size);
+ if (msg_size < sizeof (struct CollectMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ attr = (const char *) &c_msg[1];
+
+ if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct CollectMessage) - 1]) ||
+ (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+static void
+client_disconnect_cb (void *cls,
+ struct GNUNET_SERVICE_Client *client,
+ void *app_ctx)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client %p disconnected\n",
+ client);
+}
+
+static void *
+client_connect_cb (void *cls,
+ struct GNUNET_SERVICE_Client *client,
+ struct GNUNET_MQ_Handle *mq)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client %p connected\n",
+ client);
+ return client;
+}
+
+/**
+ * Process Credential requests.
+ *
+ * @param cls closure
+ * @param c configuration to use
+ * @param handle service handle
+ */
+static void
+run (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *c,
+ struct GNUNET_SERVICE_Handle *handle)
+{
+
+ gns = GNUNET_GNS_connect (c);
+ if (NULL == gns)
+ {
+ fprintf (stderr,
+ _("Failed to connect to GNS\n"));
+ }
+ namestore = GNUNET_NAMESTORE_connect (c);
+ if (NULL == namestore)
+ {
+ fprintf (stderr,
+ _("Failed to connect to namestore\n"));
+ }
+
+ statistics = GNUNET_STATISTICS_create ("credential", c);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+}
+
+
+/**
+ * Define "main" method using service macro
+ */
+GNUNET_SERVICE_MAIN
+("credential",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_var_size (verify,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
+ struct VerifyMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (collect,
+ GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
+ struct CollectMessage,
+ NULL),
+ GNUNET_MQ_handler_end());
+
+/* end of gnunet-service-credential.c */
diff --git a/src/credential/plugin_gnsrecord_credential.c b/src/credential/plugin_gnsrecord_credential.c
new file mode 100644
index 000000000..342790b7a
--- /dev/null
+++ b/src/credential/plugin_gnsrecord_credential.c
@@ -0,0 +1,353 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2013 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file credential/plugin_gnsrecord_credential.c
+ * @brief gnsrecord plugin to provide the API for CREDENTIAL records
+ * @author Martin Schanzenbach
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_gnsrecord_plugin.h"
+#include "gnunet_signatures.h"
+#include "credential_serialization.h"
+#include "credential_misc.h"
+
+/**
+ * Convert the 'value' of a record to a string.
+ *
+ * @param cls closure, unused
+ * @param type type of the record
+ * @param data value in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the value
+ */
+static char *
+credential_value_to_string (void *cls,
+ uint32_t type,
+ const void *data,
+ size_t data_size)
+{
+
+ const char *cdata;
+
+ switch (type)
+ {
+ case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
+ {
+ struct GNUNET_CREDENTIAL_DelegationRecord sets;
+ char *attr_str;
+ char *subject_pkey;
+ char *tmp_str;
+ int i;
+ if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
+ return NULL; /* malformed */
+ memcpy (&sets,
+ data,
+ sizeof (sets));
+ cdata = data;
+ struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
+ if (GNUNET_OK != GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll (sets.data_size),
+ &cdata[sizeof (sets)],
+ ntohl (sets.set_count),
+ set))
+ return NULL;
+
+ for (i=0;i<ntohl(sets.set_count);i++)
+ {
+ subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%d len attr\n", set[i].subject_attribute_len);
+ if (0 == set[i].subject_attribute_len)
+ {
+ if (0 == i)
+ {
+ GNUNET_asprintf (&attr_str,
+ "%s",
+ subject_pkey);
+ } else {
+ GNUNET_asprintf (&tmp_str,
+ "%s,%s",
+ attr_str,
+ subject_pkey);
+ GNUNET_free (attr_str);
+ attr_str = tmp_str;
+ }
+ } else {
+ if (0 == i)
+ {
+ GNUNET_asprintf (&attr_str,
+ "%s %s",
+ subject_pkey,
+ set[i].subject_attribute);
+ } else {
+ GNUNET_asprintf (&tmp_str,
+ "%s,%s %s",
+ attr_str,
+ subject_pkey,
+ set[i].subject_attribute);
+ GNUNET_free (attr_str);
+ attr_str = tmp_str;
+ }
+ }
+ GNUNET_free (subject_pkey);
+ }
+ return attr_str;
+ }
+ case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
+ {
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ char *cred_str;
+
+ cred = GNUNET_CREDENTIAL_credential_deserialize (data,
+ data_size);
+ cred_str = GNUNET_CREDENTIAL_credential_to_string (cred);
+ GNUNET_free (cred);
+ return cred_str;
+ }
+ case GNUNET_GNSRECORD_TYPE_POLICY:
+ {
+ return GNUNET_strndup (data,data_size);
+ }
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * Convert human-readable version of a 'value' of a record to the binary
+ * representation.
+ *
+ * @param cls closure, unused
+ * @param type type of the record
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+static int
+credential_string_to_value (void *cls,
+ uint32_t type,
+ const char *s,
+ void **data,
+ size_t *data_size)
+{
+ if (NULL == s)
+ return GNUNET_SYSERR;
+ switch (type)
+ {
+ case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
+ {
+ struct GNUNET_CREDENTIAL_DelegationRecord *sets;
+ char attr_str[253 + 1];
+ char subject_pkey[52 + 1];
+ char *token;
+ char *tmp_str;
+ int matches = 0;
+ int entries;
+ size_t tmp_data_size;
+ int i;
+
+ tmp_str = GNUNET_strdup (s);
+ token = strtok (tmp_str, ",");
+ entries = 0;
+ tmp_data_size = 0;
+ *data_size = sizeof (struct GNUNET_CREDENTIAL_DelegationRecord);
+ while (NULL != token)
+ {
+ matches = SSCANF (token,
+ "%s %s",
+ subject_pkey,
+ attr_str);
+ if (0 == matches)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unable to parse ATTR record string `%s'\n"),
+ s);
+ GNUNET_free (tmp_str);
+ return GNUNET_SYSERR;
+ }
+ if (1 == matches) {
+ tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet);
+ } else if (2 == matches) {
+ tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
+ }
+ entries++;
+ token = strtok (NULL, ",");
+ }
+ GNUNET_free (tmp_str);
+ tmp_str = GNUNET_strdup (s);
+ token = strtok (tmp_str, ",");
+ struct GNUNET_CREDENTIAL_DelegationSet set[entries];
+ for (i=0;i<entries;i++)
+ {
+ matches = SSCANF (token,
+ "%s %s",
+ subject_pkey,
+ attr_str);
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
+ strlen (subject_pkey),
+ &set[i].subject_key);
+ if (2 == matches) {
+ set[i].subject_attribute_len = strlen (attr_str) + 1;
+ set[i].subject_attribute = GNUNET_strdup (attr_str);
+ }
+ token = strtok (NULL , ",");
+ }
+ tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
+ set);
+
+ if (-1 == tmp_data_size)
+ return GNUNET_SYSERR;
+ *data_size += tmp_data_size;
+ *data = sets = GNUNET_malloc (*data_size);
+ GNUNET_CREDENTIAL_delegation_set_serialize (entries,
+ set,
+ tmp_data_size,
+ (char*)&sets[1]);
+ for (i=0;i<entries;i++)
+ {
+ if (0 != set[i].subject_attribute_len)
+ GNUNET_free ((char*)set[i].subject_attribute);
+ }
+ sets->set_count = htonl (entries);
+ sets->data_size = GNUNET_htonll (tmp_data_size);
+
+ GNUNET_free (tmp_str);
+ return GNUNET_OK;
+ }
+ case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
+ {
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ cred = GNUNET_CREDENTIAL_credential_from_string (s);
+
+ *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
+ (char**)data);
+ return GNUNET_OK;
+ }
+ case GNUNET_GNSRECORD_TYPE_POLICY:
+ {
+ *data_size = strlen (s);
+ *data = GNUNET_strdup (s);
+ return GNUNET_OK;
+ }
+ default:
+ return GNUNET_SYSERR;
+ }
+}
+
+
+/**
+ * Mapping of record type numbers to human-readable
+ * record type names.
+ */
+static struct {
+ const char *name;
+ uint32_t number;
+} name_map[] = {
+ { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
+ { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
+ { "POLICY", GNUNET_GNSRECORD_TYPE_POLICY },
+ { NULL, UINT32_MAX }
+};
+
+
+/**
+ * Convert a type name (i.e. "AAAA") to the corresponding number.
+ *
+ * @param cls closure, unused
+ * @param gns_typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+static uint32_t
+credential_typename_to_number (void *cls,
+ const char *gns_typename)
+{
+ unsigned int i;
+
+ i=0;
+ while ( (name_map[i].name != NULL) &&
+ (0 != strcasecmp (gns_typename, name_map[i].name)) )
+ i++;
+ return name_map[i].number;
+}
+
+
+/**
+ * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
+ *
+ * @param cls closure, unused
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+static const char *
+credential_number_to_typename (void *cls,
+ uint32_t type)
+{
+ unsigned int i;
+
+ i=0;
+ while ( (name_map[i].name != NULL) &&
+ (type != name_map[i].number) )
+ i++;
+ return name_map[i].name;
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls NULL
+ * @return the exported block API
+ */
+void *
+libgnunet_plugin_gnsrecord_credential_init (void *cls)
+{
+ struct GNUNET_GNSRECORD_PluginFunctions *api;
+
+ api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
+ api->value_to_string = &credential_value_to_string;
+ api->string_to_value = &credential_string_to_value;
+ api->typename_to_number = &credential_typename_to_number;
+ api->number_to_typename = &credential_number_to_typename;
+ return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the return value from #libgnunet_plugin_block_test_init
+ * @return NULL
+ */
+void *
+libgnunet_plugin_gnsrecord_credential_done (void *cls)
+{
+ struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
+
+ GNUNET_free (api);
+ return NULL;
+}
+
+/* end of plugin_gnsrecord_credential.c */
diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c
new file mode 100644
index 000000000..480658822
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,1146 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2012-2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+/**
+ * @author Martin Schanzenbach
+ * @file credential/plugin_rest_credential.c
+ * @brief GNUnet CREDENTIAL REST plugin
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include <gnunet_identity_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_namestore_service.h>
+#include <gnunet_credential_service.h>
+#include <gnunet_rest_lib.h>
+#include <gnunet_jsonapi_lib.h>
+#include <gnunet_jsonapi_util.h>
+#include <jansson.h>
+
+#define GNUNET_REST_API_NS_CREDENTIAL "/credential"
+
+#define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
+
+#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
+
+#define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
+
+#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+struct RequestHandle
+{
+ /**
+ * Handle to Credential service.
+ */
+ struct GNUNET_CREDENTIAL_Handle *credential;
+
+ /**
+ * Handle to lookup request
+ */
+ struct GNUNET_CREDENTIAL_Request *verify_request;
+
+ /**
+ * Handle to issue request
+ */
+ struct GNUNET_CREDENTIAL_Request *issue_request;
+
+ /**
+ * Handle to identity
+ */
+ struct GNUNET_IDENTITY_Handle *identity;
+
+ /**
+ * Handle to identity operation
+ */
+ struct GNUNET_IDENTITY_Operation *id_op;
+
+ /**
+ * Handle to ego lookup
+ */
+ struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
+
+ /**
+ * Handle to rest request
+ */
+ struct GNUNET_REST_RequestHandle *rest_handle;
+
+ /**
+ * ID of a task associated with the resolution process.
+ */
+ struct GNUNET_SCHEDULER_Task * timeout_task;
+
+ /**
+ * The root of the received JSON or NULL
+ */
+ json_t *json_root;
+
+ /**
+ * The plugin result processor
+ */
+ GNUNET_REST_ResultProcessor proc;
+
+ /**
+ * The closure of the result processor
+ */
+ void *proc_cls;
+
+ /**
+ * The issuer attribute to verify
+ */
+ char *issuer_attr;
+
+ /**
+ * The subject attribute
+ */
+ char *subject_attr;
+
+ /**
+ * The public key of the issuer
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * The public key of the subject
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * HTTP response code
+ */
+ int response_code;
+
+ /**
+ * Timeout
+ */
+ struct GNUNET_TIME_Relative timeout;
+
+};
+
+
+/**
+ * Cleanup lookup handle.
+ *
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (struct RequestHandle *handle)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Cleaning up\n");
+ if (NULL != handle->json_root)
+ json_decref (handle->json_root);
+
+ if (NULL != handle->issuer_attr)
+ GNUNET_free (handle->issuer_attr);
+ if (NULL != handle->subject_attr)
+ GNUNET_free (handle->subject_attr);
+ if (NULL != handle->verify_request)
+ GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
+ if (NULL != handle->credential)
+ GNUNET_CREDENTIAL_disconnect (handle->credential);
+ if (NULL != handle->id_op)
+ GNUNET_IDENTITY_cancel (handle->id_op);
+ if (NULL != handle->ego_lookup)
+ GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
+ if (NULL != handle->identity)
+ GNUNET_IDENTITY_disconnect (handle->identity);
+ if (NULL != handle->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (handle->timeout_task);
+ }
+ GNUNET_free (handle);
+}
+
+
+static void
+do_error (void *cls)
+{
+ struct RequestHandle *handle = cls;
+ struct MHD_Response *resp;
+
+ resp = GNUNET_REST_create_response (NULL);
+ handle->proc (handle->proc_cls, resp, handle->response_code);
+ cleanup_handle (handle);
+}
+
+/**
+ * Attribute delegation to JSON
+ *
+ * @param delegation_chain_entry the DSE
+ * @return JSON, NULL if failed
+ */
+static json_t*
+attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation *delegation_chain_entry)
+{
+ char *subject;
+ char *issuer;
+ json_t *attr_obj;
+
+ issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->issuer_key);
+ if (NULL == issuer)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Issuer in delegation malformed\n");
+ return NULL;
+ }
+ subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&delegation_chain_entry->subject_key);
+ if (NULL == subject)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Subject in credential malformed\n");
+ GNUNET_free (issuer);
+ return NULL;
+ }
+ attr_obj = json_object ();
+
+ json_object_set_new (attr_obj, "issuer", json_string (issuer));
+ json_object_set_new (attr_obj, "issuer_attribute",
+ json_string (delegation_chain_entry->issuer_attribute));
+
+ json_object_set_new (attr_obj, "subject", json_string (subject));
+ if (0 < delegation_chain_entry->subject_attribute_len)
+ {
+ json_object_set_new (attr_obj, "subject_attribute",
+ json_string (delegation_chain_entry->subject_attribute));
+ }
+ GNUNET_free (issuer);
+ GNUNET_free (subject);
+ return attr_obj;
+}
+
+/**
+ * JSONAPI resource to Credential
+ *
+ * @param res the JSONAPI resource
+ * @return the resulting credential, NULL if failed
+ */
+static struct GNUNET_CREDENTIAL_Credential*
+json_to_credential (json_t *res)
+{
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ json_t *tmp;
+ const char *attribute;
+ const char *signature;
+ char *sig;
+
+ tmp = json_object_get (res, "attribute");
+ if (0 == json_is_string (tmp))
+ {
+ return NULL;
+ }
+ attribute = json_string_value (tmp);
+ cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
+ + strlen (attribute));
+ cred->issuer_attribute = attribute;
+ cred->issuer_attribute_len = strlen (attribute);
+ tmp = json_object_get (res, "issuer");
+ if (0 == json_is_string (tmp))
+ {
+ GNUNET_free (cred);
+ return NULL;
+ }
+
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
+ strlen (json_string_value(tmp)),
+ &cred->issuer_key);
+ tmp = json_object_get (res, "subject");
+ if (0 == json_is_string (tmp))
+ {
+ GNUNET_free (cred);
+ return NULL;
+ }
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
+ strlen (json_string_value(tmp)),
+ &cred->subject_key);
+
+ tmp = json_object_get (res, "signature");
+ if (0 == json_is_string (tmp))
+ {
+ GNUNET_free (cred);
+ return NULL;
+ }
+ signature = json_string_value (tmp);
+ GNUNET_STRINGS_base64_decode (signature,
+ strlen (signature),
+ (char**)&sig);
+ GNUNET_memcpy (&cred->signature,
+ sig,
+ sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+ GNUNET_free (sig);
+
+ tmp = json_object_get (res, "expiration");
+ if (0 == json_is_integer (tmp))
+ {
+ GNUNET_free (cred);
+ return NULL;
+ }
+ cred->expiration.abs_value_us = json_integer_value (tmp);
+ return cred;
+}
+
+
+/**
+ * Credential to JSON
+ *
+ * @param cred the credential
+ * @return the resulting json, NULL if failed
+ */
+static json_t*
+credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ char *issuer;
+ char *subject;
+ char *signature;
+ char attribute[cred->issuer_attribute_len + 1];
+ json_t *cred_obj;
+
+ issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
+ if (NULL == issuer)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Issuer in credential malformed\n");
+ return NULL;
+ }
+ subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
+ if (NULL == subject)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Subject in credential malformed\n");
+ GNUNET_free (issuer);
+ return NULL;
+ }
+ GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
+ sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+ &signature);
+ memcpy (attribute,
+ cred->issuer_attribute,
+ cred->issuer_attribute_len);
+ attribute[cred->issuer_attribute_len] = '\0';
+ cred_obj = json_object ();
+ json_object_set_new (cred_obj, "issuer", json_string (issuer));
+ json_object_set_new (cred_obj, "subject", json_string (subject));
+ json_object_set_new (cred_obj, "attribute", json_string (attribute));
+ json_object_set_new (cred_obj, "signature", json_string (signature));
+ json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
+ GNUNET_free (issuer);
+ GNUNET_free (subject);
+ GNUNET_free (signature);
+ return cred_obj;
+}
+
+static void
+handle_collect_response (void *cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ struct RequestHandle *handle = cls;
+ struct MHD_Response *resp;
+ struct GNUNET_JSONAPI_Document *json_document;
+ struct GNUNET_JSONAPI_Resource *json_resource;
+ json_t *cred_obj;
+ json_t *cred_array;
+ char *result;
+ char *issuer;
+ char *id;
+ uint32_t i;
+
+ handle->verify_request = NULL;
+ if (NULL == cred) {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Verify failed.\n");
+ handle->response_code = MHD_HTTP_NOT_FOUND;
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
+ if (NULL == issuer)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Issuer in delegation malformed\n");
+ return;
+ }
+ GNUNET_asprintf (&id,
+ "%s.%s",
+ issuer,
+ handle->issuer_attr);
+ GNUNET_free (issuer);
+ json_document = GNUNET_JSONAPI_document_new ();
+ json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
+ id);
+ GNUNET_free (id);
+ cred_array = json_array ();
+ for (i=0;i<c_count;i++)
+ {
+ cred_obj = credential_to_json (&cred[i]);
+ json_array_append_new (cred_array, cred_obj);
+ }
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ GNUNET_REST_JSONAPI_CREDENTIAL,
+ cred_array);
+ GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+ GNUNET_JSONAPI_document_serialize (json_document, &result);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Result %s\n",
+ result);
+ json_decref (cred_array);
+ GNUNET_JSONAPI_document_delete (json_document);
+ resp = GNUNET_REST_create_response (result);
+ GNUNET_free(result);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+ cleanup_handle (handle);
+}
+
+static void
+subject_ego_lookup (void *cls,
+ const struct GNUNET_IDENTITY_Ego *ego)
+{
+ struct RequestHandle *handle = cls;
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
+ handle->ego_lookup = NULL;
+
+ if (NULL == ego)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Subject not found\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
+ handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
+ &handle->issuer_key,
+ handle->issuer_attr,
+ sub_key,
+ &handle_collect_response,
+ handle);
+}
+
+
+
+static void
+handle_verify_response (void *cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+
+ struct RequestHandle *handle = cls;
+ struct MHD_Response *resp;
+ struct GNUNET_JSONAPI_Document *json_document;
+ struct GNUNET_JSONAPI_Resource *json_resource;
+ json_t *cred_obj;
+ json_t *attr_obj;
+ json_t *cred_array;
+ json_t *attr_array;
+ char *result;
+ char *issuer;
+ char *id;
+ uint32_t i;
+
+ handle->verify_request = NULL;
+ if (NULL == cred) {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Verify failed.\n");
+ handle->response_code = MHD_HTTP_NOT_FOUND;
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
+ if (NULL == issuer)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Issuer in delegation malformed\n");
+ return;
+ }
+ GNUNET_asprintf (&id,
+ "%s.%s",
+ issuer,
+ handle->issuer_attr);
+ GNUNET_free (issuer);
+ json_document = GNUNET_JSONAPI_document_new ();
+ json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
+ id);
+ GNUNET_free (id);
+ attr_array = json_array ();
+ for (i = 0; i < d_count; i++)
+ {
+ attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
+ json_array_append_new (attr_array, attr_obj);
+ }
+ cred_array = json_array ();
+ for (i=0;i<c_count;i++)
+ {
+ cred_obj = credential_to_json (&cred[i]);
+ json_array_append_new (cred_array, cred_obj);
+ }
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ GNUNET_REST_JSONAPI_CREDENTIAL,
+ cred_array);
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ GNUNET_REST_JSONAPI_DELEGATIONS,
+ attr_array);
+ GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+ GNUNET_JSONAPI_document_serialize (json_document, &result);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Result %s\n",
+ result);
+ json_decref (attr_array);
+ json_decref (cred_array);
+ GNUNET_JSONAPI_document_delete (json_document);
+ resp = GNUNET_REST_create_response (result);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+ GNUNET_free (result);
+ cleanup_handle (handle);
+}
+
+static void
+collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
+ const char* url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+ struct GNUNET_HashCode key;
+ char *tmp;
+ char *entity_attr;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connecting...\n");
+ handle->credential = GNUNET_CREDENTIAL_connect (cfg);
+ handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
+ &do_error, handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connected\n");
+ if (NULL == handle->credential)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Connecting to CREDENTIAL failed\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
+ strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
+ &key);
+ if ( GNUNET_NO ==
+ GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+ &key) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Missing issuer attribute\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+ &key);
+ entity_attr = GNUNET_strdup (tmp);
+ tmp = strtok(entity_attr, ".");
+ if (NULL == tmp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed issuer or attribute\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
+ strlen (tmp),
+ &handle->issuer_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed issuer key\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ tmp = strtok (NULL, "."); //Issuer attribute
+ if (NULL == tmp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed attribute\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ handle->issuer_attr = GNUNET_strdup (tmp);
+ GNUNET_free (entity_attr);
+
+ GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
+ strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
+ &key);
+ if ( GNUNET_NO ==
+ GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+ &key) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Missing subject\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+ &key);
+ if (NULL == tmp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed subject\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
+ tmp,
+ &subject_ego_lookup,
+ handle);
+}
+
+
+
+static void
+verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
+ const char* url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+ struct GNUNET_HashCode key;
+ struct GNUNET_JSONAPI_Document *json_obj;
+ struct GNUNET_JSONAPI_Resource *res;
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ char *tmp;
+ char *entity_attr;
+ int i;
+ uint32_t credential_count;
+ uint32_t resource_count;
+ json_t *cred_json;
+ json_t *data_js;
+ json_error_t err;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connecting...\n");
+ handle->credential = GNUNET_CREDENTIAL_connect (cfg);
+ handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
+ &do_error, handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connected\n");
+ if (NULL == handle->credential)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Connecting to CREDENTIAL failed\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
+ strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
+ &key);
+ if ( GNUNET_NO ==
+ GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+ &key) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Missing issuer attribute\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+ &key);
+ entity_attr = GNUNET_strdup (tmp);
+ tmp = strtok(entity_attr, ".");
+ if (NULL == tmp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed issuer or attribute\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
+ strlen (tmp),
+ &handle->issuer_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed issuer key\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ tmp = strtok (NULL, "."); //Issuer attribute
+ if (NULL == tmp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed attribute\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ handle->issuer_attr = GNUNET_strdup (tmp);
+ GNUNET_free (entity_attr);
+
+ GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
+ strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
+ &key);
+ if ( GNUNET_NO ==
+ GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+ &key) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Missing subject key\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+ &key);
+ if (NULL == tmp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed subject\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
+ strlen (tmp),
+ &handle->subject_key)) {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed subject key\n");
+ GNUNET_free (entity_attr);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+
+ if (0 >= handle->rest_handle->data_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Missing credentials\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+
+ struct GNUNET_JSON_Specification docspec[] = {
+ GNUNET_JSON_spec_jsonapi_document (&json_obj),
+ GNUNET_JSON_spec_end()
+ };
+ char term_data[handle->rest_handle->data_size+1];
+ term_data[handle->rest_handle->data_size] = '\0';
+ credential_count = 0;
+ GNUNET_memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_js = json_loads (term_data,
+ JSON_DECODE_ANY,
+ &err);
+ GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
+ NULL, NULL));
+ json_decref (data_js);
+ if (NULL == json_obj)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse JSONAPI Object from %s\n",
+ term_data);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+
+ resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
+ GNUNET_assert (1 == resource_count);
+ res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
+ if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
+ GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Resource not a credential!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse JSONAPI Object from %s\n",
+ term_data);
+ GNUNET_JSONAPI_document_delete (json_obj);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ cred_json = GNUNET_JSONAPI_resource_read_attr (res,
+ GNUNET_REST_JSONAPI_CREDENTIAL);
+
+ GNUNET_assert (json_is_array (cred_json));
+
+ credential_count = json_array_size(cred_json);
+
+ struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
+ for (i=0;i<credential_count;i++)
+ {
+ cred = json_to_credential (json_array_get (cred_json, i));
+ if (NULL == cred)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse credential!\n");
+ continue;
+ }
+ GNUNET_memcpy (&credentials[i],
+ cred,
+ sizeof (struct GNUNET_CREDENTIAL_Credential));
+ credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
+ GNUNET_free (cred);
+ }
+ GNUNET_JSONAPI_document_delete(json_obj);
+ handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
+ &handle->issuer_key,
+ handle->issuer_attr,
+ &handle->subject_key,
+ credential_count,
+ credentials,
+ &handle_verify_response,
+ handle);
+ for (i=0;i<credential_count;i++)
+ GNUNET_free ((char*)credentials[i].issuer_attribute);
+
+}
+
+void
+send_cred_response (struct RequestHandle *handle,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ struct MHD_Response *resp;
+ struct GNUNET_JSONAPI_Document *json_document;
+ struct GNUNET_JSONAPI_Resource *json_resource;
+ json_t *cred_obj;
+ char *result;
+ char *issuer;
+ char *subject;
+ char *signature;
+ char *id;
+
+ GNUNET_assert (NULL != cred);
+ issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
+ if (NULL == issuer)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Subject malformed\n");
+ return;
+ }
+ GNUNET_asprintf (&id,
+ "%s.%s",
+ issuer,
+ (char*)&cred[1]);
+ subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
+ if (NULL == subject)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Subject malformed\n");
+ return;
+ }
+ GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
+ sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+ &signature);
+ json_document = GNUNET_JSONAPI_document_new ();
+ json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
+ id);
+ GNUNET_free (id);
+ cred_obj = json_object();
+ json_object_set_new (cred_obj, "issuer", json_string (issuer));
+ json_object_set_new (cred_obj, "subject", json_string (subject));
+ json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us));
+ json_object_set_new (cred_obj, "signature", json_string (signature));
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ GNUNET_REST_JSONAPI_CREDENTIAL,
+ cred_obj);
+ GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+ GNUNET_JSONAPI_document_serialize (json_document, &result);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Result %s\n",
+ result);
+ json_decref (cred_obj);
+ GNUNET_JSONAPI_document_delete (json_document);
+ resp = GNUNET_REST_create_response (result);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+ GNUNET_free (result);
+ GNUNET_free (signature);
+ GNUNET_free (issuer);
+ GNUNET_free (subject);
+ cleanup_handle (handle);
+}
+
+void
+get_cred_issuer_cb (void *cls,
+ struct GNUNET_IDENTITY_Ego *ego,
+ void **ctx,
+ const char *name)
+{
+ struct RequestHandle *handle = cls;
+ struct GNUNET_TIME_Absolute etime_abs;
+ struct GNUNET_TIME_Relative etime_rel;
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
+ struct GNUNET_HashCode key;
+ struct GNUNET_CREDENTIAL_Credential *cred;
+ char* expiration_str;
+ char* tmp;
+
+ handle->id_op = NULL;
+
+ if (NULL == name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Issuer not configured!\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connecting to credential service...\n");
+ handle->credential = GNUNET_CREDENTIAL_connect (cfg);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connected\n");
+ if (NULL == handle->credential)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Connecting to CREDENTIAL failed\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
+ strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
+ &key);
+ if ( GNUNET_NO ==
+ GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+ &key) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Missing expiration\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+ &key);
+ if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
+ &etime_rel))
+ {
+ etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
+ } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str,
+ &etime_abs))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed expiration: %s\n", expiration_str);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
+ strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
+ &key);
+ if ( GNUNET_NO ==
+ GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+ &key) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Missing issuer attribute\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get
+ (handle->rest_handle->url_param_map,
+ &key));
+ GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
+ strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
+ &key);
+ if ( GNUNET_NO ==
+ GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+ &key) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Missing subject\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+ &key);
+ if (NULL == tmp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed subject\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
+ strlen (tmp),
+ &handle->subject_key)) {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Malformed subject key\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
+ cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
+ &handle->subject_key,
+ handle->issuer_attr,
+ &etime_abs);
+ if (NULL == cred)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to create credential\n");
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ send_cred_response (handle, cred);
+}
+
+
+static void
+issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
+ const char* url,
+ void *cls)
+{
+ struct RequestHandle *handle = cls;
+
+ handle->identity = GNUNET_IDENTITY_connect (cfg,
+ NULL,
+ NULL);
+ handle->id_op = GNUNET_IDENTITY_get(handle->identity,
+ "credential-issuer",
+ &get_cred_issuer_cb,
+ handle);
+ handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
+ &do_error,
+ handle);
+}
+
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char* url,
+ void *cls)
+{
+ struct MHD_Response *resp;
+ struct RequestHandle *handle = cls;
+
+ //For GNS, independent of path return all options
+ resp = GNUNET_REST_create_response (NULL);
+ MHD_add_response_header (resp,
+ "Access-Control-Allow-Methods",
+ MHD_HTTP_METHOD_GET);
+ handle->proc (handle->proc_cls,
+ resp,
+ MHD_HTTP_OK);
+ cleanup_handle (handle);
+}
+
+
+static void
+rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
+ GNUNET_REST_ResultProcessor proc,
+ void *proc_cls)
+{
+ struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+ struct GNUNET_REST_RequestHandlerError err;
+
+ handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+ handle->proc_cls = proc_cls;
+ handle->proc = proc;
+ handle->rest_handle = conndata_handle;
+
+ static const struct GNUNET_REST_RequestHandler handlers[] = {
+ {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont},
+ {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, &collect_cred_cont},
+ {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont},
+ {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
+ GNUNET_REST_HANDLER_END
+ };
+
+ if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
+ handlers,
+ &err,
+ handle))
+ {
+ handle->response_code = err.error_code;
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ }
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_credential_init (void *cls)
+{
+ static struct Plugin plugin;
+ cfg = cls;
+ struct GNUNET_REST_Plugin *api;
+
+ if (NULL != plugin.cfg)
+ return NULL; /* can only initialize once! */
+ memset (&plugin, 0, sizeof (struct Plugin));
+ plugin.cfg = cfg;
+ api = GNUNET_new (struct GNUNET_REST_Plugin);
+ api->cls = &plugin;
+ api->name = GNUNET_REST_API_NS_CREDENTIAL;
+ api->process_request = &rest_credential_process_request;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("GNS REST API initialized\n"));
+ return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_credential_done (void *cls)
+{
+ struct GNUNET_REST_Plugin *api = cls;
+ struct Plugin *plugin = api->cls;
+
+ plugin->cfg = NULL;
+ GNUNET_free (api);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GNS REST plugin is finished\n");
+ return NULL;
+}
+
+/* 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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+TEST_ATTR2="test2"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
+#TODO1 Get credential and store it with subject (3)
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
+$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c test_credential_lookup.conf`
+$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste -d, -s`
+echo $CREDS
+RES=$?
+gnunet-arm -e -c test_credential_lookup.conf
+
+if test $? != 0
+then
+ echo "Error collecting..."
+ exit 1
+fi
+
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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) Service.user -> GNU.project.member
+# (2) GNU.project -> GNUnet
+# (3) GNUnet.member -> GNUnet.developer
+# (4) GNUnet.member -> GNUnet.user
+# (5) GNUnet.developer -> Alice
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C service -c test_credential_lookup.conf
+gnunet-identity -C alice -c test_credential_lookup.conf
+gnunet-identity -C gnu -c test_credential_lookup.conf
+gnunet-identity -C gnunet -c test_credential_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
+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
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
+gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+
+#TODO2 Add -z swich like in gnunet-gns
+#RES_CRED=`gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY -c test_credential_lookup.conf`
+
+gnunet-arm -i rest -c test_credential_lookup.conf
+
+sleep 5
+
+curl -v "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"
+
+#TODO cleanup properly
+gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
+echo "Stopping arm..."
+gnunet-arm -e -c test_credential_lookup.conf
+echo "Done"
+if [ "$RES_CRED" != "Failed." ]
+then
+ echo -e "${RES_CRED}"
+ exit 0
+else
+ echo "FAIL: Failed to verify credential $RES_CRED."
+ exit 1
+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 @@
+@INLINE@ ../../contrib/no_forcestart.conf
+
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-gnunet-credential-testing/
+
+[namestore-sqlite]
+FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
+
+[namecache-sqlite]
+FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
+
+[identity]
+# Directory where we store information about our egos
+EGODIR = $GNUNET_TEST_HOME/identity/egos/
+
+[dhtcache]
+DATABASE = heap
+
+[transport]
+PLUGINS = tcp
+
+[transport-tcp]
+BINDTO = 127.0.0.1
+
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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
+#TODO1 Get credential and store it with subject (3)
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
+STATUS=$?
+
+if test $? != 0
+then
+ echo "Error issuing..."
+ exit 1
+fi
+#Try import
+$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+RES=$?
+gnunet-arm -e -c test_credential_lookup.conf
+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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-arm -i gns
+gnunet-arm -i credential
+gnunet-arm -i identity
+gnunet-arm -i rest -c test_credential_lookup.conf
+
+gnunet-arm -I -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+gnunet-identity -s credential-issuer -e testissuer
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
+#TODO1 Get credential and store it with subject (3)
+sleep 5
+curl "localhost:7776/credential/issue?subject_key=$SUBJECT_KEY&attribute=$TEST_ATTR&expiration=1d"
+#CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
+STATUS=$?
+
+if test $? != 0
+then
+ echo "Error issuing..."
+ exit 1
+fi
+#Try import
+#$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+RES=$?
+gnunet-arm -e -c test_credential_lookup.conf
+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 @@
+@INLINE@ test_credential_defaults.conf
+
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-gnunet-credential-peer-1/
+
+[dht]
+AUTOSTART = YES
+
+[transport]
+PLUGINS =
+
+[credential]
+AUTOSTART = YES
+PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
+
+[rest]
+PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
+
+[gns]
+#PREFIX = valgrind --leak-check=full --track-origins=yes
+AUTOSTART = YES
+AUTO_IMPORT_PKEY = YES
+MAX_PARALLEL_BACKGROUND_QUERIES = 10
+DEFAULT_LOOKUP_TIMEOUT = 15 s
+RECORD_PUT_INTERVAL = 1 h
+ZONE_PUBLISH_TIME_WINDOW = 1 h
+DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
+
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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) Service.user -> GNU.project.member
+# (2) GNU.project -> GNUnet
+# (3) GNUnet.member -> GNUnet.developer
+# (4) GNUnet.member -> GNUnet.user
+# (5) GNUnet.developer -> Alice
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C service -c test_credential_lookup.conf
+gnunet-identity -C alice -c test_credential_lookup.conf
+gnunet-identity -C gnu -c test_credential_lookup.conf
+gnunet-identity -C gnunet -c test_credential_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
+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
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
+gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
+
+echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf
+#TODO2 Add -z swich like in gnunet-gns
+gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf
+
+
+#TODO cleanup properly
+gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+
+if [ "$RES_CRED" != "Failed." ]
+then
+ echo -e "${RES_CRED}"
+ exit 0
+else
+ echo "FAIL: Failed to verify credential $RES_CRED."
+ exit 1
+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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) Service.user -> GNU.project.member
+# (2) GNU.project -> GNUnet
+# (3) GNUnet.member -> GNUnet.developer
+# (4) GNUnet.member -> GNUnet.user
+# (5) GNUnet.developer -> Alice
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C service -c test_credential_lookup.conf
+gnunet-identity -C alice -c test_credential_lookup.conf
+gnunet-identity -C gnu -c test_credential_lookup.conf
+gnunet-identity -C gnunet -c test_credential_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
+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
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
+gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
+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
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED1=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+# (5) GNUnet issues Alice the credential "user"
+CRED2=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED1" -e 5m -c test_credential_lookup.conf
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m -c test_credential_lookup.conf
+
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, -s`
+
+#TODO2 Add -z swich like in gnunet-gns
+RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf`
+
+
+#TODO cleanup properly
+gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+
+if [ "$RES_CRED" != "Failed." ]
+then
+ echo -e "${RES_CRED}"
+ exit 0
+else
+ echo "FAIL: Failed to verify credential $RES_CRED."
+ exit 1
+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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) Service.user -> GNU.project.member
+# (2) GNU.project -> GNUnet
+# (3) GNUnet.member -> GNUnet.developer
+# (4) GNUnet.member -> GNUnet.user
+# (5) GNUnet.developer -> Alice
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C service -c test_credential_lookup.conf
+gnunet-identity -C alice -c test_credential_lookup.conf
+gnunet-identity -C gnu -c test_credential_lookup.conf
+gnunet-identity -C gnunet -c test_credential_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service | awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
+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
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
+gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 5m -c test_credential_lookup.conf
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY --attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+
+#TODO2 Add -z swich like in gnunet-gns
+#RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
+
+gnunet-arm -i rest -c test_credential_lookup.conf
+
+sleep 5
+
+CREDS=`curl "localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"`
+
+echo $CREDS
+
+curl -v "localhost:7776/credential/verify?attribute=$SERVICE_KEY.$USER_ATTR&subject_key=$ALICE_KEY" --data "$CREDS"
+
+#TODO cleanup properly
+gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+
+if [ "$RES_CRED" != "Failed." ]
+then
+ echo -e "${RES_CRED}"
+ exit 0
+else
+ echo "FAIL: Failed to verify credential $RES_CRED."
+ exit 1
+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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+# (3) Isser.user -> Subject
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+
+TEST_ATTR="user"
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep testissuer | awk '{print $3}')
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer --subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+TEST_CREDENTIAL="t1"
+gnunet-namestore -p -z testsubject -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m -c test_credential_lookup.conf
+
+#TODO2 Add -z swich like in gnunet-gns
+#RES_CRED=`$DO_TIMEOUT gnunet-credential --verify --issuer=$ISSUER_KEY --attribute="$TEST_ATTR" --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
+RES_CRED=`gnunet-credential --verify --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c test_credential_lookup.conf`
+
+#TODO cleanup properly
+gnunet-namestore -z testsubject -d -n $TEST_CREDENTIAL -t CRED -e never -c test_credential_lookup.conf
+gnunet-identity -D testsubject -c test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+echo $RES_CRED
+#TODO3 proper test
+if [ "$RES_CRED" == "Successful." ]
+then
+ exit 0
+else
+ echo "FAIL: Failed to verify credential."
+ exit 1
+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,
if (GNUNET_YES !=
GNUNET_OS_check_helper_binary (binary,
GNUNET_YES,
- "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) //no nat, ipv4 only
+ "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) //no nat, ipv4 only
{
GNUNET_free (binary);
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,
return;
proc = lr->lookup_proc;
proc_cls = lr->proc_cls;
- GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
- handle->lookup_tail,
- lr);
- GNUNET_free (lr);
+
GNUNET_assert (GNUNET_OK ==
GNUNET_GNSRECORD_records_deserialize (mlen,
(const char*) &lookup_msg[1],
@@ -256,6 +253,12 @@ handle_result (void *cls,
proc (proc_cls,
rd_count,
rd);
+ GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
+ handle->lookup_tail,
+ lr);
+ if (NULL != lr->env)
+ GNUNET_MQ_discard (lr->env);
+ GNUNET_free (lr);
}
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,
GNUNET_free (ival);
return box_str;
}
- case GNUNET_GNSRECORD_TYPE_REVERSE:
- {
- struct GNUNET_GNSRECORD_ReverseRecord rev;
- char *rev_str;
- char *pkey_str;
-
- if (data_size < sizeof (struct GNUNET_GNSRECORD_ReverseRecord))
- return NULL; /* malformed */
-
- memcpy (&rev,
- data,
- sizeof (rev));
- cdata = data;
- pkey_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&rev.pkey);
-
- GNUNET_asprintf (&rev_str,
- "%s %s %"SCNu64,
- &cdata[sizeof (rev)],
- pkey_str,
- rev.expiration.abs_value_us);
- GNUNET_free (pkey_str);
- return rev_str;
-
- }
default:
return NULL;
}
@@ -335,48 +311,6 @@ gns_string_to_value (void *cls,
GNUNET_free (bval);
return GNUNET_OK;
}
- case GNUNET_GNSRECORD_TYPE_REVERSE:
- {
- struct GNUNET_GNSRECORD_ReverseRecord *rev;
- char known_by[253 + 1];
- struct GNUNET_TIME_Absolute expiration;
-
- /* TODO: From crypto_ecc.c
- * Why is this not a constant???
- */
- size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
- if (enclen % 5 > 0)
- enclen += 5 - enclen % 5;
- enclen /= 5; /* 260/5 = 52 */
- char pkey_str[enclen + 1];
-
- if (3 != SSCANF (s,
- "%253s %52s %"SCNu64,
- known_by,
- pkey_str,
- &expiration.abs_value_us))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse REVERSE record string `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1;
- *data = rev = GNUNET_malloc (*data_size);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str,
- strlen (pkey_str),
- &rev->pkey))
- {
- GNUNET_free (rev);
- return GNUNET_SYSERR;
- }
- rev->expiration = expiration;
- GNUNET_memcpy (&rev[1],
- known_by,
- strlen (known_by));
- return GNUNET_OK;
- }
default:
return GNUNET_SYSERR;
}
@@ -397,7 +331,6 @@ static struct {
{ "VPN", GNUNET_GNSRECORD_TYPE_VPN },
{ "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
{ "BOX", GNUNET_GNSRECORD_TYPE_BOX },
- { "REVERSE", GNUNET_GNSRECORD_TYPE_REVERSE },
{ NULL, UINT32_MAX }
};
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 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/gnunet
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+if MINGW
+ WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+ XLIBS = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+ libgnunetidentityattribute.la
+
+libgnunetidentityattribute_la_SOURCES = \
+ identity_attribute.c
+libgnunetidentityattribute_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL)
+libgnunetidentityattribute_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS) $(WINFLAGS) \
+ -version-info 0:0:0
+
+
+plugin_LTLIBRARIES = \
+ libgnunet_plugin_identity_attribute_gnuid.la
+
+
+libgnunet_plugin_identity_attribute_gnuid_la_SOURCES = \
+ plugin_identity_attribute_gnuid.c
+libgnunet_plugin_identity_attribute_gnuid_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(LTLIBINTL)
+libgnunet_plugin_identity_attribute_gnuid_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
diff --git a/src/identity-attribute/identity_attribute.c b/src/identity-attribute/identity_attribute.c
new file mode 100644
index 000000000..cf50d058e
--- /dev/null
+++ b/src/identity-attribute/identity_attribute.c
@@ -0,0 +1,421 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2010-2015 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file identity-attribute/identity_attribute.c
+ * @brief helper library to manage identity attributes
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "identity_attribute.h"
+#include "gnunet_identity_attribute_plugin.h"
+
+/**
+ * Handle for a plugin
+ */
+struct Plugin
+{
+ /**
+ * Name of the plugin
+ */
+ char *library_name;
+
+ /**
+ * Plugin API
+ */
+ struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
+};
+
+/**
+ * Plugins
+ */
+static struct Plugin **attr_plugins;
+
+/**
+ * Number of plugins
+ */
+static unsigned int num_plugins;
+
+/**
+ * Init canary
+ */
+static int initialized;
+
+/**
+ * Add a plugin
+ */
+static void
+add_plugin (void* cls,
+ const char *library_name,
+ void *lib_ret)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = lib_ret;
+ struct Plugin *plugin;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Loading attribute plugin `%s'\n",
+ library_name);
+ plugin = GNUNET_new (struct Plugin);
+ plugin->api = api;
+ plugin->library_name = GNUNET_strdup (library_name);
+ GNUNET_array_append (attr_plugins, num_plugins, plugin);
+}
+
+/**
+ * Load plugins
+ */
+static void
+init()
+{
+ if (GNUNET_YES == initialized)
+ return;
+ initialized = GNUNET_YES;
+ GNUNET_PLUGIN_load_all ("libgnunet_plugin_identity_attribute_", NULL,
+ &add_plugin, NULL);
+}
+
+/**
+ * Convert a type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename)
+{
+ unsigned int i;
+ struct Plugin *plugin;
+ uint32_t ret;
+
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = attr_plugins[i];
+ if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
+ typename)))
+ return ret;
+ }
+ return UINT32_MAX;
+}
+
+/**
+ * Convert a type number to the corresponding type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char*
+GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type)
+{
+ unsigned int i;
+ struct Plugin *plugin;
+ const char *ret;
+
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = attr_plugins[i];
+ if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
+ type)))
+ return ret;
+ }
+ return NULL;
+}
+
+/**
+ * Convert human-readable version of a 'claim' of an attribute to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
+ const char *s,
+ void **data,
+ size_t *data_size)
+{
+ unsigned int i;
+ struct Plugin *plugin;
+
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = attr_plugins[i];
+ if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
+ type,
+ s,
+ data,
+ data_size))
+ return GNUNET_OK;
+ }
+ return GNUNET_SYSERR;
+}
+
+/**
+ * Convert the 'claim' of an attribute to a string
+ *
+ * @param type the type of attribute
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
+ const void* data,
+ size_t data_size)
+{
+ unsigned int i;
+ struct Plugin *plugin;
+ char *ret;
+
+ init();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = attr_plugins[i];
+ if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
+ type,
+ data,
+ data_size)))
+ return ret;
+ }
+ return NULL;
+}
+
+/**
+ * Create a new attribute.
+ *
+ * @param attr_name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
+GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
+ uint32_t type,
+ const void* data,
+ size_t data_size)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
+ char *write_ptr;
+
+ attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) +
+ strlen (attr_name) + 1 +
+ data_size);
+ attr->type = type;
+ attr->data_size = data_size;
+ attr->version = 0;
+ write_ptr = (char*)&attr[1];
+ GNUNET_memcpy (write_ptr,
+ attr_name,
+ strlen (attr_name) + 1);
+ attr->name = write_ptr;
+ write_ptr += strlen (attr->name) + 1;
+ GNUNET_memcpy (write_ptr,
+ data,
+ data_size);
+ attr->data = write_ptr;
+ return attr;
+}
+
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ size_t len = 0;
+ for (le = attrs->list_head; NULL != le; le = le->next)
+ len += GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
+ return len;
+}
+
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+ char *result)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ size_t len;
+ size_t total_len;
+ char* write_ptr;
+
+ write_ptr = result;
+ total_len = 0;
+ for (le = attrs->list_head; NULL != le; le = le->next)
+ {
+ len = GNUNET_IDENTITY_ATTRIBUTE_serialize (le->claim,
+ write_ptr);
+ total_len += len;
+ write_ptr += len;
+ }
+ return total_len;
+}
+
+struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
+GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
+ size_t data_size)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ size_t attr_len;
+ const char* read_ptr;
+
+ if (data_size < sizeof (struct Attribute))
+ return NULL;
+
+ attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+ read_ptr = data;
+ while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
+ {
+
+ le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
+ le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (read_ptr,
+ data_size - (read_ptr - data));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Deserialized attribute %s\n", le->claim->name);
+ GNUNET_CONTAINER_DLL_insert (attrs->list_head,
+ attrs->list_tail,
+ le);
+ attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
+ read_ptr += attr_len;
+ }
+ return attrs;
+}
+
+struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
+GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *result_le;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *result;
+ size_t len;
+
+ result = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+ for (le = attrs->list_head; NULL != le; le = le->next)
+ {
+ result_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
+ len = sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) + le->claim->data_size;
+ result_le->claim = GNUNET_malloc (len);
+ GNUNET_memcpy (result_le->claim,
+ le->claim,
+ len);
+ result_le->claim->name = (const char*)&result_le->claim[1];
+ GNUNET_CONTAINER_DLL_insert (result->list_head,
+ result->list_tail,
+ result_le);
+ }
+ return result;
+}
+
+
+void
+GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *tmp_le;
+
+ for (le = attrs->list_head; NULL != le;)
+ {
+ GNUNET_free (le->claim);
+ tmp_le = le;
+ le = le->next;
+ GNUNET_free (tmp_le);
+ }
+ GNUNET_free (attrs);
+
+}
+
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
+{
+ return sizeof (struct Attribute)
+ + strlen (attr->name)
+ + attr->data_size;
+}
+
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
+ char *result)
+{
+ size_t data_len_ser;
+ size_t name_len;
+ struct Attribute *attr_ser;
+ char* write_ptr;
+
+ attr_ser = (struct Attribute*)result;
+ attr_ser->attribute_type = htons (attr->type);
+ attr_ser->attribute_version = htonl (attr->version);
+ name_len = strlen (attr->name);
+ attr_ser->name_len = htons (name_len);
+ write_ptr = (char*)&attr_ser[1];
+ GNUNET_memcpy (write_ptr, attr->name, name_len);
+ write_ptr += name_len;
+ //TODO plugin-ize
+ //data_len_ser = plugin->serialize_attribute_value (attr,
+ // &attr_ser[1]);
+ data_len_ser = attr->data_size;
+ GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
+ attr_ser->data_size = htons (data_len_ser);
+
+ return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
+}
+
+struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
+GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
+ size_t data_size)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
+ struct Attribute *attr_ser;
+ size_t data_len;
+ size_t name_len;
+ char* write_ptr;
+
+ if (data_size < sizeof (struct Attribute))
+ return NULL;
+
+ attr_ser = (struct Attribute*)data;
+ data_len = ntohs (attr_ser->data_size);
+ name_len = ntohs (attr_ser->name_len);
+ attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim)
+ + data_len + name_len + 1);
+ attr->type = ntohs (attr_ser->attribute_type);
+ attr->version = ntohl (attr_ser->attribute_version);
+ attr->data_size = ntohs (attr_ser->data_size);
+
+ write_ptr = (char*)&attr[1];
+ GNUNET_memcpy (write_ptr,
+ &attr_ser[1],
+ name_len);
+ write_ptr[name_len] = '\0';
+ attr->name = write_ptr;
+
+ write_ptr += name_len + 1;
+ GNUNET_memcpy (write_ptr,
+ (char*)&attr_ser[1] + name_len,
+ attr->data_size);
+ attr->data = write_ptr;
+ return attr;
+
+}
+
+/* end of identity_attribute.c */
diff --git a/src/identity-attribute/identity_attribute.h b/src/identity-attribute/identity_attribute.h
new file mode 100644
index 000000000..8dfc17521
--- /dev/null
+++ b/src/identity-attribute/identity_attribute.h
@@ -0,0 +1,56 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2012-2015 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+/**
+ * @author Martin Schanzenbach
+ * @file identity-attribute/identity_attribute.h
+ * @brief GNUnet Identity attributes
+ *
+ */
+#ifndef IDENTITY_ATTRIBUTE_H
+#define IDENTITY_ATTRIBUTE_H
+
+#include "gnunet_identity_provider_service.h"
+
+struct Attribute
+{
+ /**
+ * Attribute type
+ */
+ uint32_t attribute_type;
+
+ /**
+ * Attribute version
+ */
+ uint32_t attribute_version;
+
+ /**
+ * Name length
+ */
+ uint32_t name_len;
+
+ /**
+ * Data size
+ */
+ uint32_t data_size;
+
+ //followed by data_size Attribute value data
+};
+
+#endif
diff --git a/src/identity-attribute/plugin_identity_attribute_gnuid.c b/src/identity-attribute/plugin_identity_attribute_gnuid.c
new file mode 100644
index 000000000..006b45ea2
--- /dev/null
+++ b/src/identity-attribute/plugin_identity_attribute_gnuid.c
@@ -0,0 +1,184 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2013, 2014, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file identity-attribute/plugin_identity_attribute_gnuid.c
+ * @brief identity attribute plugin to provide the API for fundamental
+ * attribute types.
+ *
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_identity_attribute_plugin.h"
+#include <inttypes.h>
+
+
+/**
+ * Convert the 'value' of an attribute to a string.
+ *
+ * @param cls closure, unused
+ * @param type type of the attribute
+ * @param data value in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the value
+ */
+static char *
+gnuid_value_to_string (void *cls,
+ uint32_t type,
+ const void *data,
+ size_t data_size)
+{
+
+ switch (type)
+ {
+ case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
+ return GNUNET_strndup (data, data_size);
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * Convert human-readable version of a 'value' of an attribute to the binary
+ * representation.
+ *
+ * @param cls closure, unused
+ * @param type type of the attribute
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+static int
+gnuid_string_to_value (void *cls,
+ uint32_t type,
+ const char *s,
+ void **data,
+ size_t *data_size)
+{
+ if (NULL == s)
+ return GNUNET_SYSERR;
+ switch (type)
+ {
+
+ case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
+ *data = GNUNET_strdup (s);
+ *data_size = strlen (s);
+ return GNUNET_OK;
+ default:
+ return GNUNET_SYSERR;
+ }
+}
+
+
+/**
+ * Mapping of attribute type numbers to human-readable
+ * attribute type names.
+ */
+static struct {
+ const char *name;
+ uint32_t number;
+} gnuid_name_map[] = {
+ { "STRING", GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING },
+ { NULL, UINT32_MAX }
+};
+
+
+/**
+ * Convert a type name to the corresponding number.
+ *
+ * @param cls closure, unused
+ * @param gnuid_typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+static uint32_t
+gnuid_typename_to_number (void *cls,
+ const char *gnuid_typename)
+{
+ unsigned int i;
+
+ i=0;
+ while ( (NULL != gnuid_name_map[i].name) &&
+ (0 != strcasecmp (gnuid_typename,
+ gnuid_name_map[i].name)) )
+ i++;
+ return gnuid_name_map[i].number;
+}
+
+
+/**
+ * Convert a type number (i.e. 1) to the corresponding type string
+ *
+ * @param cls closure, unused
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+static const char *
+gnuid_number_to_typename (void *cls,
+ uint32_t type)
+{
+ unsigned int i;
+
+ i=0;
+ while ( (NULL != gnuid_name_map[i].name) &&
+ (type != gnuid_name_map[i].number) )
+ i++;
+ return gnuid_name_map[i].name;
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls NULL
+ * @return the exported block API
+ */
+void *
+libgnunet_plugin_identity_attribute_gnuid_init (void *cls)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
+
+ api = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions);
+ api->value_to_string = &gnuid_value_to_string;
+ api->string_to_value = &gnuid_string_to_value;
+ api->typename_to_number = &gnuid_typename_to_number;
+ api->number_to_typename = &gnuid_number_to_typename;
+ return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the return value from #libgnunet_plugin_block_test_init()
+ * @return NULL
+ */
+void *
+libgnunet_plugin_identity_attribute_gnuid_done (void *cls)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = cls;
+
+ GNUNET_free (api);
+ return NULL;
+}
+
+/* end of plugin_identity_attribute_type_gnuid.c */
diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am
index 0d8752c4c..adf6af3b3 100644
--- a/src/identity-provider/Makefile.am
+++ b/src/identity-provider/Makefile.am
@@ -12,6 +12,15 @@ if USE_COVERAGE
XLIB = -lgcov
endif
+if HAVE_SQLITE
+SQLITE_PLUGIN = libgnunet_plugin_identity_provider_sqlite.la
+endif
+
+EXTRA_DIST = \
+ test_idp_defaults.conf \
+ test_idp.conf \
+ $(check_SCRIPTS)
+
pkgcfgdir= $(pkgdatadir)/config.d/
libexecdir= $(pkglibdir)/libexec/
@@ -22,29 +31,51 @@ pkgcfg_DATA = \
lib_LTLIBRARIES = \
libgnunetidentityprovider.la
plugin_LTLIBRARIES = \
- libgnunet_plugin_rest_identity_provider.la
+ libgnunet_plugin_rest_identity_provider.la \
+ libgnunet_plugin_gnsrecord_identity_provider.la \
+ $(SQLITE_PLUGIN)
bin_PROGRAMS = \
- gnunet-identity-token
+ gnunet-idp
libexec_PROGRAMS = \
gnunet-service-identity-provider
-EXTRA_DIST = \
- $(pkgcfg_DATA)
+libgnunet_plugin_gnsrecord_identity_provider_la_SOURCES = \
+ plugin_gnsrecord_identity_provider.c
+libgnunet_plugin_gnsrecord_identity_provider_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(LTLIBINTL)
+libgnunet_plugin_gnsrecord_identity_provider_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_identity_provider_sqlite_la_SOURCES = \
+ plugin_identity_provider_sqlite.c
+libgnunet_plugin_identity_provider_sqlite_la_LIBADD = \
+ libgnunetidentityprovider.la \
+ $(top_builddir)/src/sq/libgnunetsq.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
+ $(LTLIBINTL)
+libgnunet_plugin_identity_provider_sqlite_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
gnunet_service_identity_provider_SOURCES = \
- gnunet-service-identity-provider.c \
- identity_token.c identity_token.h
+ gnunet-service-identity-provider.c
gnunet_service_identity_provider_LDADD = \
$(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/namestore/libgnunetnamestore.la \
$(top_builddir)/src/identity/libgnunetidentity.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/abe/libgnunetabe.la \
+ $(top_builddir)/src/credential/libgnunetcredential.la \
+ $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
+ libgnunetidentityprovider.la \
$(top_builddir)/src/gns/libgnunetgns.la \
- $(GN_LIBINTL) \
- -ljansson
+ $(GN_LIBINTL)
libgnunetidentityprovider_la_SOURCES = \
identity_provider_api.c \
@@ -57,22 +88,37 @@ libgnunetidentityprovider_la_LDFLAGS = \
-version-info 0:0:0
libgnunet_plugin_rest_identity_provider_la_SOURCES = \
- plugin_rest_identity_provider.c
+ plugin_rest_identity_provider.c \
+ jwt.c
libgnunet_plugin_rest_identity_provider_la_LIBADD = \
$(top_builddir)/src/identity/libgnunetidentity.la \
libgnunetidentityprovider.la \
$(top_builddir)/src/rest/libgnunetrest.la \
$(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
+ $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
$(top_builddir)/src/namestore/libgnunetnamestore.la \
$(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
$(LTLIBINTL) -ljansson -lmicrohttpd
libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \
$(GN_PLUGIN_LDFLAGS)
-
-gnunet_identity_token_SOURCES = \
- gnunet-identity-token.c
-gnunet_identity_token_LDADD = \
+gnunet_idp_SOURCES = \
+ gnunet-idp.c
+gnunet_idp_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- -ljansson -lmicrohttpd \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ libgnunetidentityprovider.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
$(GN_LIBINTL)
+
+check_SCRIPTS = \
+ test_idp_attribute.sh \
+ test_idp_issue.sh \
+ test_idp_consume.sh \
+ test_idp_revoke.sh
+
+if ENABLE_TEST_RUN
+ AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
+ TESTS = $(check_SCRIPTS)
+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 @@
-/*
- This file is part of GNUnet.
- Copyright (C) 2012-2015 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
- */
-/**
- * @author Martin Schanzenbach
- * @file src/identity-provider/gnunet-service-identity-provider.c
- * @brief Identity Token Service
- *
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include <jansson.h>
-#include "gnunet_signatures.h"
-
-/**
- * The token
- */
-static char* token;
-
-/**
- * Weather to print the token
- */
-static int print_token;
-
-static void
-run (void *cls,
- char *const *args,
- const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *c)
-{
- char *payload;
- char *header;
- //Get token parts
- const char *header_b64;
- const char *payload_b64;
- const char *signature_b32;
- const char *keystring;
- char *data;
- json_t *payload_json;
- json_t *keystring_json;
- json_error_t error;
- struct GNUNET_CRYPTO_EcdsaPublicKey key;
- struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
- struct GNUNET_CRYPTO_EcdsaSignature sig;
-
- if (NULL == token)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- _("Option `-t' is required\n"));
- return;
- }
- header_b64 = strtok (token, ".");
- payload_b64 = strtok (NULL, ".");
- signature_b32 = strtok (NULL, ".");
- if ( (NULL == header_b64) ||
- (NULL == payload_b64) ||
- (NULL == signature_b32) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- _("Token `%s' is malformed\n"),
- token);
- GNUNET_free (token);
- token = NULL;
- return;
- }
-
- //Decode payload
- GNUNET_STRINGS_base64_decode (payload_b64,
- strlen (payload_b64),
- &payload);
- //Decode header
- GNUNET_STRINGS_base64_decode (header_b64,
- strlen (header_b64),
- &header);
-
-
- GNUNET_asprintf(&data,
- "%s,%s",
- header_b64,
- payload_b64);
- char *val = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
- purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose*)val;
- purpose->size = htonl(sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (data));
- purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
- GNUNET_memcpy (&purpose[1], data, strlen(data));
- GNUNET_free (data);
- GNUNET_free (token);
- token = NULL;
-
- if (print_token)
- printf ("Token:\nHeader:\t\t%s\nPayload:\t%s\n",
- header,
- payload);
- GNUNET_free (header);
-
- payload_json = json_loads (payload, 0, &error);
- GNUNET_free (payload);
-
- if ((NULL == payload_json) || (! json_is_object (payload_json)) )
- {
- GNUNET_free (val);
- return;
- }
- keystring_json = json_object_get (payload_json, "iss");
- if (! json_is_string (keystring_json))
- {
- GNUNET_free (val);
- return;
- }
- keystring = json_string_value (keystring_json);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_public_key_from_string (keystring,
- strlen (keystring),
- &key))
- {
- GNUNET_free (val);
- return;
- }
- GNUNET_STRINGS_string_to_data (signature_b32,
- strlen (signature_b32),
- &sig,
- sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
-
- if (print_token)
- printf ("Signature:\t%s\n",
- keystring);
-
- if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN,
- purpose,
- &sig,
- &key))
- printf("Signature not OK!\n");
- else
- printf("Signature OK!\n");
- GNUNET_free (val);
- return;
-}
-
-
-int
-main(int argc, char *const argv[])
-{
- struct GNUNET_GETOPT_CommandLineOption options[] = {
-
- GNUNET_GETOPT_option_string ('t',
- "token",
- NULL,
- gettext_noop ("GNUid token"),
- &token),
-
- GNUNET_GETOPT_option_flag ('p',
- "print",
- gettext_noop ("Print token contents"),
- &print_token),
-
- GNUNET_GETOPT_OPTION_END
- };
- return GNUNET_PROGRAM_run (argc, argv, "ct",
- "ct", options,
- &run, NULL);
-}
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 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2012-2015 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+/**
+ * @author Martin Schanzenbach
+ * @file src/identity-provider/gnunet-idp.c
+ * @brief Identity Provider utility
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_identity_provider_service.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_signatures.h"
+
+/**
+ * return value
+ */
+static int ret;
+
+/**
+ * List attribute flag
+ */
+static int list;
+
+/**
+ * Relying party
+ */
+static char* rp;
+
+/**
+ * The attribute
+ */
+static char* attr_name;
+
+/**
+ * Attribute value
+ */
+static char* attr_value;
+
+/**
+ * Attributes to issue
+ */
+static char* issue_attrs;
+
+/**
+ * Ticket to consume
+ */
+static char* consume_ticket;
+
+/**
+ * Attribute type
+ */
+static char* type_str;
+
+/**
+ * Ticket to revoke
+ */
+static char* revoke_ticket;
+
+/**
+ * Ego name
+ */
+static char* ego_name;
+
+/**
+ * Identity handle
+ */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
+/**
+ * IdP handle
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle;
+
+/**
+ * IdP operation
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
+
+/**
+ * Attribute iterator
+ */
+static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator;
+
+/**
+ * Master ABE key
+ */
+static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
+
+/**
+ * ego private key
+ */
+static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
+
+/**
+ * rp public key
+ */
+static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
+
+/**
+ * Ticket to consume
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+
+/**
+ * Attribute list
+ */
+static struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list;
+
+static void
+do_cleanup(void *cls)
+{
+ if (NULL != attr_iterator)
+ GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator);
+ if (NULL != idp_handle)
+ GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle);
+ if (NULL != identity_handle)
+ GNUNET_IDENTITY_disconnect (identity_handle);
+ if (NULL != abe_key)
+ GNUNET_free (abe_key);
+ if (NULL != attr_list)
+ GNUNET_free (attr_list);
+}
+
+static void
+ticket_issue_cb (void* cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
+{
+ char* ticket_str;
+ if (NULL != ticket) {
+ ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
+ sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
+ printf("%s\n",
+ ticket_str);
+ GNUNET_free (ticket_str);
+ }
+ GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+store_attr_cont (void *cls,
+ int32_t success,
+ const char*emsg)
+{
+ if (GNUNET_SYSERR == success) {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%s\n", emsg);
+ }
+ GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+process_attrs (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
+{
+ char *value_str;
+ if (NULL == identity)
+ {
+ GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+ return;
+ }
+ if (NULL == attr)
+ {
+ ret = 1;
+ return;
+ }
+ value_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
+ attr->data,
+ attr->data_size);
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "%s: %s\n", attr->name, value_str);
+}
+
+
+static void
+iter_error (void *cls)
+{
+ attr_iterator = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to iterate over attributes\n");
+ GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+process_rvk (void *cls, int success, const char* msg)
+{
+ if (GNUNET_OK != success)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Revocation failed.\n");
+ ret = 1;
+ }
+ GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+iter_finished (void *cls)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
+ char *data;
+ size_t data_size;
+ int type;
+
+ attr_iterator = NULL;
+ if (list)
+ {
+ GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+ return;
+ }
+
+ if (issue_attrs)
+ {
+ idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (idp_handle,
+ pkey,
+ &rp_key,
+ attr_list,
+ &ticket_issue_cb,
+ NULL);
+ return;
+ }
+ if (consume_ticket)
+ {
+ idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (idp_handle,
+ pkey,
+ &ticket,
+ &process_attrs,
+ NULL);
+ return;
+ }
+ if (revoke_ticket)
+ {
+ idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle,
+ pkey,
+ &ticket,
+ &process_rvk,
+ NULL);
+ return;
+ }
+ if (NULL == type_str)
+ type = GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING;
+ else
+ type = GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (type_str);
+
+ GNUNET_assert (GNUNET_SYSERR != GNUNET_IDENTITY_ATTRIBUTE_string_to_value (type,
+ attr_value,
+ (void**)&data,
+ &data_size));
+ claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
+ type,
+ data,
+ data_size);
+ idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
+ pkey,
+ claim,
+ &store_attr_cont,
+ NULL);
+
+
+}
+
+static void
+iter_cb (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ char *attrs_tmp;
+ char *attr_str;
+
+ if (issue_attrs)
+ {
+ attrs_tmp = GNUNET_strdup (issue_attrs);
+ attr_str = strtok (attrs_tmp, ",");
+ while (NULL != attr_str) {
+ if (0 != strcmp (attr_str, attr->name)) {
+ attr_str = strtok (NULL, ",");
+ continue;
+ }
+ le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
+ le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name,
+ attr->type,
+ attr->data,
+ attr->data_size);
+ GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
+ attr_list->list_tail,
+ le);
+ break;
+ }
+ GNUNET_free (attrs_tmp);
+ } else if (list) {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "%s: %s\n", attr->name, (char*)attr->data);
+ }
+ GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
+}
+
+static void
+ego_cb (void *cls,
+ struct GNUNET_IDENTITY_Ego *ego,
+ void **ctx,
+ const char *name)
+{
+ if (NULL == name)
+ return;
+ if (0 != strcmp (name, ego_name))
+ return;
+ pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+
+ if (NULL != rp)
+ GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
+ strlen (rp),
+ &rp_key);
+ if (NULL != consume_ticket)
+ GNUNET_STRINGS_string_to_data (consume_ticket,
+ strlen (consume_ticket),
+ &ticket,
+ sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
+ if (NULL != revoke_ticket)
+ GNUNET_STRINGS_string_to_data (revoke_ticket,
+ strlen (revoke_ticket),
+ &ticket,
+ sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
+
+
+ attr_list = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+
+ attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
+ pkey,
+ &iter_error,
+ NULL,
+ &iter_cb,
+ NULL,
+ &iter_finished,
+ NULL);
+
+
+}
+
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ ret = 0;
+ if (NULL == ego_name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ _("Ego is required\n"));
+ return;
+ }
+
+ idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
+ //Get Ego
+ identity_handle = GNUNET_IDENTITY_connect (c,
+ &ego_cb,
+ NULL);
+
+
+}
+
+
+int
+main(int argc, char *const argv[])
+{
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+
+ GNUNET_GETOPT_option_string ('a',
+ "add",
+ NULL,
+ gettext_noop ("Add attribute"),
+ &attr_name),
+
+ GNUNET_GETOPT_option_string ('V',
+ "value",
+ NULL,
+ gettext_noop ("Attribute value"),
+ &attr_value),
+ GNUNET_GETOPT_option_string ('e',
+ "ego",
+ NULL,
+ gettext_noop ("Ego"),
+ &ego_name),
+ GNUNET_GETOPT_option_string ('r',
+ "rp",
+ NULL,
+ gettext_noop ("Audience (relying party)"),
+ &rp),
+ GNUNET_GETOPT_option_flag ('D',
+ "dump",
+ gettext_noop ("List attributes for Ego"),
+ &list),
+ GNUNET_GETOPT_option_string ('i',
+ "issue",
+ NULL,
+ gettext_noop ("Issue a ticket"),
+ &issue_attrs),
+ GNUNET_GETOPT_option_string ('C',
+ "consume",
+ NULL,
+ gettext_noop ("Consume a ticket"),
+ &consume_ticket),
+ GNUNET_GETOPT_option_string ('R',
+ "revoke",
+ NULL,
+ gettext_noop ("Revoke a ticket"),
+ &revoke_ticket),
+ GNUNET_GETOPT_option_string ('t',
+ "type",
+ NULL,
+ gettext_noop ("Type of attribute"),
+ &type_str),
+ GNUNET_GETOPT_OPTION_END
+ };
+ GNUNET_PROGRAM_run (argc, argv, "ct",
+ "ct", options,
+ &run, NULL);
+ return ret;
+}
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c
index 53fd02c9f..4e1de36cd 100644
--- a/src/identity-provider/gnunet-service-identity-provider.c
+++ b/src/identity-provider/gnunet-service-identity-provider.c
@@ -30,12 +30,14 @@
#include "gnunet_identity_service.h"
#include "gnunet_gnsrecord_lib.h"
#include "gnunet_namestore_service.h"
+#include "gnunet_abe_lib.h"
+#include "gnunet_credential_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet_gns_service.h"
+#include "gnunet_identity_provider_plugin.h"
+#include "gnunet_identity_attribute_lib.h"
#include "gnunet_signatures.h"
#include "identity_provider.h"
-#include "identity_token.h"
-#include <inttypes.h>
/**
* First pass state
@@ -58,24 +60,19 @@
#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
/**
- * Service state (to detect initial update pass)
- */
-static int state;
-
-/**
- * Head of ego entry DLL
+ * Identity handle
*/
-static struct EgoEntry *ego_head;
+static struct GNUNET_IDENTITY_Handle *identity_handle;
/**
- * Tail of ego entry DLL
+ * Database handle
*/
-static struct EgoEntry *ego_tail;
+static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
/**
- * Identity handle
+ * Name of DB plugin
*/
-static struct GNUNET_IDENTITY_Handle *identity_handle;
+static char *db_lib_name;
/**
* Token expiration interval
@@ -93,6 +90,16 @@ static struct GNUNET_NAMESTORE_Handle *ns_handle;
static struct GNUNET_GNS_Handle *gns_handle;
/**
+ * Credential handle
+ */
+static struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
+/**
+ * Stats handle
+ */
+static struct GNUNET_STATISTICS_Handle *stats_handle;
+
+/**
* Namestore qe
*/
static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
@@ -112,11 +119,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task;
*/
static struct GNUNET_SCHEDULER_Task *update_task;
-/**
- * Timeout for next update pass
- */
-static struct GNUNET_TIME_Relative min_rel_exp;
-
/**
* Currently processed token
@@ -134,43 +136,260 @@ static char* label;
static char* scopes;
/**
- * Expiration for processed token
+ * Handle to the statistics service.
*/
-static uint64_t rd_exp;
+static struct GNUNET_STATISTICS_Handle *stats;
/**
- * ECDHE Privkey for processed token metadata
+ * Our configuration.
*/
-static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey;
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
/**
- * Handle to the statistics service.
+ * An idp client
*/
-static struct GNUNET_STATISTICS_Handle *stats;
+struct IdpClient;
/**
- * Our configuration.
+ * A ticket iteration operation.
*/
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
+struct TicketIteration
+{
+ /**
+ * DLL
+ */
+ struct TicketIteration *next;
+
+ /**
+ * DLL
+ */
+ struct TicketIteration *prev;
+
+ /**
+ * Client which intiated this zone iteration
+ */
+ struct IdpClient *client;
+ /**
+ * Key of the identity we are iterating over.
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey identity;
-struct ExchangeHandle
+ /**
+ * Identity is audience
+ */
+ uint32_t is_audience;
+
+ /**
+ * The operation id fot the iteration in the response for the client
+ */
+ uint32_t r_id;
+
+ /**
+ * Offset of the iteration used to address next result of the
+ * iteration in the store
+ *
+ * Initialy set to 0 in handle_iteration_start
+ * Incremented with by every call to handle_iteration_next
+ */
+ uint32_t offset;
+
+};
+
+
+
+/**
+ * Callback after an ABE bootstrap
+ *
+ * @param cls closure
+ * @param abe_key the ABE key that exists or was created
+ */
+typedef void
+(*AbeBootstrapResult) (void *cls,
+ struct GNUNET_ABE_AbeMasterKey *abe_key);
+
+
+struct AbeBootstrapHandle
{
+ /**
+ * Function to call when finished
+ */
+ AbeBootstrapResult proc;
/**
- * Client connection
+ * Callback closure
+ */
+ char *proc_cls;
+
+ /**
+ * Key of the zone we are iterating over.
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+ /**
+ * Namestore Queue Entry
+ */
+ struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+ /**
+ * The issuer egos ABE master key
+ */
+ struct GNUNET_ABE_AbeMasterKey *abe_key;
+};
+
+/**
+ * An attribute iteration operation.
+ */
+struct AttributeIterator
+{
+ /**
+ * Next element in the DLL
+ */
+ struct AttributeIterator *next;
+
+ /**
+ * Previous element in the DLL
+ */
+ struct AttributeIterator *prev;
+
+ /**
+ * IDP client which intiated this zone iteration
+ */
+ struct IdpClient *client;
+
+ /**
+ * Key of the zone we are iterating over.
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+ /**
+ * The issuer egos ABE master key
+ */
+ struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+ /**
+ * Namestore iterator
+ */
+ struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+ /**
+ * The operation id fot the zone iteration in the response for the client
+ */
+ uint32_t request_id;
+
+};
+
+
+
+/**
+ * An idp client
+ */
+struct IdpClient
+{
+
+ /**
+ * The client
*/
struct GNUNET_SERVICE_Client *client;
/**
- * Ticket
+ * Message queue for transmission to @e client
+ */
+ struct GNUNET_MQ_Handle *mq;
+
+ /**
+ * Head of the DLL of
+ * Attribute iteration operations in
+ * progress initiated by this client
+ */
+ struct AttributeIterator *op_head;
+
+ /**
+ * Tail of the DLL of
+ * Attribute iteration operations
+ * in progress initiated by this client
+ */
+ struct AttributeIterator *op_tail;
+
+ /**
+ * Head of DLL of ticket iteration ops
+ */
+ struct TicketIteration *ticket_iter_head;
+
+ /**
+ * Tail of DLL of ticket iteration ops
+ */
+ struct TicketIteration *ticket_iter_tail;
+
+
+ /**
+ * Head of DLL of ticket revocation ops
+ */
+ struct TicketRevocationHandle *revocation_list_head;
+
+ /**
+ * Tail of DLL of ticket revocation ops
+ */
+ struct TicketRevocationHandle *revocation_list_tail;
+};
+
+
+
+struct AttributeStoreHandle
+{
+
+ /**
+ * Client connection
+ */
+ struct IdpClient *client;
+
+ /**
+ * Identity
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+ /**
+ * Identity pubkey
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
+
+ /**
+ * The issuer egos ABE master key
+ */
+ struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+ /**
+ * QueueEntry
+ */
+ struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+ /**
+ * The attribute to store
+ */
+ struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
+
+ /**
+ * request id
+ */
+ uint32_t r_id;
+};
+
+
+/* Prototype */
+struct ParallelLookup;
+
+struct ConsumeTicketHandle
+{
+
+ /**
+ * Client connection
*/
- struct TokenTicket *ticket;
+ struct IdpClient *client;
/**
- * Token returned
+ * Ticket
*/
- struct IdentityToken *token;
+ struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
/**
* LookupRequest
@@ -180,86 +399,173 @@ struct ExchangeHandle
/**
* Audience Key
*/
- struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
/**
- * Label to return
+ * Audience Key
*/
- char *label;
+ struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
/**
+ * Lookup DLL
+ */
+ struct ParallelLookup *parallel_lookups_head;
+
+ /**
+ * Lookup DLL
+ */
+ struct ParallelLookup *parallel_lookups_tail;
+
+ /**
+ * Kill task
+ */
+ struct GNUNET_SCHEDULER_Task *kill_task;
+
+ /**
+ * The ABE key
+ */
+ struct GNUNET_ABE_AbeKey *key;
+
+ /**
+ * Attributes
+ */
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+
+ /**
+ * Lookup time
+ */
+ struct GNUNET_TIME_Absolute lookup_start_time;
+
+ /**
* request id
*/
uint32_t r_id;
};
-struct IssueHandle
+/**
+ * Handle for a parallel GNS lookup job
+ */
+struct ParallelLookup
{
+ /* DLL */
+ struct ParallelLookup *next;
+
+ /* DLL */
+ struct ParallelLookup *prev;
+
+ /* The GNS request */
+ struct GNUNET_GNS_LookupRequest *lookup_request;
+
+ /* The handle the return to */
+ struct ConsumeTicketHandle *handle;
+
+ /**
+ * Lookup time
+ */
+ struct GNUNET_TIME_Absolute lookup_start_time;
+
+ /* The label to look up */
+ char *label;
+};
+
+/**
+ * Ticket revocation request handle
+ */
+struct TicketRevocationHandle
+{
+ /**
+ * DLL
+ */
+ struct TicketRevocationHandle *next;
+
+ /**
+ * DLL
+ */
+ struct TicketRevocationHandle *prev;
/**
* Client connection
*/
- struct GNUNET_SERVICE_Client *client;
+ struct IdpClient *client;
+
+ /**
+ * Attributes to reissue
+ */
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+
+ /**
+ * Attributes to revoke
+ */
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs;
/**
* Issuer Key
*/
- struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
/**
- * Issue pubkey
+ * Ticket to issue
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey;
+ struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
/**
- * Audience Key
+ * QueueEntry
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
+ struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
/**
- * Expiration
+ * Namestore iterator
*/
- struct GNUNET_TIME_Absolute expiration;
+ struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
/**
- * Scopes
+ * The ABE master key
*/
- char *scopes;
+ struct GNUNET_ABE_AbeMasterKey *abe_key;
/**
- * nonce
+ * Offset
*/
- uint64_t nonce;
+ uint32_t offset;
/**
- * NS iterator
+ * request id
*/
- struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+ uint32_t r_id;
+};
+
+
+
+/**
+ * Ticket issue request handle
+ */
+struct TicketIssueHandle
+{
/**
- * Attribute map
+ * Client connection
*/
- struct GNUNET_CONTAINER_MultiHashMap *attr_map;
+ struct IdpClient *client;
/**
- * Token
+ * Attributes to issue
*/
- struct IdentityToken *token;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
/**
- * Ticket
+ * Issuer Key
*/
- struct TokenTicket *ticket;
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
/**
- * QueueEntry
+ * Ticket to issue
*/
- struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+ struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
/**
- * The label the token is stored under
+ * QueueEntry
*/
- char *label;
+ struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
/**
* request id
@@ -267,6 +573,7 @@ struct IssueHandle
uint32_t r_id;
};
+
/**
* DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
*
@@ -293,1303 +600,1774 @@ struct EgoEntry
*/
struct GNUNET_CONTAINER_MultiHashMap *attr_map;
- /**
- * Attributes are old and should be updated if GNUNET_YES
- */
- int attributes_dirty;
};
/**
- * Continuation for token store call
+ * Cleanup task
+ */
+static void
+cleanup()
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Cleaning up\n");
+ if (NULL != stats)
+ {
+ GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
+ stats = NULL;
+ }
+ GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
+ TKT_database));
+ GNUNET_free (db_lib_name);
+ db_lib_name = NULL;
+ if (NULL != timeout_task)
+ GNUNET_SCHEDULER_cancel (timeout_task);
+ if (NULL != update_task)
+ GNUNET_SCHEDULER_cancel (update_task);
+ if (NULL != identity_handle)
+ GNUNET_IDENTITY_disconnect (identity_handle);
+ if (NULL != gns_handle)
+ GNUNET_GNS_disconnect (gns_handle);
+ if (NULL != credential_handle)
+ GNUNET_CREDENTIAL_disconnect (credential_handle);
+ if (NULL != ns_it)
+ GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
+ if (NULL != ns_qe)
+ GNUNET_NAMESTORE_cancel (ns_qe);
+ if (NULL != ns_handle)
+ GNUNET_NAMESTORE_disconnect (ns_handle);
+ if (NULL != stats_handle)
+ GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO);
+ GNUNET_free_non_null (token);
+ GNUNET_free_non_null (label);
+
+}
+
+/**
+ * Shutdown task
*
* @param cls NULL
- * @param success error code
- * @param emsg error message
*/
static void
-store_token_cont (void *cls,
- int32_t success,
- const char *emsg)
+do_shutdown (void *cls)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Shutting down...\n");
+ cleanup();
+}
+
+/**
+ * Finished storing newly bootstrapped ABE key
+ */
+static void
+bootstrap_store_cont (void *cls,
+ int32_t success,
+ const char *emsg)
{
- ns_qe = NULL;
+ struct AbeBootstrapHandle *abh = cls;
if (GNUNET_SYSERR == success)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to update token: %s\n",
+ "Failed to bootstrap ABE master %s\n",
emsg);
+ abh->proc (abh->proc_cls, NULL);
+ GNUNET_free (abh->abe_key);
+ GNUNET_free (abh);
return;
}
- GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+ abh->proc (abh->proc_cls, abh->abe_key);
+ GNUNET_free (abh);
}
-
/**
- * This function updates the old token with new attributes,
- * removes deleted attributes and expiration times.
- *
- * @param cls the ego entry
+ * Generates and stores a new ABE key
*/
static void
-handle_token_update (void *cls)
+bootstrap_store_task (void *cls)
{
- char *token_metadata;
- char *write_ptr;
- char *enc_token_str;
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
- struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
- struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey;
- struct EgoEntry *ego_entry = cls;
- struct GNUNET_GNSRECORD_Data token_record[2];
- struct GNUNET_HashCode key_hash;
- struct GNUNET_TIME_Relative token_rel_exp;
- struct GNUNET_TIME_Relative token_ttl;
- struct GNUNET_TIME_Absolute token_exp;
- struct GNUNET_TIME_Absolute token_nbf;
- struct GNUNET_TIME_Absolute new_exp;
- struct GNUNET_TIME_Absolute new_iat;
- struct GNUNET_TIME_Absolute new_nbf;
- struct IdentityToken *new_token;
- struct TokenAttr *cur_value;
- struct TokenAttr *attr;
- size_t token_metadata_len;
-
- priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
- GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
- &pub_key);
-
- //Note: We need the token expiration time here. Not the record expiration
- //time.
- //There are two types of tokens: Token that expire on GNS level with
- //an absolute expiration time. Those are basically tokens that will
- //be automatically revoked on (record)expiration.
- //Tokens stored with relative expiration times will expire on the token level (token expiration)
- //but this service will reissue new tokens that can be retrieved from GNS
- //automatically.
-
- for (attr = token->attr_head; NULL != attr; attr = attr->next)
- {
- if (0 == strcmp (attr->name, "exp"))
- {
- GNUNET_assert (1 == sscanf (attr->val_head->value,
- "%"SCNu64,
- &token_exp.abs_value_us));
- } else if (0 == strcmp (attr->name, "nbf")) {
- GNUNET_assert (1 == sscanf (attr->val_head->value,
- "%"SCNu64,
- &token_nbf.abs_value_us));
- }
- }
- token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp);
-
- token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp);
- if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us)
- {
- //This token is not yet expired! Save and skip
- if (min_rel_exp.rel_value_us > token_ttl.rel_value_us)
- {
- min_rel_exp = token_ttl;
- }
- GNUNET_free (token);
- token = NULL;
- GNUNET_free (label);
- label = NULL;
- GNUNET_free (scopes);
- scopes = NULL;
- GNUNET_NAMESTORE_zone_iterator_next (ns_it);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Token is expired. Create a new one\n");
- new_token = token_create (&pub_key,
- &token->aud_key);
- new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
- new_nbf = GNUNET_TIME_absolute_get ();
- new_iat = new_nbf;
- for (attr = token->attr_head; NULL != attr; attr = attr->next)
- {
- if (0 == strcmp (attr->name, "exp"))
- {
- token_add_attr_int (new_token, attr->name, new_exp.abs_value_us);
- }
- else if (0 == strcmp (attr->name, "nbf"))
- {
- token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us);
- }
- else if (0 == strcmp (attr->name, "iat"))
- {
- token_add_attr_int (new_token, attr->name, new_iat.abs_value_us);
- }
- else if ((0 == strcmp (attr->name, "iss"))
- || (0 == strcmp (attr->name, "aud")))
- {
- //Omit
- }
- else if (0 == strcmp (attr->name, "sub"))
- {
- token_add_attr (new_token,
- attr->name,
- attr->val_head->value);
- }
- else
- {
- GNUNET_CRYPTO_hash (attr->name,
- strlen (attr->name),
- &key_hash);
- //Check if attr still exists. omit of not
- if (GNUNET_NO !=
- GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
- &key_hash))
- {
- cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
- &key_hash);
- GNUNET_assert (NULL != cur_value);
- GNUNET_CONTAINER_DLL_insert (new_token->attr_head,
- new_token->attr_tail,
- cur_value);
- }
- }
- }
+ struct AbeBootstrapHandle *abh = cls;
+ struct GNUNET_GNSRECORD_Data rd[1];
+ char *key;
+
+ rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
+ (void**)&key);
+ rd[0].data = key;
+ rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
+ rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
+ rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
+ abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+ &abh->identity,
+ "+",
+ 1,
+ rd,
+ &bootstrap_store_cont,
+ abh);
+ GNUNET_free (key);
+}
- // reassemble and set
- GNUNET_assert (token_serialize (new_token,
- priv_key,
- &new_ecdhe_privkey,
- &enc_token_str));
-
- token_record[0].data = enc_token_str;
- token_record[0].data_size = strlen (enc_token_str) + 1;
- token_record[0].expiration_time = rd_exp; //Old expiration time
- token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
- token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
-
- //Meta
- token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
- + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
- + strlen (scopes) + 1; //With 0-Terminator
- token_metadata = GNUNET_malloc (token_metadata_len);
- write_ptr = token_metadata;
- GNUNET_memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
- write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
- GNUNET_memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
- GNUNET_memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
-
- token_record[1].data = token_metadata;
- token_record[1].data_size = token_metadata_len;
- token_record[1].expiration_time = rd_exp;
- token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
- token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
-
- ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
- priv_key,
- label,
- 2,
- token_record,
- &store_token_cont,
- ego_entry);
- token_destroy (new_token);
- token_destroy (token);
- GNUNET_free (new_ecdhe_privkey);
- GNUNET_free (enc_token_str);
- token = NULL;
- GNUNET_free (label);
- label = NULL;
- GNUNET_free (scopes);
- scopes = NULL;
+/**
+ * Error checking for ABE master
+ */
+static void
+bootstrap_abe_error (void *cls)
+{
+ struct AbeBootstrapHandle *abh = cls;
+ GNUNET_free (abh);
+ abh->proc (abh->proc_cls, NULL);
+ GNUNET_free (abh);
}
+/**
+ * Handle ABE lookup in namestore
+ */
static void
-update_identities(void *cls);
+bootstrap_abe_result (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+ const char *label,
+ unsigned int rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct AbeBootstrapHandle *abh = cls;
+ struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+ for (uint32_t i=0;i<rd_count;i++) {
+ if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
+ continue;
+ abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
+ rd[i].data_size);
+ abh->proc (abh->proc_cls, abe_key);
+ GNUNET_free (abh);
+ return;
+ }
+ //No ABE master found, bootstrapping...
+ abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
+ GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
+}
/**
- *
- * Cleanup attr_map
- *
- * @param cls NULL
- * @param key the key
- * @param value the json_t attribute value
- * @return #GNUNET_YES
+ * Bootstrap ABE master if it does not yet exists.
+ * Will call the AbeBootstrapResult processor when done.
+ * will always recreate the ABE key of GNUNET_YES == recreate
*/
-static int
-clear_ego_attrs (void *cls,
- const struct GNUNET_HashCode *key,
- void *value)
-{
- struct TokenAttr *attr = value;
- struct TokenAttrValue *val;
- struct TokenAttrValue *tmp_val;
- for (val = attr->val_head; NULL != val;)
+static void
+bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+ AbeBootstrapResult proc,
+ void* cls,
+ int recreate)
+{
+ struct AbeBootstrapHandle *abh;
+
+ abh = GNUNET_new (struct AbeBootstrapHandle);
+ abh->proc = proc;
+ abh->proc_cls = cls;
+ abh->identity = *identity;
+ if (GNUNET_YES == recreate)
{
- tmp_val = val->next;
- GNUNET_CONTAINER_DLL_remove (attr->val_head,
- attr->val_tail,
- val);
- GNUNET_free (val->value);
- GNUNET_free (val);
- val = tmp_val;
+ abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
+ GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
+ } else {
+ abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
+ identity,
+ "+",
+ &bootstrap_abe_error,
+ abh,
+ &bootstrap_abe_result,
+ abh);
}
- GNUNET_free (attr->name);
- GNUNET_free (attr);
-
- return GNUNET_YES;
}
-static void
-token_collect_error_cb (void *cls)
-{
- struct EgoEntry *ego_entry = cls;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- ">>> Updating Ego failed!\n");
- //Clear attribute map for ego
- GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
- &clear_ego_attrs,
- ego_entry);
- GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
- update_task = GNUNET_SCHEDULER_add_now (&update_identities,
- ego_entry->next);
+static int
+create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
+ struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
+ struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
+{
+ struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
+
+ GNUNET_CRYPTO_hash_to_enc (new_key_hash,
+ &new_key_hash_str);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
+ static const char ctx_key[] = "gnuid-aes-ctx-key";
+ GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
+ new_key_hash, sizeof (struct GNUNET_HashCode),
+ ctx_key, strlen (ctx_key),
+ NULL, 0);
+ static const char ctx_iv[] = "gnuid-aes-ctx-iv";
+ GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
+ new_key_hash, sizeof (struct GNUNET_HashCode),
+ ctx_iv, strlen (ctx_iv),
+ NULL, 0);
+ return GNUNET_OK;
+}
+static void
+cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
+{
+ if (NULL != handle->attrs)
+ GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
+ if (NULL != handle->ns_qe)
+ GNUNET_NAMESTORE_cancel (handle->ns_qe);
+ GNUNET_free (handle);
}
static void
-token_collect_finished_cb (void *cls)
+send_ticket_result (struct IdpClient *client,
+ uint32_t r_id,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
{
- struct EgoEntry *ego_entry = cls;
+ struct TicketResultMessage *irm;
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- ">>> Updating Ego finished\n");
- //Clear attribute map for ego
- GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
- &clear_ego_attrs,
- ego_entry);
- GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
- update_task = GNUNET_SCHEDULER_add_now (&update_identities,
- ego_entry->next);
-}
+ /* store ticket in DB */
+ if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
+ ticket,
+ attrs))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to store ticket after issue\n");
+ GNUNET_break (0);
+ }
+ env = GNUNET_MQ_msg_extra (irm,
+ sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
+ ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
+ *ticket_buf = *ticket;
+ irm->id = htonl (r_id);
+ GNUNET_MQ_send (client->mq,
+ env);
+}
-/**
- *
- * Update all ID_TOKEN records for an identity and store them
- *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
- */
static void
-token_collect (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
- const char *lbl,
- unsigned int rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
-{
- struct EgoEntry *ego_entry = cls;
- const struct GNUNET_GNSRECORD_Data *token_record;
- const struct GNUNET_GNSRECORD_Data *token_metadata_record;
- struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
- struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key;
-
- //There should be only a single record for a token under a label
- if (2 != rd_count)
+store_ticket_issue_cont (void *cls,
+ int32_t success,
+ const char *emsg)
+{
+ struct TicketIssueHandle *handle = cls;
+
+ handle->ns_qe = NULL;
+ if (GNUNET_SYSERR == success)
{
- GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+ cleanup_ticket_issue_handle (handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
+ "Unknown Error\n");
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
return;
}
+ send_ticket_result (handle->client,
+ handle->r_id,
+ &handle->ticket,
+ handle->attrs);
+ cleanup_ticket_issue_handle (handle);
+}
- if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
- {
- token_metadata_record = &rd[0];
- token_record = &rd[1];
+
+
+int
+serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+ const struct GNUNET_ABE_AbeKey *rp_key,
+ struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
+ char **result)
+{
+ struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ char *enc_keyinfo;
+ char *serialized_key;
+ char *buf;
+ char *write_ptr;
+ char attrs_str_len;
+ ssize_t size;
+
+ struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+ struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+ struct GNUNET_HashCode new_key_hash;
+ ssize_t enc_size;
+
+ size = GNUNET_ABE_cpabe_serialize_key (rp_key,
+ (void**)&serialized_key);
+ attrs_str_len = 0;
+ for (le = attrs->list_head; NULL != le; le = le->next) {
+ attrs_str_len += strlen (le->claim->name) + 1;
}
- else
- {
- token_record = &rd[0];
- token_metadata_record = &rd[1];
+ buf = GNUNET_malloc (attrs_str_len + size);
+ write_ptr = buf;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Writing attributes\n");
+ for (le = attrs->list_head; NULL != le; le = le->next) {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s\n", le->claim->name);
+
+
+ GNUNET_memcpy (write_ptr,
+ le->claim->name,
+ strlen (le->claim->name));
+ write_ptr[strlen (le->claim->name)] = ',';
+ write_ptr += strlen (le->claim->name) + 1;
}
- if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
- {
- GNUNET_NAMESTORE_zone_iterator_next (ns_it);
- return;
+ write_ptr--;
+ write_ptr[0] = '\0'; //replace last , with a 0-terminator
+ write_ptr++;
+ GNUNET_memcpy (write_ptr,
+ serialized_key,
+ size);
+ GNUNET_free (serialized_key);
+ // ECDH keypair E = eG
+ *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
+ GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
+ &ecdh_pubkey);
+ enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
+ // Derived key K = H(eB)
+ GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
+ &ticket->audience,
+ &new_key_hash));
+ create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
+ enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
+ size + attrs_str_len,
+ &skey, &iv,
+ enc_keyinfo);
+ *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
+ enc_size);
+ GNUNET_memcpy (*result,
+ &ecdh_pubkey,
+ sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+ GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
+ enc_keyinfo,
+ enc_size);
+ GNUNET_free (enc_keyinfo);
+ GNUNET_free (buf);
+ return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
+}
+
+
+
+static void
+issue_ticket_after_abe_bootstrap (void *cls,
+ struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+ struct TicketIssueHandle *ih = cls;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+ struct GNUNET_GNSRECORD_Data code_record[1];
+ struct GNUNET_ABE_AbeKey *rp_key;
+ char *code_record_data;
+ char **attrs;
+ char *label;
+ char *policy;
+ int attrs_len;
+ uint32_t i;
+ size_t code_record_len;
+
+ //Create new ABE key for RP
+ attrs_len = 0;
+ for (le = ih->attrs->list_head; NULL != le; le = le->next)
+ attrs_len++;
+ attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
+ i = 0;
+ for (le = ih->attrs->list_head; NULL != le; le = le->next) {
+ GNUNET_asprintf (&policy, "%s_%lu",
+ le->claim->name,
+ le->claim->version);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding attribute to key: %s\n",
+ policy);
+ attrs[i] = policy;
+ i++;
}
- if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
+ attrs[i] = NULL;
+ rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
+ attrs);
+
+ //TODO review this wireformat
+ code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
+ ih->attrs,
+ rp_key,
+ &ecdhe_privkey,
+ &code_record_data);
+ code_record[0].data = code_record_data;
+ code_record[0].data_size = code_record_len;
+ code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+ code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
+ code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+
+ label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
+ sizeof (uint64_t));
+ //Publish record
+ ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+ &ih->identity,
+ label,
+ 1,
+ code_record,
+ &store_ticket_issue_cont,
+ ih);
+ //for (; i > 0; i--)
+ // GNUNET_free (attrs[i-1]);
+ GNUNET_free (ecdhe_privkey);
+ GNUNET_free (label);
+ GNUNET_free (attrs);
+ GNUNET_free (code_record_data);
+ GNUNET_ABE_cpabe_delete_key (rp_key,
+ GNUNET_YES);
+ GNUNET_ABE_cpabe_delete_master_key (abe_key);
+}
+
+
+static int
+check_issue_ticket_message(void *cls,
+ const struct IssueTicketMessage *im)
+{
+ uint16_t size;
+
+ size = ntohs (im->header.size);
+ if (size <= sizeof (struct IssueTicketMessage))
{
- GNUNET_NAMESTORE_zone_iterator_next (ns_it);
- return;
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
}
+ return GNUNET_OK;
+}
- //Get metadata and decrypt token
- priv_key = (struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data;
- ecdhe_privkey = *priv_key;
- aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&priv_key[1];
- scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- token_parse2 (token_record->data,
- &ecdhe_privkey,
- aud_key,
- &token);
+static void
+handle_issue_ticket_message (void *cls,
+ const struct IssueTicketMessage *im)
+{
+ struct TicketIssueHandle *ih;
+ struct IdpClient *idp = cls;
+ size_t attrs_len;
+
+ ih = GNUNET_new (struct TicketIssueHandle);
+ attrs_len = ntohs (im->attr_len);
+ ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
+ ih->r_id = ntohl (im->id);
+ ih->client = idp;
+ ih->identity = im->identity;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
+ &ih->ticket.identity);
+ ih->ticket.audience = im->rp;
+ ih->ticket.rnd =
+ GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
+ UINT64_MAX);
+ bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
+ GNUNET_SERVICE_client_continue (idp->client);
- label = GNUNET_strdup (lbl);
- rd_exp = token_record->expiration_time;
+}
- GNUNET_SCHEDULER_add_now (&handle_token_update,
- ego_entry);
+/**********************************************************
+ * Revocation
+ **********************************************************/
+
+/**
+ * Cleanup revoke handle
+ *
+ * @param rh the ticket revocation handle
+ */
+static void
+cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
+{
+ if (NULL != rh->attrs)
+ GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->attrs);
+ if (NULL != rh->rvk_attrs)
+ GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->rvk_attrs);
+ if (NULL != rh->abe_key)
+ GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
+ if (NULL != rh->ns_qe)
+ GNUNET_NAMESTORE_cancel (rh->ns_qe);
+ if (NULL != rh->ns_it)
+ GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
+ GNUNET_free (rh);
}
+/**
+ * Send revocation result
+ *
+ * @param rh ticket revocation handle
+ * @param success GNUNET_OK if successful result
+ */
static void
-attribute_collect_error_cb (void *cls)
+send_revocation_finished (struct TicketRevocationHandle *rh,
+ uint32_t success)
{
- struct EgoEntry *ego_entry = cls;
+ struct GNUNET_MQ_Envelope *env;
+ struct RevokeTicketResultMessage *trm;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- ">>> Updating Attributes failed!\n");
- ego_entry->attributes_dirty = GNUNET_NO;
- update_task = GNUNET_SCHEDULER_add_now (&update_identities,
- ego_entry);
+ env = GNUNET_MQ_msg (trm,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
+ trm->id = htonl (rh->r_id);
+ trm->success = htonl (success);
+ GNUNET_MQ_send (rh->client->mq,
+ env);
+ GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
+ rh->client->revocation_list_tail,
+ rh);
}
+/**
+ * Process ticket from database
+ *
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
+ */
+static void
+ticket_reissue_proc (void *cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
+
static void
-attribute_collect_finished_cb (void *cls)
+revocation_reissue_tickets (struct TicketRevocationHandle *rh);
+
+
+static void reissue_next (void *cls)
{
- struct EgoEntry *ego_entry = cls;
+ struct TicketRevocationHandle *rh = cls;
+ revocation_reissue_tickets (rh);
+}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- ">>> Updating Attributes finished\n");
- ego_entry->attributes_dirty = GNUNET_NO;
- update_task = GNUNET_SCHEDULER_add_now (&update_identities,
- ego_entry);
+
+static void
+reissue_ticket_cont (void *cls,
+ int32_t success,
+ const char *emsg)
+{
+ struct TicketRevocationHandle *rh = cls;
+
+ rh->ns_qe = NULL;
+ if (GNUNET_SYSERR == success)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
+ "Unknown Error\n");
+ send_revocation_finished (rh, GNUNET_SYSERR);
+ cleanup_revoke_ticket_handle (rh);
+ return;
+ }
+ rh->offset++;
+ GNUNET_SCHEDULER_add_now (&reissue_next, rh);
}
/**
+ * Process ticket from database
*
- * Collect all ID_ATTR records for an identity and store them
- *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
- *
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
*/
static void
-attribute_collect (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
- const char *lbl,
- unsigned int rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
-{
- struct EgoEntry *ego_entry = cls;
- struct GNUNET_HashCode key;
- struct TokenAttr *attr;
- struct TokenAttrValue *val;
- char *val_str;
- int i;
-
- if (0 == rd_count)
+ticket_reissue_proc (void *cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+ struct TicketRevocationHandle *rh = cls;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover;
+ struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+ struct GNUNET_GNSRECORD_Data code_record[1];
+ struct GNUNET_ABE_AbeKey *rp_key;
+ char *code_record_data;
+ char **attr_arr;
+ char *label;
+ char *policy;
+ int attrs_len;
+ uint32_t i;
+ int reissue_ticket;
+ size_t code_record_len;
+
+
+ if (NULL == ticket)
{
- GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Iteration done\n");
return;
}
- GNUNET_CRYPTO_hash (lbl,
- strlen (lbl),
- &key);
- if (1 == rd_count)
+
+ if (0 == memcmp (&ticket->audience,
+ &rh->ticket.audience,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
{
- if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
- {
- val_str = GNUNET_GNSRECORD_value_to_string (rd->record_type,
- rd->data,
- rd->data_size);
- attr = GNUNET_malloc (sizeof (struct TokenAttr));
- attr->name = GNUNET_strdup (lbl);
- val = GNUNET_malloc (sizeof (struct TokenAttrValue));
- val->value = val_str;
- GNUNET_CONTAINER_DLL_insert (attr->val_head,
- attr->val_tail,
- val);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
- &key,
- attr,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Do not reissue for this identity.!\n");
- GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+ rh->offset++;
+ GNUNET_SCHEDULER_add_now (&reissue_next, rh);
return;
}
- attr = GNUNET_malloc (sizeof (struct TokenAttr));
- attr->name = GNUNET_strdup (lbl);
- for (i = 0; i < rd_count; i++)
+ /*
+ * Check if any attribute of this ticket intersects with a rollover attribute
+ */
+ reissue_ticket = GNUNET_NO;
+ for (le = attrs->list_head; NULL != le; le = le->next)
{
- if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
+ for (le_rollover = rh->rvk_attrs->list_head;
+ NULL != le_rollover;
+ le_rollover = le_rollover->next)
{
- val_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
- rd[i].data,
- rd[i].data_size);
- val = GNUNET_malloc (sizeof (struct TokenAttrValue));
- val->value = val_str;
- GNUNET_CONTAINER_DLL_insert (attr->val_head,
- attr->val_tail,
- val);
+ if (0 == strcmp (le_rollover->claim->name,
+ le->claim->name))
+ {
+ reissue_ticket = GNUNET_YES;
+ le->claim->version = le_rollover->claim->version;
+ }
}
}
- GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
- &key,
- attr,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-}
-
-/**
- *
- * Update identity information for ego. If attribute map is
- * dirty, first update the attributes.
- *
- * @param cls the ego to update
- */
-static void
-update_identities(void *cls)
-{
- struct EgoEntry *next_ego = cls;
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
- update_task = NULL;
- if (NULL == next_ego)
+ if (GNUNET_NO == reissue_ticket)
{
- if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
- min_rel_exp = MIN_WAIT_TIME;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- ">>> Finished. Rescheduling in %"SCNu64"\n",
- min_rel_exp.rel_value_us);
- ns_it = NULL;
- //finished -> reschedule
- update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp,
- &update_identities,
- ego_head);
- min_rel_exp.rel_value_us = 0;
+ "Skipping ticket.\n");
+
+ rh->offset++;
+ GNUNET_SCHEDULER_add_now (&reissue_next, rh);
+
+
return;
}
- priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
- if (GNUNET_YES == next_ego->attributes_dirty)
- {
- //Starting over. We must update the Attributes for they might have changed.
- ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
- priv_key,
- &attribute_collect_error_cb,
- next_ego,
- &attribute_collect,
- next_ego,
- &attribute_collect_finished_cb,
- next_ego);
+ //Create new ABE key for RP
+ attrs_len = 0;
+
+ /* If this is the RP we want to revoke attributes of, the do so */
+
+ for (le = attrs->list_head; NULL != le; le = le->next)
+ attrs_len++;
+ attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
+ i = 0;
+ for (le = attrs->list_head; NULL != le; le = le->next) {
+ GNUNET_asprintf (&policy, "%s_%lu",
+ le->claim->name,
+ le->claim->version);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Recreating key with %s\n", policy);
+ attr_arr[i] = policy;
+ i++;
}
- else
+ attr_arr[i] = NULL;
+ rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
+ attr_arr);
+
+ //TODO review this wireformat
+ code_record_len = serialize_abe_keyinfo2 (ticket,
+ attrs,
+ rp_key,
+ &ecdhe_privkey,
+ &code_record_data);
+ code_record[0].data = code_record_data;
+ code_record[0].data_size = code_record_len;
+ code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+ code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
+ code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+
+ label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+ sizeof (uint64_t));
+ //Publish record
+ rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+ &rh->identity,
+ label,
+ 1,
+ code_record,
+ &reissue_ticket_cont,
+ rh);
+ //for (; i > 0; i--)
+ // GNUNET_free (attr_arr[i-1]);
+ GNUNET_free (ecdhe_privkey);
+ GNUNET_free (label);
+ GNUNET_free (attr_arr);
+ GNUNET_free (code_record_data);
+ GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
+}
+
+
+/* Prototype for below function */
+static void
+attr_reenc_cont (void *cls,
+ int32_t success,
+ const char *emsg);
+
+static void
+revocation_reissue_tickets (struct TicketRevocationHandle *rh)
+{
+ int ret;
+ /* Done, issue new keys */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Revocation Phase III: Reissuing Tickets\n");
+ if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
+ &rh->ticket.identity,
+ GNUNET_NO,
+ rh->offset,
+ &ticket_reissue_proc,
+ rh)))
{
- //Ego will be dirty next time
- next_ego->attributes_dirty = GNUNET_YES;
- ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
- priv_key,
- &token_collect_error_cb,
- next_ego,
- &token_collect,
- next_ego,
- &token_collect_finished_cb,
- next_ego);
+ GNUNET_break (0);
+ }
+ if (GNUNET_NO == ret)
+ {
+ send_revocation_finished (rh, GNUNET_OK);
+ cleanup_revoke_ticket_handle (rh);
+ return;
}
}
-
/**
- * Function called initially to start update task
+ * Revoke next attribte by reencryption with
+ * new ABE master
*/
static void
-init_cont ()
+reenc_next_attribute (struct TicketRevocationHandle *rh)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n");
- //Initially iterate all itenties and refresh all tokens
- update_task = GNUNET_SCHEDULER_add_now (&update_identities,
- ego_head);
+ struct GNUNET_GNSRECORD_Data rd[1];
+ char* buf;
+ char* enc_buf;
+ size_t enc_size;
+ char* rd_buf;
+ size_t buf_size;
+ char* policy;
+ uint32_t attr_ver;
+
+ if (NULL == rh->attrs->list_head)
+ {
+ revocation_reissue_tickets (rh);
+ return;
+ }
+ buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
+ buf = GNUNET_malloc (buf_size);
+ GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
+ buf);
+ rh->attrs->list_head->claim->version++;
+ GNUNET_asprintf (&policy, "%s_%lu",
+ rh->attrs->list_head->claim->name,
+ rh->attrs->list_head->claim->version);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Encrypting with policy %s\n", policy);
+ /**
+ * Encrypt the attribute value and store in namestore
+ */
+ enc_size = GNUNET_ABE_cpabe_encrypt (buf,
+ buf_size,
+ policy, //Policy
+ rh->abe_key,
+ (void**)&enc_buf);
+ GNUNET_free (buf);
+ GNUNET_free (policy);
+ rd[0].data_size = enc_size + sizeof (uint32_t);
+ rd_buf = GNUNET_malloc (rd[0].data_size);
+ attr_ver = htonl (rh->attrs->list_head->claim->version);
+ GNUNET_memcpy (rd_buf,
+ &attr_ver,
+ sizeof (uint32_t));
+ GNUNET_memcpy (rd_buf+sizeof (uint32_t),
+ enc_buf,
+ enc_size);
+ rd[0].data = rd_buf;
+ rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
+ rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
+ rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+ &rh->identity,
+ rh->attrs->list_head->claim->name,
+ 1,
+ rd,
+ &attr_reenc_cont,
+ rh);
+ GNUNET_free (enc_buf);
+ GNUNET_free (rd_buf);
}
-
/**
- * Initial ego collection function.
- *
- * @param cls NULL
- * @param ego ego
- * @param ctx context
- * @param identifier ego name
+ * Namestore callback after revoked attribute
+ * is stored
*/
static void
-list_ego (void *cls,
- struct GNUNET_IDENTITY_Ego *ego,
- void **ctx,
- const char *identifier)
+attr_reenc_cont (void *cls,
+ int32_t success,
+ const char *emsg)
{
- struct EgoEntry *new_entry;
- if ((NULL == ego) && (STATE_INIT == state))
+ struct TicketRevocationHandle *rh = cls;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+
+ if (GNUNET_SYSERR == success)
{
- state = STATE_POST_INIT;
- init_cont ();
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to reencrypt attribute %s\n",
+ emsg);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
return;
}
- if (STATE_INIT == state) {
- new_entry = GNUNET_malloc (sizeof (struct EgoEntry));
- new_entry->ego = ego;
- new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
- GNUNET_NO);
- new_entry->attributes_dirty = GNUNET_YES;
- GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
+ if (NULL == rh->attrs->list_head)
+ {
+ revocation_reissue_tickets (rh);
+ return;
}
+ le = rh->attrs->list_head;
+ GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
+ rh->attrs->list_tail,
+ le);
+ GNUNET_assert (NULL != rh->rvk_attrs);
+ GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
+ rh->rvk_attrs->list_tail,
+ le);
+
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Re-encrypting next attribute\n");
+ reenc_next_attribute (rh);
}
-/**
- * Cleanup task
- */
+
static void
-cleanup()
+process_attributes_to_update (void *cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
{
- struct EgoEntry *ego_entry;
- struct EgoEntry *ego_tmp;
+ struct TicketRevocationHandle *rh = cls;
+ rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Cleaning up\n");
- if (NULL != stats)
+ "Revocation Phase I: Collecting attributes\n");
+ /* Reencrypt all attributes with new key */
+ if (NULL == rh->attrs->list_head)
{
- GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
- stats = NULL;
+ /* No attributes to reencrypt */
+ send_revocation_finished (rh, GNUNET_OK);
+ cleanup_revoke_ticket_handle (rh);
+ return;
+ } else {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Revocation Phase II: Re-encrypting attributes\n");
+ reenc_next_attribute (rh);
}
- if (NULL != timeout_task)
- GNUNET_SCHEDULER_cancel (timeout_task);
- if (NULL != update_task)
- GNUNET_SCHEDULER_cancel (update_task);
- if (NULL != identity_handle)
- GNUNET_IDENTITY_disconnect (identity_handle);
- if (NULL != gns_handle)
- GNUNET_GNS_disconnect (gns_handle);
- if (NULL != ns_it)
- GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
- if (NULL != ns_qe)
- GNUNET_NAMESTORE_cancel (ns_qe);
- if (NULL != ns_handle)
- GNUNET_NAMESTORE_disconnect (ns_handle);
- if (NULL != token)
- GNUNET_free (token);
- if (NULL != label)
- GNUNET_free (label);
+}
- for (ego_entry = ego_head;
- NULL != ego_entry;)
- {
- ego_tmp = ego_entry;
- if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
- {
- GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
- &clear_ego_attrs,
- ego_tmp);
- }
- GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map);
- ego_entry = ego_entry->next;
- GNUNET_free (ego_tmp);
+
+static void
+get_ticket_after_abe_bootstrap (void *cls,
+ struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Finished ABE bootstrap\n");
+ struct TicketRevocationHandle *rh = cls;
+ rh->abe_key = abe_key;
+ TKT_database->get_ticket_attributes (TKT_database->cls,
+ &rh->ticket,
+ &process_attributes_to_update,
+ rh);
+}
+
+static int
+check_revoke_ticket_message(void *cls,
+ const struct RevokeTicketMessage *im)
+{
+ uint16_t size;
+
+ size = ntohs (im->header.size);
+ if (size <= sizeof (struct RevokeTicketMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
}
+ return GNUNET_OK;
}
-/**
- * Shutdown task
- *
- * @param cls NULL
- * @param tc task context
- */
static void
-do_shutdown (void *cls)
+handle_revoke_ticket_message (void *cls,
+ const struct RevokeTicketMessage *rm)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Shutting down...\n");
- cleanup();
+ struct TicketRevocationHandle *rh;
+ struct IdpClient *idp = cls;
+ struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
+
+ rh = GNUNET_new (struct TicketRevocationHandle);
+ ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
+ rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+ rh->ticket = *ticket;
+ rh->r_id = ntohl (rm->id);
+ rh->client = idp;
+ rh->identity = rm->identity;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
+ &rh->ticket.identity);
+ GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
+ idp->revocation_list_tail,
+ rh);
+ bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
+ GNUNET_SERVICE_client_continue (idp->client);
+
}
-static struct GNUNET_MQ_Envelope*
-create_exchange_result_message (const char* token,
- const char* label,
- uint64_t ticket_nonce,
- uint64_t id)
+static void
+cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
{
- struct GNUNET_MQ_Envelope *env;
- struct ExchangeResultMessage *erm;
- uint16_t token_len = strlen (token) + 1;
-
- env = GNUNET_MQ_msg_extra (erm,
- token_len,
- GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
- erm->ticket_nonce = htonl (ticket_nonce);
- erm->id = id;
- GNUNET_memcpy (&erm[1], token, token_len);
- return env;
+ if (NULL != handle->key)
+ GNUNET_ABE_cpabe_delete_key (handle->key,
+ GNUNET_YES);
+ if (NULL != handle->attrs)
+ GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
+ GNUNET_free (handle);
}
-static struct GNUNET_MQ_Envelope*
-create_issue_result_message (const char* label,
- const char* ticket,
- const char* token,
- uint64_t id)
+
+static int
+check_consume_ticket_message(void *cls,
+ const struct ConsumeTicketMessage *cm)
{
- struct GNUNET_MQ_Envelope *env;
- struct IssueResultMessage *irm;
- char *tmp_str;
- size_t len;
+ uint16_t size;
- GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token);
- len = strlen (tmp_str) + 1;
- env = GNUNET_MQ_msg_extra (irm,
- len,
- GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
- irm->id = id;
- GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1);
- GNUNET_free (tmp_str);
- return env;
+ size = ntohs (cm->header.size);
+ if (size <= sizeof (struct ConsumeTicketMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
}
static void
-cleanup_issue_handle (struct IssueHandle *handle)
-{
- if (NULL != handle->attr_map)
- GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
- if (NULL != handle->scopes)
- GNUNET_free (handle->scopes);
- if (NULL != handle->token)
- token_destroy (handle->token);
- if (NULL != handle->ticket)
- ticket_destroy (handle->ticket);
- if (NULL != handle->label)
- GNUNET_free (handle->label);
- GNUNET_free (handle);
+process_parallel_lookup2 (void *cls, uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Parallel lookup finished (count=%u)\n", rd_count);
+ struct ParallelLookup *parallel_lookup = cls;
+ struct ConsumeTicketHandle *handle = parallel_lookup->handle;
+ struct ConsumeTicketResultMessage *crm;
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le;
+ struct GNUNET_TIME_Absolute decrypt_duration;
+ char *data;
+ char *data_tmp;
+ ssize_t attr_len;
+ size_t attrs_len;
+
+ GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
+ handle->parallel_lookups_tail,
+ parallel_lookup);
+ GNUNET_free (parallel_lookup->label);
+
+ GNUNET_STATISTICS_update (stats_handle,
+ "attribute_lookup_time_total",
+ GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
+ GNUNET_YES);
+ GNUNET_STATISTICS_update (stats_handle,
+ "attribute_lookups_count",
+ 1,
+ GNUNET_YES);
+
+
+ GNUNET_free (parallel_lookup);
+ if (1 != rd_count)
+ GNUNET_break(0);//TODO
+ if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
+ {
+ decrypt_duration = GNUNET_TIME_absolute_get ();
+ attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
+ rd->data_size - sizeof (uint32_t),
+ handle->key,
+ (void**)&data);
+ if (GNUNET_SYSERR != attr_len)
+ {
+ GNUNET_STATISTICS_update (stats_handle,
+ "abe_decrypt_time_total",
+ GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
+ GNUNET_YES);
+ GNUNET_STATISTICS_update (stats_handle,
+ "abe_decrypt_count",
+ 1,
+ GNUNET_YES);
+
+ attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
+ attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data,
+ attr_len);
+ attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
+ GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
+ handle->attrs->list_tail,
+ attr_le);
+ GNUNET_free (data);
+ }
+ }
+ if (NULL != handle->parallel_lookups_head)
+ return; //Wait for more
+ /* Else we are done */
+
+ /* Store ticket in DB */
+ if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
+ &handle->ticket,
+ handle->attrs))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to store ticket after consume\n");
+ GNUNET_break (0);
+ }
+
+ GNUNET_SCHEDULER_cancel (handle->kill_task);
+ attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs);
+ env = GNUNET_MQ_msg_extra (crm,
+ attrs_len,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
+ crm->id = htonl (handle->r_id);
+ crm->attrs_len = htons (attrs_len);
+ crm->identity = handle->ticket.identity;
+ data_tmp = (char *) &crm[1];
+ GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs,
+ data_tmp);
+ GNUNET_MQ_send (handle->client->mq, env);
+ cleanup_consume_ticket_handle (handle);
}
-static void
-store_token_issue_cont (void *cls,
- int32_t success,
- const char *emsg)
+void
+abort_parallel_lookups2 (void *cls)
{
- struct IssueHandle *handle = cls;
+ struct ConsumeTicketHandle *handle = cls;
+ struct ParallelLookup *lu;
+ struct ParallelLookup *tmp;
+ struct AttributeResultMessage *arm;
struct GNUNET_MQ_Envelope *env;
- char *ticket_str;
- char *token_str;
- handle->ns_qe = NULL;
- if (GNUNET_SYSERR == success)
+ for (lu = handle->parallel_lookups_head;
+ NULL != lu;) {
+ GNUNET_GNS_lookup_cancel (lu->lookup_request);
+ GNUNET_free (lu->label);
+ tmp = lu->next;
+ GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
+ handle->parallel_lookups_tail,
+ lu);
+ GNUNET_free (lu);
+ lu = tmp;
+ }
+ env = GNUNET_MQ_msg (arm,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
+ arm->id = htonl (handle->r_id);
+ arm->attr_len = htons (0);
+ GNUNET_MQ_send (handle->client->mq, env);
+
+}
+
+
+static void
+process_consume_abe_key (void *cls, uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct ConsumeTicketHandle *handle = cls;
+ struct GNUNET_HashCode new_key_hash;
+ struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
+ struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
+ struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
+ struct ParallelLookup *parallel_lookup;
+ size_t size;
+ char *buf;
+ char *scope;
+ char *lookup_query;
+
+ handle->lookup_request = NULL;
+ if (1 != rd_count)
{
- cleanup_issue_handle (handle);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
- "Unknown Error\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Number of keys %d != 1.",
+ rd_count);
+ cleanup_consume_ticket_handle (handle);
GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
return;
}
- if (GNUNET_OK != ticket_serialize (handle->ticket,
- &handle->iss_key,
- &ticket_str))
+
+ //Decrypt
+ ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
+
+ buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+
+ //Calculate symmetric key from ecdh parameters
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
+ ecdh_key,
+ &new_key_hash));
+ create_sym_key_from_ecdh (&new_key_hash,
+ &enc_key,
+ &enc_iv);
+ size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
+ rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
+ &enc_key,
+ &enc_iv,
+ buf);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Decrypted bytes: %zd Expected bytes: %zd\n",
+ size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+ GNUNET_STATISTICS_update (stats_handle,
+ "abe_key_lookup_time_total",
+ GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
+ GNUNET_YES);
+ GNUNET_STATISTICS_update (stats_handle,
+ "abe_key_lookups_count",
+ 1,
+ GNUNET_YES);
+ scopes = GNUNET_strdup (buf);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Scopes %s\n", scopes);
+ handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
+ rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
+ - strlen (scopes) - 1);
+
+ for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
- "Error serializing ticket\n");
- cleanup_issue_handle (handle);
- GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
- return;
+ GNUNET_asprintf (&lookup_query,
+ "%s.gnu",
+ scope);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up %s\n", lookup_query);
+ parallel_lookup = GNUNET_new (struct ParallelLookup);
+ parallel_lookup->handle = handle;
+ parallel_lookup->label = GNUNET_strdup (scope);
+ parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
+ parallel_lookup->lookup_request
+ = GNUNET_GNS_lookup (gns_handle,
+ lookup_query,
+ &handle->ticket.identity,
+ GNUNET_GNSRECORD_TYPE_ID_ATTR,
+ GNUNET_GNS_LO_DEFAULT,
+ &process_parallel_lookup2,
+ parallel_lookup);
+ GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
+ handle->parallel_lookups_tail,
+ parallel_lookup);
+ GNUNET_free (lookup_query);
}
- if (GNUNET_OK != token_to_string (handle->token,
- &handle->iss_key,
- &token_str))
+ GNUNET_free (scopes);
+ GNUNET_free (buf);
+ handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
+ &abort_parallel_lookups2,
+ handle);
+}
+
+
+static void
+handle_consume_ticket_message (void *cls,
+ const struct ConsumeTicketMessage *cm)
+{
+ struct ConsumeTicketHandle *ch;
+ struct IdpClient *idp = cls;
+ char* lookup_query;
+ char* rnd_label;
+
+ ch = GNUNET_new (struct ConsumeTicketHandle);
+ ch->r_id = ntohl (cm->id);
+ ch->client = idp;
+ ch->identity = cm->identity;
+ ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+ GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
+ &ch->identity_pub);
+ ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
+ rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
+ sizeof (uint64_t));
+ GNUNET_asprintf (&lookup_query,
+ "%s.gnu",
+ rnd_label);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking for ABE key under %s\n", lookup_query);
+ ch->lookup_start_time = GNUNET_TIME_absolute_get ();
+ ch->lookup_request
+ = GNUNET_GNS_lookup (gns_handle,
+ lookup_query,
+ &ch->ticket.identity,
+ GNUNET_GNSRECORD_TYPE_ABE_KEY,
+ GNUNET_GNS_LO_DEFAULT,
+ &process_consume_abe_key,
+ ch);
+ GNUNET_free (rnd_label);
+ GNUNET_free (lookup_query);
+ GNUNET_SERVICE_client_continue (idp->client);
+}
+
+static void
+cleanup_as_handle (struct AttributeStoreHandle *handle)
+{
+ if (NULL != handle->claim)
+ GNUNET_free (handle->claim);
+ if (NULL != handle->abe_key)
+ GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
+ GNUNET_free (handle);
+}
+
+static void
+attr_store_cont (void *cls,
+ int32_t success,
+ const char *emsg)
+{
+ struct AttributeStoreHandle *as_handle = cls;
+ struct GNUNET_MQ_Envelope *env;
+ struct AttributeStoreResultMessage *acr_msg;
+
+ if (GNUNET_SYSERR == success)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
- "Error serializing token\n");
- GNUNET_free (ticket_str);
- cleanup_issue_handle (handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to store attribute %s\n",
+ emsg);
+ cleanup_as_handle (as_handle);
GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
return;
}
- env = create_issue_result_message (handle->label,
- ticket_str,
- token_str,
- handle->r_id);
- GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending ATTRIBUTE_STORE_RESPONSE message\n");
+ env = GNUNET_MQ_msg (acr_msg,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
+ acr_msg->id = htonl (as_handle->r_id);
+ acr_msg->op_result = htonl (GNUNET_OK);
+ GNUNET_MQ_send (as_handle->client->mq,
env);
- cleanup_issue_handle (handle);
- GNUNET_free (ticket_str);
- GNUNET_free (token_str);
+ cleanup_as_handle (as_handle);
}
-
-/**
- * Build a token and store it
- *
- * @param cls the IssueHandle
- */
static void
-sign_and_return_token (void *cls)
+attr_store_task (void *cls)
{
- struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
- struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
- struct IssueHandle *handle = cls;
- struct GNUNET_GNSRECORD_Data token_record[2];
- char *nonce_str;
- char *enc_token_str;
- char *token_metadata;
- char* write_ptr;
- uint64_t time;
- uint64_t exp_time;
- size_t token_metadata_len;
-
- //Remote nonce
- nonce_str = NULL;
- GNUNET_asprintf (&nonce_str, "%lu", handle->nonce);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
-
- GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
- &pub_key);
- handle->ticket = ticket_create (handle->nonce,
- &pub_key,
- handle->label,
- &handle->aud_key);
-
- time = GNUNET_TIME_absolute_get().abs_value_us;
- exp_time = time + token_expiration_interval.rel_value_us;
-
- token_add_attr_int (handle->token, "nbf", time);
- token_add_attr_int (handle->token, "iat", time);
- token_add_attr_int (handle->token, "exp", exp_time);
- token_add_attr (handle->token, "nonce", nonce_str);
-
- //Token in a serialized encrypted format
- GNUNET_assert (token_serialize (handle->token,
- &handle->iss_key,
- &ecdhe_privkey,
- &enc_token_str));
-
- //Token record E,E_K (Token)
- token_record[0].data = enc_token_str;
- token_record[0].data_size = strlen (enc_token_str) + 1;
- token_record[0].expiration_time = exp_time;
- token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
- token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
-
-
- token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
- + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
- + strlen (handle->scopes) + 1; //With 0-Terminator
- token_metadata = GNUNET_malloc (token_metadata_len);
- write_ptr = token_metadata;
- GNUNET_memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
- write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
- GNUNET_memcpy (write_ptr, &handle->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
- GNUNET_memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); //with 0-Terminator;
-
- token_record[1].data = token_metadata;
- token_record[1].data_size = token_metadata_len;
- token_record[1].expiration_time = exp_time;
- token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
- token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
-
- //Persist token
- handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
- &handle->iss_key,
- handle->label,
- 2,
- token_record,
- &store_token_issue_cont,
- handle);
- GNUNET_free (ecdhe_privkey);
- GNUNET_free (nonce_str);
- GNUNET_free (enc_token_str);
- GNUNET_free (token_metadata);
+ struct AttributeStoreHandle *as_handle = cls;
+ struct GNUNET_GNSRECORD_Data rd[1];
+ char* buf;
+ char* policy;
+ char* enc_buf;
+ char* rd_buf;
+ size_t enc_size;
+ size_t buf_size;
+ uint32_t attr_ver;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Storing attribute\n");
+ buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim);
+ buf = GNUNET_malloc (buf_size);
+
+ GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim,
+ buf);
+
+ GNUNET_asprintf (&policy,
+ "%s_%lu",
+ as_handle->claim->name,
+ as_handle->claim->version);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Encrypting with policy %s\n", policy);
+ /**
+ * Encrypt the attribute value and store in namestore
+ */
+ enc_size = GNUNET_ABE_cpabe_encrypt (buf,
+ buf_size,
+ policy, //Policy
+ as_handle->abe_key,
+ (void**)&enc_buf);
+ GNUNET_free (buf);
+ GNUNET_free (policy);
+ rd[0].data_size = enc_size + sizeof (uint32_t);
+ rd_buf = GNUNET_malloc (rd[0].data_size);
+ attr_ver = htonl (as_handle->claim->version);
+ GNUNET_memcpy (rd_buf,
+ &attr_ver,
+ sizeof (uint32_t));
+ GNUNET_memcpy (rd_buf+sizeof (uint32_t),
+ enc_buf,
+ enc_size);
+ rd[0].data = rd_buf;
+ rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
+ rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
+ as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+ &as_handle->identity,
+ as_handle->claim->name,
+ 1,
+ rd,
+ &attr_store_cont,
+ as_handle);
+ GNUNET_free (enc_buf);
+ GNUNET_free (rd_buf);
}
static void
-attr_collect_error (void *cls)
+store_after_abe_bootstrap (void *cls,
+ struct GNUNET_ABE_AbeMasterKey *abe_key)
{
- struct IssueHandle *handle = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Finished ABE bootstrap\n");
+ struct AttributeStoreHandle *ash = cls;
+ ash->abe_key = abe_key;
+ GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
+}
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n");
- handle->ns_it = NULL;
- GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+static int
+check_attribute_store_message(void *cls,
+ const struct AttributeStoreMessage *sam)
+{
+ uint16_t size;
+
+ size = ntohs (sam->header.size);
+ if (size <= sizeof (struct AttributeStoreMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
}
static void
-attr_collect_finished (void *cls)
+handle_attribute_store_message (void *cls,
+ const struct AttributeStoreMessage *sam)
{
- struct IssueHandle *handle = cls;
+ struct AttributeStoreHandle *as_handle;
+ struct IdpClient *idp = cls;
+ size_t data_len;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received ATTRIBUTE_STORE message\n");
+
+ data_len = ntohs (sam->attr_len);
+
+ as_handle = GNUNET_new (struct AttributeStoreHandle);
+ as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1],
+ data_len);
+
+ as_handle->r_id = ntohl (sam->id);
+ as_handle->identity = sam->identity;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
+ &as_handle->identity_pkey);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
- handle->ns_it = NULL;
- GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+ GNUNET_SERVICE_client_continue (idp->client);
+ as_handle->client = idp;
+ bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
}
+static void
+cleanup_iter_handle (struct AttributeIterator *ai)
+{
+ if (NULL != ai->abe_key)
+ GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
+ GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
+ ai->client->op_tail,
+ ai);
+ GNUNET_free (ai);
+}
+
+static void
+attr_iter_error (void *cls)
+{
+ struct AttributeIterator *ai = cls;
+ //TODO
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to iterate over attributes\n");
+ cleanup_iter_handle (ai);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+}
+
+static void
+attr_iter_finished (void *cls)
+{
+ struct AttributeIterator *ai = cls;
+ struct GNUNET_MQ_Envelope *env;
+ struct AttributeResultMessage *arm;
+
+ env = GNUNET_MQ_msg (arm,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
+ arm->id = htonl (ai->request_id);
+ arm->attr_len = htons (0);
+ GNUNET_MQ_send (ai->client->mq, env);
+ cleanup_iter_handle (ai);
+}
-/**
- * Collect attributes for token
- */
static void
-attr_collect (void *cls,
+attr_iter_cb (void *cls,
const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
const char *label,
unsigned int rd_count,
const struct GNUNET_GNSRECORD_Data *rd)
{
- struct IssueHandle *handle = cls;
- int i;
- char* data;
- struct GNUNET_HashCode key;
-
- GNUNET_CRYPTO_hash (label,
- strlen (label),
- &key);
-
- if (0 == rd_count ||
- ( (NULL != handle->attr_map) &&
- (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map,
- &key))
- )
- )
+ struct AttributeIterator *ai = cls;
+ struct AttributeResultMessage *arm;
+ struct GNUNET_ABE_AbeKey *key;
+ struct GNUNET_MQ_Envelope *env;
+ ssize_t msg_extra_len;
+ char* attr_ser;
+ char* attrs[2];
+ char* data_tmp;
+ char* policy;
+ uint32_t attr_ver;
+
+ if (rd_count != 1)
{
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+ GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
-
- if (1 == rd_count)
- {
- if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
- {
- data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
- rd->data,
- rd->data_size);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
- token_add_attr (handle->token,
- label,
- data);
- GNUNET_free (data);
- }
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+ if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
+ GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
return;
}
+ attr_ver = ntohl(*((uint32_t*)rd->data));
+ GNUNET_asprintf (&policy, "%s_%lu",
+ label, attr_ver);
+ attrs[0] = policy;
+ attrs[1] = 0;
+ key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
+ attrs);
+ msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
+ rd->data_size-sizeof (uint32_t),
+ key,
+ (void**)&attr_ser);
+
+ GNUNET_ABE_cpabe_delete_key (key,
+ GNUNET_YES);
+ //GNUNET_free (policy);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found attribute: %s\n", label);
+ env = GNUNET_MQ_msg_extra (arm,
+ msg_extra_len,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
+ arm->id = htonl (ai->request_id);
+ arm->attr_len = htons (msg_extra_len);
+ GNUNET_CRYPTO_ecdsa_key_get_public (zone,
+ &arm->identity);
+ data_tmp = (char *) &arm[1];
+ GNUNET_memcpy (data_tmp,
+ attr_ser,
+ msg_extra_len);
+ GNUNET_MQ_send (ai->client->mq, env);
+ GNUNET_free (attr_ser);
+ GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
+ ai->abe_key = NULL;
+}
- i = 0;
- for (; i < rd_count; i++)
- {
- if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
- {
- data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
- rd[i].data,
- rd[i].data_size);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
- token_add_attr (handle->token, label, data);
- GNUNET_free (data);
- }
- }
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+void
+iterate_after_abe_bootstrap (void *cls,
+ struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+ struct AttributeIterator *ai = cls;
+ ai->abe_key = abe_key;
+ ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+ &ai->identity,
+ &attr_iter_error,
+ ai,
+ &attr_iter_cb,
+ ai,
+ &attr_iter_finished,
+ ai);
}
+void
+iterate_next_after_abe_bootstrap (void *cls,
+ struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+ struct AttributeIterator *ai = cls;
+ ai->abe_key = abe_key;
+ GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
+}
+
+
+
static void
-cleanup_exchange_handle (struct ExchangeHandle *handle)
+handle_iteration_start (void *cls,
+ const struct AttributeIterationStartMessage *ais_msg)
{
- if (NULL != handle->ticket)
- ticket_destroy (handle->ticket);
- if (NULL != handle->token)
- token_destroy (handle->token);
- GNUNET_free (handle);
+ struct IdpClient *idp = cls;
+ struct AttributeIterator *ai;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received ATTRIBUTE_ITERATION_START message\n");
+ ai = GNUNET_new (struct AttributeIterator);
+ ai->request_id = ntohl (ais_msg->id);
+ ai->client = idp;
+ ai->identity = ais_msg->identity;
+
+ GNUNET_CONTAINER_DLL_insert (idp->op_head,
+ idp->op_tail,
+ ai);
+ bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
+ GNUNET_SERVICE_client_continue (idp->client);
}
+
static void
-process_lookup_result (void *cls, uint32_t rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
+handle_iteration_stop (void *cls,
+ const struct AttributeIterationStopMessage *ais_msg)
{
- struct ExchangeHandle *handle = cls;
- struct GNUNET_MQ_Envelope *env;
- char* token_str;
- char* record_str;
+ struct IdpClient *idp = cls;
+ struct AttributeIterator *ai;
+ uint32_t rid;
- handle->lookup_request = NULL;
- if (2 != rd_count)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received `%s' message\n",
+ "ATTRIBUTE_ITERATION_STOP");
+ rid = ntohl (ais_msg->id);
+ for (ai = idp->op_head; NULL != ai; ai = ai->next)
+ if (ai->request_id == rid)
+ break;
+ if (NULL == ai)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Number of tokens %d != 2.",
- rd_count);
- cleanup_exchange_handle (handle);
- GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ GNUNET_break (0);
+ GNUNET_SERVICE_client_drop (idp->client);
return;
}
-
- record_str =
- GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN,
- rd->data,
- rd->data_size);
-
- //Decrypt and parse
- GNUNET_assert (GNUNET_OK == token_parse (record_str,
- &handle->aud_privkey,
- &handle->token));
-
- //Readable
- GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
- &handle->aud_privkey,
- &token_str));
-
- env = create_exchange_result_message (token_str,
- handle->label,
- handle->ticket->payload->nonce,
- handle->r_id);
- GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
- env);
- cleanup_exchange_handle (handle);
- GNUNET_free (record_str);
- GNUNET_free (token_str);
+ GNUNET_CONTAINER_DLL_remove (idp->op_head,
+ idp->op_tail,
+ ai);
+ GNUNET_free (ai);
+ GNUNET_SERVICE_client_continue (idp->client);
}
-/**
- * Checks a exchange message
- *
- * @param cls client sending the message
- * @param xm message of type `struct ExchangeMessage`
- * @return #GNUNET_OK if @a xm is well-formed
- */
-static int
-check_exchange_message (void *cls,
- const struct ExchangeMessage *xm)
+
+static void
+handle_iteration_next (void *cls,
+ const struct AttributeIterationNextMessage *ais_msg)
{
- uint16_t size;
+ struct IdpClient *idp = cls;
+ struct AttributeIterator *ai;
+ uint32_t rid;
- size = ntohs (xm->header.size);
- if (size <= sizeof (struct ExchangeMessage))
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received ATTRIBUTE_ITERATION_NEXT message\n");
+ rid = ntohl (ais_msg->id);
+ for (ai = idp->op_head; NULL != ai; ai = ai->next)
+ if (ai->request_id == rid)
+ break;
+ if (NULL == ai)
{
GNUNET_break (0);
- return GNUNET_SYSERR;
+ GNUNET_SERVICE_client_drop (idp->client);
+ return;
}
- return GNUNET_OK;
+ bootstrap_abe (&ai->identity,
+ &iterate_next_after_abe_bootstrap,
+ ai,
+ GNUNET_NO);
+ GNUNET_SERVICE_client_continue (idp->client);
}
/**
- *
- * Handler for exchange message
- *
- * @param cls unused
- * @param client who sent the message
- * @param message the message
+ * Ticket iteration processor result
*/
-static void
-handle_exchange_message (void *cls,
- const struct ExchangeMessage *xm)
+enum ZoneIterationResult
{
- struct ExchangeHandle *xchange_handle;
- struct GNUNET_SERVICE_Client *client = cls;
- const char *ticket;
- char *lookup_query;
+ /**
+ * Iteration start.
+ */
+ IT_START = 0,
- ticket = (const char *) &xm[1];
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received EXCHANGE of `%s' from client\n",
- ticket);
- xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle));
- xchange_handle->aud_privkey = xm->aud_privkey;
- xchange_handle->r_id = xm->id;
- if (GNUNET_SYSERR == ticket_parse (ticket,
- &xchange_handle->aud_privkey,
- &xchange_handle->ticket))
- {
- GNUNET_free (xchange_handle);
- GNUNET_SERVICE_client_drop (client);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for token under %s\n",
- xchange_handle->ticket->payload->label);
- GNUNET_asprintf (&lookup_query,
- "%s.gnu",
- xchange_handle->ticket->payload->label);
- GNUNET_SERVICE_client_continue (client);
- xchange_handle->client = client;
- xchange_handle->lookup_request
- = GNUNET_GNS_lookup (gns_handle,
- lookup_query,
- &xchange_handle->ticket->payload->identity_key,
- GNUNET_GNSRECORD_TYPE_ID_TOKEN,
- GNUNET_GNS_LO_LOCAL_MASTER,
- &process_lookup_result,
- xchange_handle);
- GNUNET_free (lookup_query);
+ /**
+ * Found tickets,
+ * Continue to iterate with next iteration_next call
+ */
+ IT_SUCCESS_MORE_AVAILABLE = 1,
-}
+ /**
+ * Iteration complete
+ */
+ IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
+};
-static void
-find_existing_token_error (void *cls)
+/**
+ * Context for ticket iteration
+ */
+struct TicketIterationProcResult
{
- struct IssueHandle *handle = cls;
- cleanup_issue_handle (handle);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error looking for existing token\n");
- GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-}
+ /**
+ * The ticket iteration handle
+ */
+ struct TicketIteration *ti;
+ /**
+ * Iteration result: iteration done?
+ * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
+ * we got one for now and have sent it to the client
+ * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
+ * #IT_START: if we are still trying to find a result.
+ */
+ int res_iteration_finished;
+
+};
static void
-find_existing_token_finished (void *cls)
+cleanup_ticket_iter_handle (struct TicketIteration *ti)
{
- struct IssueHandle *handle = cls;
- uint64_t rnd_key;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- ">>> No existing token found\n");
- rnd_key =
- GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
- UINT64_MAX);
- GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
- sizeof (uint64_t),
- &handle->label);
- handle->ns_it = NULL;
- handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
- &handle->iss_key,
- &attr_collect_error,
- handle,
- &attr_collect,
- handle,
- &attr_collect_finished,
- handle);
+ GNUNET_free (ti);
}
-
/**
+ * Process ticket from database
*
- * Look for existing token
- *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
- *
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
*/
static void
-find_existing_token (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
- const char *lbl,
- unsigned int rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
-{
- struct IssueHandle *handle = cls;
- const struct GNUNET_GNSRECORD_Data *token_metadata_record;
- struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
- struct GNUNET_HashCode key;
- int scope_count_token;
- char *scope;
- char *tmp_scopes;
+ticket_iterate_proc (void *cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+ struct TicketIterationProcResult *proc = cls;
- //There should be only a single record for a token under a label
- if (2 != rd_count)
+ if (NULL == ticket)
{
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Iteration done\n");
+ proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
return;
}
+ proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
+ send_ticket_result (proc->ti->client,
+ proc->ti->r_id,
+ ticket,
+ attrs);
- if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
- {
- token_metadata_record = &rd[0];
- }
- else
- {
- token_metadata_record = &rd[1];
- }
- if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
- {
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
- return;
- }
- ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
- aud_key =
- (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
- tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+}
- if (0 != memcmp (aud_key, &handle->aud_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- {
- char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- //Audience does not match!
- char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA,
- token_metadata_record->data,
- token_metadata_record->data_size);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Token does not match audience %s vs %s. Moving on\n",
- tmp2,
- tmp);
- GNUNET_free (tmp_scopes);
- GNUNET_free (tmp2);
- GNUNET_free (tmp);
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
- return;
- }
+/**
+ * Perform ticket iteration step
+ *
+ * @param ti ticket iterator to process
+ */
+static void
+run_ticket_iteration_round (struct TicketIteration *ti)
+{
+ struct TicketIterationProcResult proc;
+ struct GNUNET_MQ_Envelope *env;
+ struct TicketResultMessage *trm;
+ int ret;
- scope = strtok (tmp_scopes, ",");
- scope_count_token = 0;
- while (NULL != scope)
+ memset (&proc, 0, sizeof (proc));
+ proc.ti = ti;
+ proc.res_iteration_finished = IT_START;
+ while (IT_START == proc.res_iteration_finished)
{
- GNUNET_CRYPTO_hash (scope,
- strlen (scope),
- &key);
-
- if ((NULL != handle->attr_map) &&
- (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key)))
+ if (GNUNET_SYSERR ==
+ (ret = TKT_database->iterate_tickets (TKT_database->cls,
+ &ti->identity,
+ ti->is_audience,
+ ti->offset,
+ &ticket_iterate_proc,
+ &proc)))
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Issued token does not include `%s'. Moving on\n", scope);
- GNUNET_free (tmp_scopes);
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
- return;
+ GNUNET_break (0);
+ break;
}
- scope_count_token++;
- scope = strtok (NULL, ",");
+ if (GNUNET_NO == ret)
+ proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
+ ti->offset++;
}
- GNUNET_free (tmp_scopes);
- //All scopes in token are also in request. Now
- //Check length
- if ((NULL != handle->attr_map) &&
- (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == scope_count_token))
+ if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
{
- //We have an existing token
- handle->label = GNUNET_strdup (lbl);
- handle->ns_it = NULL;
- handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
- &handle->iss_key,
- &attr_collect_error,
- handle,
- &attr_collect,
- handle,
- &attr_collect_finished,
- handle);
-
- return;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "More results available\n");
+ return; /* more later */
}
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Nuber of attributes in token do not match request\n");
- //No luck
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+ /* send empty response to indicate end of list */
+ env = GNUNET_MQ_msg (trm,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
+ trm->id = htonl (ti->r_id);
+ GNUNET_MQ_send (ti->client->mq,
+ env);
+ GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
+ ti->client->ticket_iter_tail,
+ ti);
+ cleanup_ticket_iter_handle (ti);
}
-/**
- * Checks an issue message
- *
- * @param cls client sending the message
- * @param im message of type `struct IssueMessage`
- * @return #GNUNET_OK if @a im is well-formed
- */
-static int
-check_issue_message(void *cls,
- const struct IssueMessage *im)
+static void
+handle_ticket_iteration_start (void *cls,
+ const struct TicketIterationStartMessage *tis_msg)
{
- uint16_t size;
+ struct IdpClient *client = cls;
+ struct TicketIteration *ti;
- size = ntohs (im->header.size);
- if (size <= sizeof (struct IssueMessage))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- scopes = (char *) &im[1];
- if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1])
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received TICKET_ITERATION_START message\n");
+ ti = GNUNET_new (struct TicketIteration);
+ ti->r_id = ntohl (tis_msg->id);
+ ti->offset = 0;
+ ti->client = client;
+ ti->identity = tis_msg->identity;
+ ti->is_audience = ntohl (tis_msg->is_audience);
+
+ GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
+ client->ticket_iter_tail,
+ ti);
+ run_ticket_iteration_round (ti);
+ GNUNET_SERVICE_client_continue (client->client);
+}
+
+
+static void
+handle_ticket_iteration_stop (void *cls,
+ const struct TicketIterationStopMessage *tis_msg)
+{
+ struct IdpClient *client = cls;
+ struct TicketIteration *ti;
+ uint32_t rid;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received `%s' message\n",
+ "TICKET_ITERATION_STOP");
+ rid = ntohl (tis_msg->id);
+ for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
+ if (ti->r_id == rid)
+ break;
+ if (NULL == ti)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Malformed scopes received!\n");
GNUNET_break (0);
- return GNUNET_SYSERR;
+ GNUNET_SERVICE_client_drop (client->client);
+ return;
}
- return GNUNET_OK;
+ GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
+ client->ticket_iter_tail,
+ ti);
+ cleanup_ticket_iter_handle (ti);
+ GNUNET_SERVICE_client_continue (client->client);
}
-/**
- *
- * Handler for issue message
- *
- * @param cls unused
- * @param client who sent the message
- * @param message the message
- */
+
static void
-handle_issue_message (void *cls,
- const struct IssueMessage *im)
+handle_ticket_iteration_next (void *cls,
+ const struct TicketIterationNextMessage *tis_msg)
{
- const char *scopes;
- char *scopes_tmp;
- char *scope;
- struct GNUNET_HashCode key;
- struct IssueHandle *issue_handle;
- struct GNUNET_SERVICE_Client *client = cls;
-
- scopes = (const char *) &im[1];
- issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
- issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
- GNUNET_NO);
- scopes_tmp = GNUNET_strdup (scopes);
+ struct IdpClient *client = cls;
+ struct TicketIteration *ti;
+ uint32_t rid;
- for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received TICKET_ITERATION_NEXT message\n");
+ rid = ntohl (tis_msg->id);
+ for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
+ if (ti->r_id == rid)
+ break;
+ if (NULL == ti)
{
- GNUNET_CRYPTO_hash (scope,
- strlen (scope),
- &key);
- GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
- &key,
- scope,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+ GNUNET_break (0);
+ GNUNET_SERVICE_client_drop (client->client);
+ return;
}
- GNUNET_free (scopes_tmp);
- issue_handle->r_id = im->id;
- issue_handle->aud_key = im->aud_key;
- issue_handle->iss_key = im->iss_key;
- GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
- &issue_handle->iss_pkey);
- issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
- issue_handle->nonce = ntohl (im->nonce);
- GNUNET_SERVICE_client_continue (client);
- issue_handle->client = client;
- issue_handle->scopes = GNUNET_strdup (scopes);
- issue_handle->token = token_create (&issue_handle->iss_pkey,
- &issue_handle->aud_key);
-
- issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
- &im->iss_key,
- &find_existing_token_error,
- issue_handle,
- &find_existing_token,
- issue_handle,
- &find_existing_token_finished,
- issue_handle);
+ run_ticket_iteration_round (ti);
+ GNUNET_SERVICE_client_continue (client->client);
}
+
+
/**
* Main function that will be run
*
* @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL)
- * @param c configuration
+ * @param c the configuration used
+ * @param server the service handle
*/
static void
run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *c,
struct GNUNET_SERVICE_Handle *server)
{
+ char *database;
cfg = c;
stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
@@ -1606,10 +2384,38 @@ run (void *cls,
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
}
-
+ credential_handle = GNUNET_CREDENTIAL_connect (cfg);
+ if (NULL == credential_handle)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
+ }
identity_handle = GNUNET_IDENTITY_connect (cfg,
- &list_ego,
+ NULL,
NULL);
+ stats_handle = GNUNET_STATISTICS_create ("identity-provider",
+ cfg);
+ /* Loading DB plugin */
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "identity-provider",
+ "database",
+ &database))
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No database backend configured\n");
+ GNUNET_asprintf (&db_lib_name,
+ "libgnunet_plugin_identity_provider_%s",
+ database);
+ TKT_database = GNUNET_PLUGIN_load (db_lib_name,
+ (void *) cfg);
+ GNUNET_free (database);
+ if (NULL == TKT_database)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Could not load database backend `%s'\n",
+ db_lib_name);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
if (GNUNET_OK ==
GNUNET_CONFIGURATION_get_value_time (cfg,
@@ -1640,9 +2446,39 @@ client_disconnect_cb (void *cls,
struct GNUNET_SERVICE_Client *client,
void *app_ctx)
{
+ struct IdpClient *idp = app_ctx;
+ struct AttributeIterator *ai;
+ struct TicketIteration *ti;
+ struct TicketRevocationHandle *rh;
+
+ //TODO other operations
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client %p disconnected\n",
client);
+
+ while (NULL != (ai = idp->op_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (idp->op_head,
+ idp->op_tail,
+ ai);
+ GNUNET_free (ai);
+ }
+ while (NULL != (rh = idp->revocation_list_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
+ idp->revocation_list_tail,
+ rh);
+ cleanup_revoke_ticket_handle (rh);
+ }
+ while (NULL != (ti = idp->ticket_iter_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
+ idp->ticket_iter_tail,
+ ti);
+ cleanup_ticket_iter_handle (ti);
+ }
+ GNUNET_free (idp);
}
@@ -1659,10 +2495,14 @@ client_connect_cb (void *cls,
struct GNUNET_SERVICE_Client *client,
struct GNUNET_MQ_Handle *mq)
{
+ struct IdpClient *idp;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client %p connected\n",
client);
- return client;
+ idp = GNUNET_new (struct IdpClient);
+ idp->client = client;
+ idp->mq = mq;
+ return idp;
}
@@ -1677,13 +2517,45 @@ GNUNET_SERVICE_MAIN
&client_connect_cb,
&client_disconnect_cb,
NULL,
- GNUNET_MQ_hd_var_size (issue_message,
- GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE,
- struct IssueMessage,
+ GNUNET_MQ_hd_var_size (attribute_store_message,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
+ struct AttributeStoreMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_start,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
+ struct AttributeIterationStartMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_next,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
+ struct AttributeIterationNextMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_stop,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
+ struct AttributeIterationStopMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (issue_ticket_message,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
+ struct IssueTicketMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (consume_ticket_message,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
+ struct ConsumeTicketMessage,
NULL),
- GNUNET_MQ_hd_var_size (exchange_message,
- GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE,
- struct ExchangeMessage,
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
+ struct TicketIterationStartMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
+ struct TicketIterationNextMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
+ struct TicketIterationStopMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (revoke_ticket_message,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
+ struct RevokeTicketMessage,
NULL),
GNUNET_MQ_handler_end());
/* 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
UNIX_MATCH_UID = NO
UNIX_MATCH_GID = YES
TOKEN_EXPIRATION_INTERVAL = 30 m
+DATABASE = sqlite
+
+[identity-provider-sqlite]
+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..b1fe6e1fd 100644
--- a/src/identity-provider/identity_provider.h
+++ b/src/identity-provider/identity_provider.h
@@ -34,34 +34,157 @@
GNUNET_NETWORK_STRUCT_BEGIN
/**
- * The token
+ * Use to store an identity attribute
*/
-struct GNUNET_IDENTITY_PROVIDER_Token
+struct AttributeStoreMessage
{
/**
- * The JWT representation of the identity token
+ * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
*/
- char *data;
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * The length of the attribute
+ */
+ uint32_t attr_len GNUNET_PACKED;
+
+ /**
+ * Identity
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+ /* followed by the serialized attribute */
+
};
/**
- * The ticket
+ * Attribute store response message
*/
-struct GNUNET_IDENTITY_PROVIDER_Ticket
+struct AttributeStoreResultMessage
{
/**
- * The Base64 representation of the ticket
+ * Message header
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * #GNUNET_SYSERR on failure, #GNUNET_OK on success
+ */
+ int32_t op_result GNUNET_PACKED;
+
+};
+
+/**
+ * Attribute is returned from the idp.
+ */
+struct AttributeResultMessage
+{
+ /**
+ * Message header
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * Length of serialized attribute data
+ */
+ uint16_t attr_len GNUNET_PACKED;
+
+ /**
+ * always zero (for alignment)
+ */
+ uint16_t reserved GNUNET_PACKED;
+
+ /**
+ * The public key of the identity.
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+ /* followed by:
+ * serialized attribute data
+ */
+};
+
+
+/**
+ * Start a attribute iteration for the given identity
+ */
+struct AttributeIterationStartMessage
+{
+ /**
+ * Message
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * Identity.
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+};
+
+
+/**
+ * Ask for next result of attribute iteration for the given operation
+ */
+struct AttributeIterationNextMessage
+{
+ /**
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+};
+
+
+/**
+ * Stop attribute iteration for the given operation
+ */
+struct AttributeIterationStopMessage
+{
+ /**
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
*/
- char *data;
+ uint32_t id GNUNET_PACKED;
+
};
/**
- * Answer from service to client after issue operation
+ * Start a ticket iteration for the given identity
*/
-struct IssueResultMessage
+struct TicketIterationStartMessage
{
/**
- * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE
+ * Message
*/
struct GNUNET_MessageHeader header;
@@ -70,18 +193,25 @@ struct IssueResultMessage
*/
uint32_t id GNUNET_PACKED;
- /* followed by 0-terminated label,ticket,token */
+ /**
+ * Identity.
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+ /**
+ * Identity is audience or issuer
+ */
+ uint32_t is_audience GNUNET_PACKED;
};
/**
- * Ticket exchange message.
+ * Ask for next result of ticket iteration for the given operation
*/
-struct ExchangeResultMessage
+struct TicketIterationNextMessage
{
/**
- * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT
*/
struct GNUNET_MessageHeader header;
@@ -90,25 +220,35 @@ struct ExchangeResultMessage
*/
uint32_t id GNUNET_PACKED;
+};
+
+
+/**
+ * Stop ticket iteration for the given operation
+ */
+struct TicketIterationStopMessage
+{
/**
- * Nonce found in ticket. NBO
- * 0 on error.
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP
*/
- uint64_t ticket_nonce GNUNET_PACKED;
+ struct GNUNET_MessageHeader header;
- /* followed by 0-terminated token */
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
};
/**
- * Client requests IdP to issue token.
+ * Ticket issue message
*/
-struct IssueMessage
+struct IssueTicketMessage
{
/**
- * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET
*/
struct GNUNET_MessageHeader header;
@@ -117,40 +257,98 @@ struct IssueMessage
*/
uint32_t id GNUNET_PACKED;
+ /**
+ * Identity.
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
/**
- * Issuer identity private key
+ * Requesting party.
*/
- struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
+ struct GNUNET_CRYPTO_EcdsaPublicKey rp;
/**
- * Audience public key
+ * length of serialized attribute list
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
+ uint32_t attr_len GNUNET_PACKED;
+ //Followed by a serialized attribute list
+};
+
+/**
+ * Ticket revoke message
+ */
+struct RevokeTicketMessage
+{
/**
- * Nonce
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET
*/
- uint64_t nonce;
+ struct GNUNET_MessageHeader header;
/**
- * Expiration of token in NBO.
+ * Unique identifier for this request (for key collisions).
*/
- struct GNUNET_TIME_AbsoluteNBO expiration;
+ uint32_t id GNUNET_PACKED;
+ /**
+ * Identity.
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
- /* followed by 0-terminated comma-separated scope list */
+ /**
+ * length of serialized attribute list
+ */
+ uint32_t attrs_len GNUNET_PACKED;
+ //Followed by a ticket and serialized attribute list
+};
+
+/**
+ * Ticket revoke message
+ */
+struct RevokeTicketResultMessage
+{
+ /**
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * Revocation result
+ */
+ uint32_t success GNUNET_PACKED;
};
/**
- * Use to exchange a ticket for a token
+ * Ticket result message
*/
-struct ExchangeMessage
+struct TicketResultMessage
{
/**
- * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+};
+
+/**
+ * Ticket consume message
+ */
+struct ConsumeTicketMessage
+{
+ /**
+ * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET
*/
struct GNUNET_MessageHeader header;
@@ -160,15 +358,50 @@ struct ExchangeMessage
uint32_t id GNUNET_PACKED;
/**
- * Audience identity private key
+ * Identity.
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+ //Followed by a serialized ticket
+};
+
+/**
+ * Attribute list is returned from the idp.
+ */
+struct ConsumeTicketResultMessage
+{
+ /**
+ * Message header
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * Length of serialized attribute data
*/
- struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
+ uint16_t attrs_len GNUNET_PACKED;
- /* followed by 0-terminated ticket string */
+ /**
+ * always zero (for alignment)
+ */
+ uint16_t reserved GNUNET_PACKED;
+ /**
+ * The public key of the identity.
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+ /* followed by:
+ * serialized attributes data
+ */
};
+
GNUNET_NETWORK_STRUCT_END
#endif
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c
index 845d1f753..d0ece80fe 100644
--- a/src/identity-provider/identity_provider_api.c
+++ b/src/identity-provider/identity_provider_api.c
@@ -29,12 +29,12 @@
#include "gnunet_protocols.h"
#include "gnunet_mq_lib.h"
#include "gnunet_identity_provider_service.h"
+#include "gnunet_identity_attribute_lib.h"
#include "identity_provider.h"
#define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__)
-
/**
* Handle for an operation with the service.
*/
@@ -63,16 +63,24 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
const struct GNUNET_MessageHeader *msg;
/**
- * Continuation to invoke with the result of the transmission; @e cb
- * will be NULL in this case.
+ * Continuation to invoke after attribute store call
+ */
+ GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb;
+
+ /**
+ * Attribute result callback
+ */
+ GNUNET_IDENTITY_PROVIDER_AttributeResult ar_cb;
+
+ /**
+ * Revocation result callback
*/
- GNUNET_IDENTITY_PROVIDER_ExchangeCallback ex_cb;
+ GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus rvk_cb;
/**
- * Continuation to invoke with the result of the transmission for
- * 'issue' operations (@e cont will be NULL in this case).
+ * Ticket result callback
*/
- GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb;
+ GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
/**
* Envelope with the message for this queue entry.
@@ -91,6 +99,140 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
};
+/**
+ * Handle for a ticket iterator operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_TicketIterator
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct GNUNET_IDENTITY_PROVIDER_TicketIterator *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct GNUNET_IDENTITY_PROVIDER_TicketIterator *prev;
+
+ /**
+ * Main handle to access the idp.
+ */
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h;
+
+ /**
+ * Function to call on completion.
+ */
+ GNUNET_SCHEDULER_TaskCallback finish_cb;
+
+ /**
+ * Closure for @e error_cb.
+ */
+ void *finish_cb_cls;
+
+ /**
+ * The continuation to call with the results
+ */
+ GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
+
+ /**
+ * Closure for @e tr_cb.
+ */
+ void *cls;
+
+ /**
+ * Function to call on errors.
+ */
+ GNUNET_SCHEDULER_TaskCallback error_cb;
+
+ /**
+ * Closure for @e error_cb.
+ */
+ void *error_cb_cls;
+
+ /**
+ * Envelope of the message to send to the service, if not yet
+ * sent.
+ */
+ struct GNUNET_MQ_Envelope *env;
+
+ /**
+ * The operation id this zone iteration operation has
+ */
+ uint32_t r_id;
+
+};
+
+
+/**
+ * Handle for a attribute iterator operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_AttributeIterator
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev;
+
+ /**
+ * Main handle to access the idp.
+ */
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h;
+
+ /**
+ * Function to call on completion.
+ */
+ GNUNET_SCHEDULER_TaskCallback finish_cb;
+
+ /**
+ * Closure for @e error_cb.
+ */
+ void *finish_cb_cls;
+
+ /**
+ * The continuation to call with the results
+ */
+ GNUNET_IDENTITY_PROVIDER_AttributeResult proc;
+
+ /**
+ * Closure for @e proc.
+ */
+ void *proc_cls;
+
+ /**
+ * Function to call on errors.
+ */
+ GNUNET_SCHEDULER_TaskCallback error_cb;
+
+ /**
+ * Closure for @e error_cb.
+ */
+ void *error_cb_cls;
+
+ /**
+ * Envelope of the message to send to the service, if not yet
+ * sent.
+ */
+ struct GNUNET_MQ_Envelope *env;
+
+ /**
+ * Private key of the zone.
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+ /**
+ * The operation id this zone iteration operation has
+ */
+ uint32_t r_id;
+
+};
+
/**
* Handle for the service.
@@ -123,6 +265,27 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail;
/**
+ * Head of active iterations
+ */
+ struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head;
+
+ /**
+ * Tail of active iterations
+ */
+ struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail;
+
+ /**
+ * Head of active iterations
+ */
+ struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_head;
+
+ /**
+ * Tail of active iterations
+ */
+ struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_tail;
+
+
+ /**
* Currently pending transmission request, or NULL for none.
*/
struct GNUNET_CLIENT_TransmitHandle *th;
@@ -154,14 +317,13 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
};
-
/**
* Try again to connect to the service.
*
- * @param cls handle to the service.
+ * @param h handle to the identity provider service.
*/
static void
-reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle);
+reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
/**
* Reconnect
@@ -181,7 +343,7 @@ reconnect_task (void *cls)
/**
* Disconnect from service and then reconnect.
*
- * @param handle our handle
+ * @param handle our service
*/
static void
force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
@@ -197,6 +359,26 @@ force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
}
/**
+ * Free @a it.
+ *
+ * @param it entry to free
+ */
+static void
+free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+
+ GNUNET_CONTAINER_DLL_remove (h->it_head,
+ h->it_tail,
+ it);
+ if (NULL != it->env)
+ GNUNET_MQ_discard (it->env);
+ GNUNET_free (it);
+}
+
+
+
+/**
* Generic error handler, called with the appropriate error code and
* the same closure specified at the creation of the message queue.
* Not every message queue implementation supports an error handler.
@@ -213,22 +395,68 @@ mq_error_handler (void *cls,
}
/**
- * Check validity of message received from the service
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_attribute_store_response (void *cls,
+ const struct AttributeStoreResultMessage *msg)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+ struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+ uint32_t r_id = ntohl (msg->id);
+ int res;
+ const char *emsg;
+
+ for (op = h->op_head; NULL != op; op = op->next)
+ if (op->r_id == r_id)
+ break;
+ if (NULL == op)
+ return;
+
+ res = ntohl (msg->op_result);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received ATTRIBUTE_STORE_RESPONSE with result %d\n",
+ res);
+
+ /* TODO: add actual error message to response... */
+ if (GNUNET_SYSERR == res)
+ emsg = _("failed to store record\n");
+ else
+ emsg = NULL;
+ if (NULL != op->as_cb)
+ op->as_cb (op->cls,
+ res,
+ emsg);
+ GNUNET_CONTAINER_DLL_remove (h->op_head,
+ h->op_tail,
+ op);
+ GNUNET_free (op);
+
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
*
- * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *`
- * @param result_msg the incoming message
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static int
-check_exchange_result (void *cls,
- const struct ExchangeResultMessage *erm)
+check_consume_ticket_result (void *cls,
+ const struct ConsumeTicketResultMessage *msg)
{
- char *str;
- size_t size = ntohs (erm->header.size) - sizeof (*erm);
-
+ size_t msg_len;
+ size_t attrs_len;
- str = (char *) &erm[1];
- if ( (size > sizeof (struct ExchangeResultMessage)) &&
- ('\0' != str[size - sizeof (struct ExchangeResultMessage) - 1]) )
+ msg_len = ntohs (msg->header.size);
+ attrs_len = ntohs (msg->attrs_len);
+ if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len)
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -238,20 +466,85 @@ check_exchange_result (void *cls,
/**
- * Check validity of message received from the service
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_consume_ticket_result (void *cls,
+ const struct ConsumeTicketResultMessage *msg)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+ struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+ size_t attrs_len;
+ uint32_t r_id = ntohl (msg->id);
+
+ attrs_len = ntohs (msg->attrs_len);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing attribute result.\n");
+
+
+ for (op = h->op_head; NULL != op; op = op->next)
+ if (op->r_id == r_id)
+ break;
+ if (NULL == op)
+ return;
+
+ {
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1],
+ attrs_len);
+ if (NULL != op->ar_cb)
+ {
+ if (NULL == attrs)
+ {
+ op->ar_cb (op->cls,
+ &msg->identity,
+ NULL);
+ }
+ else
+ {
+ for (le = attrs->list_head; NULL != le; le = le->next)
+ op->ar_cb (op->cls,
+ &msg->identity,
+ le->claim);
+ GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
+ }
+ }
+ op->ar_cb (op->cls,
+ NULL,
+ NULL);
+ GNUNET_CONTAINER_DLL_remove (h->op_head,
+ h->op_tail,
+ op);
+ GNUNET_free (op);
+ return;
+ }
+ GNUNET_assert (0);
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
*
- * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *`
- * @param result_msg the incoming message
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static int
-check_result (void *cls,
- const struct IssueResultMessage *irm)
+check_attribute_result (void *cls,
+ const struct AttributeResultMessage *msg)
{
- char *str;
- size_t size = ntohs (irm->header.size) - sizeof (*irm);
- str = (char*) &irm[1];
- if ( (size > sizeof (struct IssueResultMessage)) &&
- ('\0' != str[size - sizeof (struct IssueResultMessage) - 1]) )
+ size_t msg_len;
+ size_t attr_len;
+
+ msg_len = ntohs (msg->header.size);
+ attr_len = ntohs (msg->attr_len);
+ if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -259,119 +552,254 @@ check_result (void *cls,
return GNUNET_OK;
}
+
/**
- * Handler for messages received from the GNS service
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
*
- * @param cls the `struct GNUNET_GNS_Handle *`
- * @param loookup_msg the incoming message
+ * @param cls
+ * @param msg the message we received
*/
static void
-handle_exchange_result (void *cls,
- const struct ExchangeResultMessage *erm)
+handle_attribute_result (void *cls,
+ const struct AttributeResultMessage *msg)
{
- struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
+ static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+ struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
struct GNUNET_IDENTITY_PROVIDER_Operation *op;
- struct GNUNET_IDENTITY_PROVIDER_Token token;
- uint64_t ticket_nonce;
- uint32_t r_id = ntohl (erm->id);
- char *str;
-
- for (op = handle->op_head; NULL != op; op = op->next)
+ size_t attr_len;
+ uint32_t r_id = ntohl (msg->id);
+
+ attr_len = ntohs (msg->attr_len);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing attribute result.\n");
+
+
+ for (it = h->it_head; NULL != it; it = it->next)
+ if (it->r_id == r_id)
+ break;
+ for (op = h->op_head; NULL != op; op = op->next)
if (op->r_id == r_id)
break;
- if (NULL == op)
+ if ((NULL == it) && (NULL == op))
return;
- str = GNUNET_strdup ((char*)&erm[1]);
- op = handle->op_head;
- GNUNET_CONTAINER_DLL_remove (handle->op_head,
- handle->op_tail,
- op);
- token.data = str;
- ticket_nonce = ntohl (erm->ticket_nonce);
- if (NULL != op->ex_cb)
- op->ex_cb (op->cls, &token, ticket_nonce);
- GNUNET_free (str);
- GNUNET_free (op);
+ if ( (0 == (memcmp (&msg->identity,
+ &identity_dummy,
+ sizeof (identity_dummy)))) )
+ {
+ if ((NULL == it) && (NULL == op))
+ {
+ GNUNET_break (0);
+ force_reconnect (h);
+ return;
+ }
+ if (NULL != it)
+ {
+ if (NULL != it->finish_cb)
+ it->finish_cb (it->finish_cb_cls);
+ free_it (it);
+ }
+ if (NULL != op)
+ {
+ if (NULL != op->ar_cb)
+ op->ar_cb (op->cls,
+ NULL,
+ NULL);
+ GNUNET_CONTAINER_DLL_remove (h->op_head,
+ h->op_tail,
+ op);
+ GNUNET_free (op);
+
+ }
+ return;
+ }
+
+ {
+ struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
+ attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1],
+ attr_len);
+ if (NULL != it)
+ {
+ if (NULL != it->proc)
+ it->proc (it->proc_cls,
+ &msg->identity,
+ attr);
+ } else if (NULL != op)
+ {
+ if (NULL != op->ar_cb)
+ op->ar_cb (op->cls,
+ &msg->identity,
+ attr);
+
+ }
+ GNUNET_free (attr);
+ return;
+ }
+ GNUNET_assert (0);
+}
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_ticket_result (void *cls,
+ const struct TicketResultMessage *msg)
+{
+ size_t msg_len;
+
+ msg_len = ntohs (msg->header.size);
+ if (msg_len < sizeof (struct TicketResultMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
}
+
+
/**
- * Handler for messages received from the GNS service
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
*
- * @param cls the `struct GNUNET_GNS_Handle *`
- * @param loookup_msg the incoming message
+ * @param cls
+ * @param msg the message we received
*/
static void
-handle_result (void *cls,
- const struct IssueResultMessage *irm)
+handle_ticket_result (void *cls,
+ const struct TicketResultMessage *msg)
{
struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
struct GNUNET_IDENTITY_PROVIDER_Operation *op;
- struct GNUNET_IDENTITY_PROVIDER_Token token;
- struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
- uint32_t r_id = ntohl (irm->id);
- char *str;
- char *label_str;
- char *ticket_str;
- char *token_str;
+ struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
+ uint32_t r_id = ntohl (msg->id);
+ size_t msg_len;
for (op = handle->op_head; NULL != op; op = op->next)
if (op->r_id == r_id)
break;
- if (NULL == op)
+ for (it = handle->ticket_it_head; NULL != it; it = it->next)
+ if (it->r_id == r_id)
+ break;
+ if ((NULL == op) && (NULL == it))
return;
- str = GNUNET_strdup ((char*)&irm[1]);
- label_str = strtok (str, ",");
-
- if (NULL == label_str)
+ msg_len = ntohs (msg->header.size);
+ if (NULL != op)
{
- GNUNET_free (str);
- GNUNET_break (0);
+ GNUNET_CONTAINER_DLL_remove (handle->op_head,
+ handle->op_tail,
+ op);
+ if (msg_len == sizeof (struct TicketResultMessage))
+ {
+ if (NULL != op->tr_cb)
+ op->tr_cb (op->cls, NULL);
+ } else {
+ ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
+ if (NULL != op->tr_cb)
+ op->tr_cb (op->cls, ticket);
+ }
+ GNUNET_free (op);
return;
- }
- ticket_str = strtok (NULL, ",");
- if (NULL == ticket_str)
- {
- GNUNET_free (str);
- GNUNET_break (0);
+ } else if (NULL != it) {
+ if (msg_len == sizeof (struct TicketResultMessage))
+ {
+ if (NULL != it->tr_cb)
+ GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
+ handle->ticket_it_tail,
+ it);
+ it->finish_cb (it->finish_cb_cls);
+ GNUNET_free (it);
+ } else {
+ ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
+ if (NULL != it->tr_cb)
+ it->tr_cb (it->cls, ticket);
+ }
return;
}
- token_str = strtok (NULL, ",");
- if (NULL == token_str)
+ GNUNET_break (0);
+}
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_revoke_ticket_result (void *cls,
+ const struct RevokeTicketResultMessage *msg)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+ struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+ uint32_t r_id = ntohl (msg->id);
+ int32_t success;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing revocation result.\n");
+
+
+ for (op = h->op_head; NULL != op; op = op->next)
+ if (op->r_id == r_id)
+ break;
+ if (NULL == op)
+ return;
+ success = ntohl (msg->success);
{
- GNUNET_free (str);
- GNUNET_break (0);
+ if (NULL != op->rvk_cb)
+ {
+ op->rvk_cb (op->cls,
+ success,
+ NULL);
+ }
+ GNUNET_CONTAINER_DLL_remove (h->op_head,
+ h->op_tail,
+ op);
+ GNUNET_free (op);
return;
}
- GNUNET_CONTAINER_DLL_remove (handle->op_head,
- handle->op_tail,
- op);
- ticket.data = ticket_str;
- token.data = token_str;
- if (NULL != op->iss_cb)
- op->iss_cb (op->cls, label_str, &ticket, &token);
- GNUNET_free (str);
- GNUNET_free (op);
-
+ GNUNET_assert (0);
}
+
+
/**
* Try again to connect to the service.
*
- * @param cls handle to the identity provider service.
+ * @param h handle to the identity provider service.
*/
static void
reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
{
struct GNUNET_MQ_MessageHandler handlers[] = {
- GNUNET_MQ_hd_var_size (result,
- GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT,
- struct IssueResultMessage,
+ GNUNET_MQ_hd_fixed_size (attribute_store_response,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE,
+ struct AttributeStoreResultMessage,
+ h),
+ GNUNET_MQ_hd_var_size (attribute_result,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT,
+ struct AttributeResultMessage,
h),
- GNUNET_MQ_hd_var_size (exchange_result,
- GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT,
- struct ExchangeResultMessage,
+ GNUNET_MQ_hd_var_size (ticket_result,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT,
+ struct TicketResultMessage,
h),
+ GNUNET_MQ_hd_var_size (consume_ticket_result,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT,
+ struct ConsumeTicketResultMessage,
+ h),
+ GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT,
+ struct RevokeTicketResultMessage,
+ h),
GNUNET_MQ_handler_end ()
};
struct GNUNET_IDENTITY_PROVIDER_Operation *op;
@@ -417,111 +845,6 @@ GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
/**
- * Issue an identity token
- *
- * @param id identity service to query
- * @param service_name for which service is an identity wanted
- * @param cb function to call with the result (will only be called once)
- * @param cb_cls closure for @a cb
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
- const char* scopes,
- struct GNUNET_TIME_Absolute expiration,
- uint64_t nonce,
- GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
- void *cb_cls)
-{
- struct GNUNET_IDENTITY_PROVIDER_Operation *op;
- struct IssueMessage *im;
- size_t slen;
-
- slen = strlen (scopes) + 1;
- if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct IssueMessage))
- {
- GNUNET_break (0);
- return NULL;
- }
- op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
- op->h = id;
- op->iss_cb = cb;
- op->cls = cb_cls;
- op->r_id = id->r_id_gen++;
- op->env = GNUNET_MQ_msg_extra (im,
- slen,
- GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE);
- im->id = op->r_id;
- im->iss_key = *iss_key;
- im->aud_key = *aud_key;
- im->nonce = htonl (nonce);
- im->expiration = GNUNET_TIME_absolute_hton (expiration);
- GNUNET_memcpy (&im[1], scopes, slen);
- GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
- id->op_tail,
- op);
- if (NULL != id->mq)
- GNUNET_MQ_send_copy (id->mq,
- op->env);
- return op;
-}
-
-
-/**
- * Exchange a token ticket for a token
- *
- * @param id identity provider service
- * @param ticket ticket to exchange
- * @param cont function to call once the operation finished
- * @param cont_cls closure for @a cont
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
- const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey,
- GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
- void *cont_cls)
-{
- struct GNUNET_IDENTITY_PROVIDER_Operation *op;
- struct ExchangeMessage *em;
- size_t slen;
- char *ticket_str;
-
- ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
-
- slen = strlen (ticket_str) + 1;
- if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct ExchangeMessage))
- {
- GNUNET_free (ticket_str);
- GNUNET_break (0);
- return NULL;
- }
- op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
- op->h = id;
- op->ex_cb = cont;
- op->cls = cont_cls;
- op->r_id = id->r_id_gen++;
- op->env = GNUNET_MQ_msg_extra (em,
- slen,
- GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE);
- em->aud_privkey = *aud_privkey;
- em->id = htonl (op->r_id);
- GNUNET_memcpy (&em[1], ticket_str, slen);
- GNUNET_free (ticket_str);
- GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
- id->op_tail,
- op);
- if (NULL != id->mq)
- GNUNET_MQ_send_copy (id->mq,
- op->env);
- return op;
-}
-
-
-/**
* Cancel an operation. Note that the operation MAY still
* be executed; this merely cancels the continuation; if the request
* was already transmitted, the service may still choose to complete
@@ -566,80 +889,482 @@ GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
}
/**
- * Convenience API
+ * Store an attribute. If the attribute is already present,
+ * it is replaced with the new attribute.
+ *
+ * @param h handle to the identity provider
+ * @param pkey private key of the identity
+ * @param attr the attribute value
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
*/
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
+ GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
+ void *cont_cls)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+ struct AttributeStoreMessage *sam;
+ size_t attr_len;
+
+ op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+ op->h = h;
+ op->as_cb = cont;
+ op->cls = cont_cls;
+ op->r_id = h->r_id_gen++;
+ GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+ h->op_tail,
+ op);
+ attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr);
+ op->env = GNUNET_MQ_msg_extra (sam,
+ attr_len,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE);
+ sam->identity = *pkey;
+ sam->id = htonl (op->r_id);
+
+ GNUNET_IDENTITY_ATTRIBUTE_serialize (attr,
+ (char*)&sam[1]);
+
+ sam->attr_len = htons (attr_len);
+ if (NULL != h->mq)
+ GNUNET_MQ_send_copy (h->mq,
+ op->env);
+ return op;
+
+}
+
+
+/**
+ * List all attributes for a local identity.
+ * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
+ * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
+ *
+ * On error (disconnect), @a error_cb will be invoked.
+ * On normal completion, @a finish_cb proc will be
+ * invoked.
+ *
+ * @param h handle to the idp
+ * @param identity identity to access
+ * @param error_cb function to call on error (i.e. disconnect),
+ * the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each attribute; it
+ * will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ * the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
+GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+ GNUNET_SCHEDULER_TaskCallback error_cb,
+ void *error_cb_cls,
+ GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
+ void *proc_cls,
+ GNUNET_SCHEDULER_TaskCallback finish_cb,
+ void *finish_cb_cls)
+{
+ struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
+ struct GNUNET_MQ_Envelope *env;
+ struct AttributeIterationStartMessage *msg;
+ uint32_t rid;
+
+ rid = h->r_id_gen++;
+ it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator);
+ it->h = h;
+ it->error_cb = error_cb;
+ it->error_cb_cls = error_cb_cls;
+ it->finish_cb = finish_cb;
+ it->finish_cb_cls = finish_cb_cls;
+ it->proc = proc;
+ it->proc_cls = proc_cls;
+ it->r_id = rid;
+ it->identity = *identity;
+ GNUNET_CONTAINER_DLL_insert_tail (h->it_head,
+ h->it_tail,
+ it);
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START);
+ msg->id = htonl (rid);
+ msg->identity = *identity;
+ if (NULL == h->mq)
+ it->env = env;
+ else
+ GNUNET_MQ_send (h->mq,
+ env);
+ return it;
+}
/**
- * Destroy token
+ * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
+ * for the next record.
*
- * @param token the token
+ * @param it the iterator
*/
void
-GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token)
+GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+ struct AttributeIterationNextMessage *msg;
+ struct GNUNET_MQ_Envelope *env;
+
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT);
+ msg->id = htonl (it->r_id);
+ GNUNET_MQ_send (h->mq,
+ env);
+}
+
+
+/**
+ * Stops iteration and releases the idp handle for further calls. Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_IDENTITY_PROVIDER_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+ struct GNUNET_MQ_Envelope *env;
+ struct AttributeIterationStopMessage *msg;
+
+ if (NULL != h->mq)
+ {
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP);
+ msg->id = htonl (it->r_id);
+ GNUNET_MQ_send (h->mq,
+ env);
+ }
+ free_it (it);
+}
+
+
+/** TODO
+ * Issues a ticket to another identity. The identity may use
+ * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
+ * and retrieve the attributes specified in the AttributeList.
+ *
+ * @param h the identity provider to use
+ * @param iss the issuing identity
+ * @param rp the subject of the ticket (the relying party)
+ * @param attrs the attributes that the relying party is given access to
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+ GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+ struct IssueTicketMessage *tim;
+ size_t attr_len;
+
+ op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+ op->h = h;
+ op->tr_cb = cb;
+ op->cls = cb_cls;
+ op->r_id = h->r_id_gen++;
+ GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+ h->op_tail,
+ op);
+ attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
+ op->env = GNUNET_MQ_msg_extra (tim,
+ attr_len,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET);
+ tim->identity = *iss;
+ tim->rp = *rp;
+ tim->id = htonl (op->r_id);
+
+ GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
+ (char*)&tim[1]);
+
+ tim->attr_len = htons (attr_len);
+ if (NULL != h->mq)
+ GNUNET_MQ_send_copy (h->mq,
+ op->env);
+ return op;
+}
+
+/**
+ * Consumes an issued ticket. The ticket is persisted
+ * and used to retrieve identity information from the issuer
+ *
+ * @param h the identity provider to use
+ * @param identity the identity that is the subject of the issued ticket (the relying party)
+ * @param ticket the issued ticket to consume
+ * @param cb the callback to call
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
+ void *cb_cls)
{
- GNUNET_assert (NULL != token);
- if (NULL != token->data)
- GNUNET_free (token->data);
- GNUNET_free (token);
+ struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+ struct ConsumeTicketMessage *ctm;
+
+ op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+ op->h = h;
+ op->ar_cb = cb;
+ op->cls = cb_cls;
+ op->r_id = h->r_id_gen++;
+ GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+ h->op_tail,
+ op);
+ op->env = GNUNET_MQ_msg_extra (ctm,
+ sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket),
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET);
+ ctm->identity = *identity;
+ ctm->id = htonl (op->r_id);
+
+ GNUNET_memcpy ((char*)&ctm[1],
+ ticket,
+ sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket));
+
+ if (NULL != h->mq)
+ GNUNET_MQ_send_copy (h->mq,
+ op->env);
+ return op;
+
}
+
/**
- * Returns string representation of token. A JSON-Web-Token.
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
*
- * @param token the token
- * @return The JWT (must be freed)
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ * the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ * will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ * the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
*/
-char *
-GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token)
+struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+ GNUNET_SCHEDULER_TaskCallback error_cb,
+ void *error_cb_cls,
+ GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
+ void *proc_cls,
+ GNUNET_SCHEDULER_TaskCallback finish_cb,
+ void *finish_cb_cls)
{
- return GNUNET_strdup (token->data);
+ struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
+ struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
+ struct GNUNET_MQ_Envelope *env;
+ struct TicketIterationStartMessage *msg;
+ uint32_t rid;
+
+ GNUNET_CRYPTO_ecdsa_key_get_public (identity,
+ &identity_pub);
+ rid = h->r_id_gen++;
+ it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
+ it->h = h;
+ it->error_cb = error_cb;
+ it->error_cb_cls = error_cb_cls;
+ it->finish_cb = finish_cb;
+ it->finish_cb_cls = finish_cb_cls;
+ it->tr_cb = proc;
+ it->cls = proc_cls;
+ it->r_id = rid;
+ GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
+ h->ticket_it_tail,
+ it);
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
+ msg->id = htonl (rid);
+ msg->identity = identity_pub;
+ msg->is_audience = htonl (GNUNET_NO);
+ if (NULL == h->mq)
+ it->env = env;
+ else
+ GNUNET_MQ_send (h->mq,
+ env);
+ return it;
+
}
+
/**
- * Returns string representation of ticket. Base64-Encoded
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
*
- * @param ticket the ticket
- * @return the Base64-Encoded ticket
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ * the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ * will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ * the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
*/
-char *
-GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
+struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+ GNUNET_SCHEDULER_TaskCallback error_cb,
+ void *error_cb_cls,
+ GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
+ void *proc_cls,
+ GNUNET_SCHEDULER_TaskCallback finish_cb,
+ void *finish_cb_cls)
{
- return GNUNET_strdup (ticket->data);
+ struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
+ struct GNUNET_MQ_Envelope *env;
+ struct TicketIterationStartMessage *msg;
+ uint32_t rid;
+
+ rid = h->r_id_gen++;
+ it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
+ it->h = h;
+ it->error_cb = error_cb;
+ it->error_cb_cls = error_cb_cls;
+ it->finish_cb = finish_cb;
+ it->finish_cb_cls = finish_cb_cls;
+ it->tr_cb = proc;
+ it->cls = proc_cls;
+ it->r_id = rid;
+ GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
+ h->ticket_it_tail,
+ it);
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
+ msg->id = htonl (rid);
+ msg->identity = *identity;
+ msg->is_audience = htonl (GNUNET_YES);
+ if (NULL == h->mq)
+ it->env = env;
+ else
+ GNUNET_MQ_send (h->mq,
+ env);
+ return it;
+
+
}
/**
- * Created a ticket from a string (Base64 encoded ticket)
+ * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
+ * for the next record.
*
- * @param input Base64 encoded ticket
- * @param ticket pointer where the ticket is stored
- * @return GNUNET_OK
+ * @param it the iterator
*/
-int
-GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input,
- struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket)
+void
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
{
- *ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
- (*ticket)->data = GNUNET_strdup (input);
- return GNUNET_OK;
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+ struct TicketIterationNextMessage *msg;
+ struct GNUNET_MQ_Envelope *env;
+
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT);
+ msg->id = htonl (it->r_id);
+ GNUNET_MQ_send (h->mq,
+ env);
}
/**
- * Destroys a ticket
+ * Stops iteration and releases the idp handle for further calls. Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_IDENTITY_PROVIDER_disconnect.
*
- * @param ticket the ticket to destroy
+ * @param it the iterator
*/
void
-GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
{
- GNUNET_assert (NULL != ticket);
- if (NULL != ticket->data)
- GNUNET_free (ticket->data);
- GNUNET_free (ticket);
+ struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+ struct GNUNET_MQ_Envelope *env;
+ struct TicketIterationStopMessage *msg;
+
+ if (NULL != h->mq)
+ {
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP);
+ msg->id = htonl (it->r_id);
+ GNUNET_MQ_send (h->mq,
+ env);
+ }
+ GNUNET_free (it);
}
+/**
+ * Revoked an issued ticket. The relying party will be unable to retrieve
+ * updated attributes.
+ *
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param ticket the ticket to revoke
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
+ void *cb_cls)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+ struct GNUNET_MQ_Envelope *env;
+ struct RevokeTicketMessage *msg;
+ uint32_t rid;
+ rid = h->r_id_gen++;
+ op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+ op->h = h;
+ op->rvk_cb = cb;
+ op->cls = cb_cls;
+ op->r_id = rid;
+ GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+ h->op_tail,
+ op);
+ env = GNUNET_MQ_msg_extra (msg,
+ sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
+ GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET);
+ msg->id = htonl (rid);
+ msg->identity = *identity;
+ memcpy (&msg[1],
+ ticket,
+ sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
+ if (NULL == h->mq)
+ op->env = env;
+ else
+ GNUNET_MQ_send (h->mq,
+ env);
+ return op;
+}
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 @@
-/*
- This file is part of GNUnet
- Copyright (C) 2010-2015 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
- */
-
-/**
- * @file identity-provider/identity_token.c
- * @brief helper library to manage identity tokens
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_signatures.h"
-#include "identity_token.h"
-#include <jansson.h>
-#include <inttypes.h>
-
-#define JWT_ALG "alg"
-
-#define JWT_ALG_VALUE "ED512"
-
-#define JWT_TYP "typ"
-
-#define JWT_TYP_VALUE "jwt"
-
-/**
- * Crypto helper functions
- */
-
-static int
-create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
- struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
- struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
-{
- struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
-
- GNUNET_CRYPTO_hash_to_enc (new_key_hash,
- &new_key_hash_str);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
- static const char ctx_key[] = "gnuid-aes-ctx-key";
- GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
- new_key_hash, sizeof (struct GNUNET_HashCode),
- ctx_key, strlen (ctx_key),
- NULL, 0);
- static const char ctx_iv[] = "gnuid-aes-ctx-iv";
- GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
- new_key_hash, sizeof (struct GNUNET_HashCode),
- ctx_iv, strlen (ctx_iv),
- NULL, 0);
- return GNUNET_OK;
-}
-
-
-
-/**
- * Decrypts data part from a token code
- */
-static int
-decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key,
- const char *cyphertext,
- size_t cyphertext_len,
- char **result_str)
-{
- struct GNUNET_HashCode new_key_hash;
- struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
- struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
-
- char *str_buf = GNUNET_malloc (cyphertext_len);
- size_t str_size;
-
- //Calculate symmetric key from ecdh parameters
- GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (priv_key,
- ecdh_key,
- &new_key_hash));
-
- create_sym_key_from_ecdh (&new_key_hash,
- &enc_key,
- &enc_iv);
-
- str_size = GNUNET_CRYPTO_symmetric_decrypt (cyphertext,
- cyphertext_len,
- &enc_key,
- &enc_iv,
- str_buf);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Decrypted bytes: %zd Expected bytes: %zd\n",
- str_size,
- cyphertext_len);
- if (-1 == str_size)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
- GNUNET_free (str_buf);
- return GNUNET_SYSERR;
- }
- *result_str = GNUNET_malloc (str_size+1);
- GNUNET_memcpy (*result_str, str_buf, str_size);
- (*result_str)[str_size] = '\0';
- GNUNET_free (str_buf);
- return GNUNET_OK;
-
-}
-
-/**
- * Decrypt string using pubkey and ECDHE
-*/
-static int
-decrypt_str_ecdhe2 (const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
- const char *ciphertext,
- size_t ciphertext_len,
- char **plaintext)
-{
- struct GNUNET_CRYPTO_SymmetricSessionKey skey;
- struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
- struct GNUNET_HashCode new_key_hash;
-
- //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
- *plaintext = GNUNET_malloc (ciphertext_len);
-
- // Derived key K = H(eB)
- GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (ecdh_privkey,
- aud_key,
- &new_key_hash));
- create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
- GNUNET_CRYPTO_symmetric_decrypt (ciphertext,
- ciphertext_len,
- &skey, &iv,
- *plaintext);
- return GNUNET_OK;
-}
-
-
-/**
- * Encrypt string using pubkey and ECDHE
- * Returns ECDHE pubkey to be used for decryption
- */
-static int
-encrypt_str_ecdhe (const char *plaintext,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
- char **cyphertext,
- struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
- struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey)
-{
- struct GNUNET_CRYPTO_SymmetricSessionKey skey;
- struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
- struct GNUNET_HashCode new_key_hash;
- ssize_t enc_size;
-
- // ECDH keypair E = eG
- *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
- GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
- ecdh_pubkey);
-
- //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
- *cyphertext = GNUNET_malloc (strlen (plaintext));
-
- // Derived key K = H(eB)
- GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
- pub_key,
- &new_key_hash));
- create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting string %s\n (len=%zd)",
- plaintext,
- strlen (plaintext));
- enc_size = GNUNET_CRYPTO_symmetric_encrypt (plaintext,
- strlen (plaintext),
- &skey, &iv,
- *cyphertext);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted (len=%zd)", enc_size);
- return GNUNET_OK;
-}
-
-
-/**
- * Identity Token API
- */
-
-
-/**
- * Create an Identity Token
- *
- * @param type the JSON API resource type
- * @param id the JSON API resource id
- * @return a new JSON API resource or NULL on error.
- */
-struct IdentityToken*
-token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey* iss,
- const struct GNUNET_CRYPTO_EcdsaPublicKey* aud)
-{
- struct IdentityToken *token;
- char* audience;
- char* issuer;
-
- issuer = GNUNET_STRINGS_data_to_string_alloc (iss,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- audience = GNUNET_STRINGS_data_to_string_alloc (aud,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
- token = GNUNET_malloc (sizeof (struct IdentityToken));
- token_add_attr (token, "iss", issuer);
- token_add_attr (token, "aud", audience);
- token_add_attr (token, "sub", issuer);
- token->aud_key = *aud;
- GNUNET_free (issuer);
- GNUNET_free (audience);
- return token;
-}
-
-void
-token_destroy (struct IdentityToken *token)
-{
- struct TokenAttr *attr;
- struct TokenAttr *tmp_attr;
- struct TokenAttrValue *val;
- struct TokenAttrValue *tmp_val;
-
- for (attr = token->attr_head; NULL != attr;)
- {
- tmp_attr = attr->next;
- GNUNET_CONTAINER_DLL_remove (token->attr_head,
- token->attr_tail,
- attr);
- for (val = attr->val_head; NULL != val;)
- {
- tmp_val = val->next;
- GNUNET_CONTAINER_DLL_remove (attr->val_head,
- attr->val_tail,
- val);
- if (NULL != val->value)
- GNUNET_free (val->value);
- GNUNET_free (val);
- val = tmp_val;
- }
- GNUNET_free (attr->name);
- GNUNET_free (attr);
- attr = tmp_attr;
- }
-
-
- GNUNET_free (token);
-}
-
-void
-token_add_attr (struct IdentityToken *token,
- const char* key,
- const char* value)
-{
- struct TokenAttr *attr;
- struct TokenAttrValue *new_val;
- GNUNET_assert (NULL != token);
-
- new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
- new_val->value = GNUNET_strdup (value);
- for (attr = token->attr_head; NULL != attr; attr = attr->next)
- {
- if (0 == strcmp (key, attr->name))
- break;
- }
-
- if (NULL == attr)
- {
- attr = GNUNET_malloc (sizeof (struct TokenAttr));
- attr->name = GNUNET_strdup (key);
- GNUNET_CONTAINER_DLL_insert (token->attr_head,
- token->attr_tail,
- attr);
- }
-
- GNUNET_CONTAINER_DLL_insert (attr->val_head,
- attr->val_tail,
- new_val);
-}
-
-void
-token_add_attr_int (struct IdentityToken *token,
- const char* key,
- uint64_t value)
-{
- struct TokenAttr *attr;
- struct TokenAttrValue *new_val;
- GNUNET_assert (NULL != token);
-
- new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
- new_val->int_value = value;
- for (attr = token->attr_head; NULL != attr; attr = attr->next)
- {
- if (0 == strcmp (key, attr->name))
- break;
- }
-
- if (NULL == attr)
- {
- attr = GNUNET_malloc (sizeof (struct TokenAttr));
- attr->name = GNUNET_strdup (key);
- GNUNET_CONTAINER_DLL_insert (token->attr_head,
- token->attr_tail,
- attr);
- }
-
- GNUNET_CONTAINER_DLL_insert (attr->val_head,
- attr->val_tail,
- new_val);
-}
-
-static void
-parse_json_payload(const char* payload_base64,
- struct IdentityToken *token)
-{
- const char *key;
- const json_t *value;
- const json_t *arr_value;
- char *payload;
- int idx;
- json_t *payload_json;
- json_error_t err_json;
-
- GNUNET_STRINGS_base64_decode (payload_base64,
- strlen (payload_base64),
- &payload);
- //TODO signature and aud key
- payload_json = json_loads (payload, JSON_DECODE_ANY, &err_json);
-
- json_object_foreach (payload_json, key, value)
- {
- if (json_is_array (value))
- {
- json_array_foreach (value, idx, arr_value)
- {
- if (json_is_integer (arr_value))
- token_add_attr_int (token, key,
- json_integer_value (arr_value));
- else
- token_add_attr (token,
- key,
- json_string_value (arr_value));
- }
- } else {
- if (json_is_integer (value))
- token_add_attr_int (token, key,
- json_integer_value (value));
- else
- token_add_attr (token, key, json_string_value (value));
- }
- }
-
- json_decref (payload_json);
- GNUNET_free (payload);
-}
-
-int
-token_parse2 (const char* raw_data,
- const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
- struct IdentityToken **result)
-{
- char *enc_token_str;
- char *tmp_buf;
- char *token_str;
- char *enc_token;
- char *payload_base64;
- size_t enc_token_len;
-
- GNUNET_asprintf (&tmp_buf, "%s", raw_data);
- strtok (tmp_buf, ",");
- enc_token_str = strtok (NULL, ",");
-
- enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
- strlen (enc_token_str),
- &enc_token);
- if (GNUNET_OK != decrypt_str_ecdhe2 (priv_key,
- aud_key,
- enc_token,
- enc_token_len,
- &token_str))
- {
- GNUNET_free (tmp_buf);
- GNUNET_free (enc_token);
- return GNUNET_SYSERR;
- }
-
- GNUNET_assert (NULL != strtok (token_str, "."));
- payload_base64 = strtok (NULL, ".");
-
- *result = GNUNET_malloc (sizeof (struct IdentityToken));
- parse_json_payload (payload_base64, *result);
-
- (*result)->aud_key = *aud_key;
- GNUNET_free (enc_token);
- GNUNET_free (token_str);
- GNUNET_free (tmp_buf);
- return GNUNET_OK;
-}
-
-int
-token_parse (const char* raw_data,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct IdentityToken **result)
-{
- char *ecdh_pubkey_str;
- char *enc_token_str;
- char *tmp_buf;
- char *token_str;
- char *enc_token;
- char *payload_base64;
- size_t enc_token_len;
- struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
- GNUNET_asprintf (&tmp_buf, "%s", raw_data);
- ecdh_pubkey_str = strtok (tmp_buf, ",");
- enc_token_str = strtok (NULL, ",");
-
- GNUNET_assert (NULL != ecdh_pubkey_str);
- GNUNET_assert (NULL != enc_token_str);
-
- GNUNET_STRINGS_string_to_data (ecdh_pubkey_str,
- strlen (ecdh_pubkey_str),
- &ecdh_pubkey,
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
- enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
- strlen (enc_token_str),
- &enc_token);
- if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
- &ecdh_pubkey,
- enc_token,
- enc_token_len,
- &token_str))
- {
- GNUNET_free (tmp_buf);
- GNUNET_free (enc_token);
- return GNUNET_SYSERR;
- }
-
- GNUNET_assert (NULL != strtok (token_str, "."));
- payload_base64 = strtok (NULL, ".");
-
- *result = GNUNET_malloc (sizeof (struct IdentityToken));
- parse_json_payload (payload_base64, *result);
-
- GNUNET_free (enc_token);
- GNUNET_free (token_str);
- GNUNET_free (tmp_buf);
- return GNUNET_OK;
-}
-
-static char*
-create_json_payload (const struct IdentityToken *token)
-{
- struct TokenAttr *attr;
- struct TokenAttrValue *val;
- json_t *root;
- char *json_str;
-
- root = json_object();
- for (attr = token->attr_head; NULL != attr; attr = attr->next)
- {
- for (val = attr->val_head; NULL != val; val = val->next)
- {
- if (NULL != val->value)
- {
- json_object_set_new (root,
- attr->name,
- json_string (val->value));
- } else {
- json_object_set_new (root,
- attr->name,
- json_integer (val->int_value));
- }
- }
- }
- json_str = json_dumps (root, JSON_INDENT(1));
- json_decref (root);
- return json_str;
-}
-
-static char*
-create_json_header(void)
-{
- json_t *root;
- char *json_str;
-
- root = json_object ();
- json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
- json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
-
- json_str = json_dumps (root, JSON_INDENT(1));
- json_decref (root);
- return json_str;
-}
-
-int
-token_to_string (const struct IdentityToken *token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result)
-{
- char *payload_str;
- char *header_str;
- char *payload_base64;
- char *header_base64;
- char *padding;
- char *signature_target;
- char *signature_str;
- struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
- header_str = create_json_header();
- GNUNET_STRINGS_base64_encode (header_str,
- strlen (header_str),
- &header_base64);
- //Remove GNUNET padding of base64
- padding = strtok(header_base64, "=");
- while (NULL != padding)
- padding = strtok(NULL, "=");
-
- payload_str = create_json_payload (token);
- GNUNET_STRINGS_base64_encode (payload_str,
- strlen (payload_str),
- &payload_base64);
-
- //Remove GNUNET padding of base64
- padding = strtok(payload_base64, "=");
- while (NULL != padding)
- padding = strtok(NULL, "=");
-
- GNUNET_asprintf (&signature_target, "%s,%s", header_base64, payload_base64);
- purpose =
- GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
- strlen (signature_target));
- purpose->size =
- htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
- purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
- GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
- if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
- purpose,
- (struct GNUNET_CRYPTO_EcdsaSignature *)&token->signature))
- {
- GNUNET_free (signature_target);
- GNUNET_free (payload_str);
- GNUNET_free (payload_base64);
- GNUNET_free (header_base64);
- GNUNET_free (purpose);
- return GNUNET_SYSERR;
- }
-
- GNUNET_STRINGS_base64_encode ((const char*)&token->signature,
- sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
- &signature_str);
- GNUNET_asprintf (result, "%s.%s.%s",
- header_base64, payload_base64, signature_str);
- GNUNET_free (signature_target);
- GNUNET_free (payload_str);
- GNUNET_free (header_str);
- GNUNET_free (signature_str);
- GNUNET_free (payload_base64);
- GNUNET_free (header_base64);
- GNUNET_free (purpose);
- return GNUNET_OK;
-}
-
-int
-token_serialize (const struct IdentityToken *token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
- char **result)
-{
- char *token_str;
- char *enc_token;
- char *dh_key_str;
- char *enc_token_base64;
- struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
- GNUNET_assert (GNUNET_OK == token_to_string (token,
- priv_key,
- &token_str));
-
- GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (token_str,
- &token->aud_key,
- &enc_token,
- ecdh_privkey,
- &ecdh_pubkey));
- GNUNET_STRINGS_base64_encode (enc_token,
- strlen (token_str),
- &enc_token_base64);
- dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ecdh_pubkey,
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
- GNUNET_asprintf (result, "%s,%s", dh_key_str, enc_token_base64);
- GNUNET_free (dh_key_str);
- GNUNET_free (enc_token_base64);
- GNUNET_free (enc_token);
- GNUNET_free (token_str);
- return GNUNET_OK;
-}
-
-struct TokenTicketPayload*
-ticket_payload_create (uint64_t nonce,
- const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
- const char* lbl_str)
-{
- struct TokenTicketPayload* payload;
-
- payload = GNUNET_malloc (sizeof (struct TokenTicketPayload));
- payload->nonce = nonce;
- payload->identity_key = *identity_pkey;
- GNUNET_asprintf (&payload->label, lbl_str, strlen (lbl_str));
- return payload;
-}
-
-void
-ticket_payload_destroy (struct TokenTicketPayload* payload)
-{
- if (NULL != payload->label)
- GNUNET_free (payload->label);
- GNUNET_free (payload);
-}
-
-void
-ticket_payload_serialize (struct TokenTicketPayload *payload,
- char **result)
-{
- char* identity_key_str;
-
- identity_key_str = GNUNET_STRINGS_data_to_string_alloc (&payload->identity_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
- GNUNET_asprintf (result,
- "{\"nonce\": \"%"SCNu64"\",\"identity\": \"%s\",\"label\": \"%s\"}",
- payload->nonce, identity_key_str, payload->label);
- GNUNET_free (identity_key_str);
-
-}
-
-
-/**
- * Create the token code
- * The data is encrypted with a share ECDH derived secret using B (aud_key)
- * and e (ecdh_privkey)
- * The ticket also contains E (ecdh_pubkey) and a signature over the
- * data and E
- */
-struct TokenTicket*
-ticket_create (uint64_t nonce,
- const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
- const char* lbl_str,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key)
-{
- struct TokenTicket *ticket;
- struct TokenTicketPayload *code_payload;
-
- ticket = GNUNET_malloc (sizeof (struct TokenTicket));
- code_payload = ticket_payload_create (nonce,
- identity_pkey,
- lbl_str);
- ticket->aud_key = *aud_key;
- ticket->payload = code_payload;
-
-
- return ticket;
-}
-
-void
-ticket_destroy (struct TokenTicket *ticket)
-{
- ticket_payload_destroy (ticket->payload);
- GNUNET_free (ticket);
-}
-
-int
-ticket_serialize (struct TokenTicket *ticket,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result)
-{
- char *code_payload_str;
- char *enc_ticket_payload;
- char *ticket_payload_str;
- char *ticket_sig_str;
- char *ticket_str;
- char *dh_key_str;
- char *write_ptr;
- struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-
- struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-
- ticket_payload_serialize (ticket->payload,
- &code_payload_str);
-
- GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (code_payload_str,
- &ticket->aud_key,
- &enc_ticket_payload,
- &ecdhe_privkey,
- &ticket->ecdh_pubkey));
-
- GNUNET_free (ecdhe_privkey);
-
- purpose =
- GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
- strlen (code_payload_str)); // E_K (code_str)
- purpose->size =
- htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
- strlen (code_payload_str));
- purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
- write_ptr = (char*) &purpose[1];
- GNUNET_memcpy (write_ptr,
- &ticket->ecdh_pubkey,
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
- write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
- GNUNET_memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
- GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
- purpose,
- &ticket->signature));
- GNUNET_STRINGS_base64_encode (enc_ticket_payload,
- strlen (code_payload_str),
- &ticket_payload_str);
- ticket_sig_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->signature,
- sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
-
- dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->ecdh_pubkey,
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
- GNUNET_asprintf (&ticket_str, "{\"data\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
- ticket_payload_str, dh_key_str, ticket_sig_str);
- GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
- GNUNET_free (dh_key_str);
- GNUNET_free (purpose);
- GNUNET_free (ticket_str);
- GNUNET_free (ticket_sig_str);
- GNUNET_free (code_payload_str);
- GNUNET_free (enc_ticket_payload);
- GNUNET_free (ticket_payload_str);
- return GNUNET_OK;
-}
-
-int
-ticket_payload_parse(const char *raw_data,
- ssize_t data_len,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- const struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe_pkey,
- struct TokenTicketPayload **result)
-{
- const char* label_str;
- const char* nonce_str;
- const char* identity_key_str;
-
- json_t *root;
- json_t *label_json;
- json_t *identity_json;
- json_t *nonce_json;
- json_error_t err_json;
- char* data_str;
- uint64_t nonce;
- struct GNUNET_CRYPTO_EcdsaPublicKey id_pkey;
-
- if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
- ecdhe_pkey,
- raw_data,
- data_len,
- &data_str))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Data decryption failed\n");
- return GNUNET_SYSERR;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data: %s\n", data_str);
- root = json_loads (data_str, JSON_DECODE_ANY, &err_json);
- if (!root)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error parsing data: %s\n", err_json.text);
- GNUNET_free (data_str);
- return GNUNET_SYSERR;
- }
-
- identity_json = json_object_get (root, "identity");
- if (!json_is_string (identity_json))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error parsing data: %s\n", err_json.text);
- json_decref (root);
- GNUNET_free (data_str);
- return GNUNET_SYSERR;
- }
- identity_key_str = json_string_value (identity_json);
- GNUNET_STRINGS_string_to_data (identity_key_str,
- strlen (identity_key_str),
- &id_pkey,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-
- label_json = json_object_get (root, "label");
- if (!json_is_string (label_json))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error parsing data: %s\n", err_json.text);
- json_decref (root);
- GNUNET_free (data_str);
- return GNUNET_SYSERR;
- }
-
- label_str = json_string_value (label_json);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found label: %s\n", label_str);
-
- nonce_json = json_object_get (root, "nonce");
- if (!json_is_string (label_json))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error parsing data: %s\n", err_json.text);
- json_decref (root);
- GNUNET_free (data_str);
- return GNUNET_SYSERR;
- }
-
- nonce_str = json_string_value (nonce_json);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found nonce: %s\n", nonce_str);
-
- GNUNET_assert (0 != sscanf (nonce_str, "%"SCNu64, &nonce));
-
- *result = ticket_payload_create (nonce,
- (const struct GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
- label_str);
- GNUNET_free (data_str);
- json_decref (root);
- return GNUNET_OK;
-
-}
-
-int
-ticket_parse (const char *raw_data,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct TokenTicket **result)
-{
- const char* enc_data_str;
- const char* ecdh_enc_str;
- const char* signature_enc_str;
-
- json_t *root;
- json_t *signature_json;
- json_t *ecdh_json;
- json_t *enc_data_json;
- json_error_t err_json;
- char* enc_data;
- char* ticket_decoded;
- char* write_ptr;
- size_t enc_data_len;
- struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
- struct TokenTicket *ticket;
- struct TokenTicketPayload *ticket_payload;
-
- ticket_decoded = NULL;
- GNUNET_STRINGS_base64_decode (raw_data, strlen (raw_data), &ticket_decoded);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket: %s\n", ticket_decoded);
- root = json_loads (ticket_decoded, JSON_DECODE_ANY, &err_json);
- if (!root)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "%s\n", err_json.text);
- return GNUNET_SYSERR;
- }
-
- signature_json = json_object_get (root, "signature");
- ecdh_json = json_object_get (root, "ecdh");
- enc_data_json = json_object_get (root, "data");
-
- signature_enc_str = json_string_value (signature_json);
- ecdh_enc_str = json_string_value (ecdh_json);
- enc_data_str = json_string_value (enc_data_json);
-
- ticket = GNUNET_malloc (sizeof (struct TokenTicket));
-
- if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ecdh_enc_str,
- strlen (ecdh_enc_str),
- &ticket->ecdh_pubkey,
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in data\n", ecdh_enc_str);
- json_decref (root);
- GNUNET_free (ticket);
- return GNUNET_SYSERR;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s for data decryption\n", ecdh_enc_str);
- if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
- strlen (signature_enc_str),
- &ticket->signature,
- sizeof (struct GNUNET_CRYPTO_EcdsaSignature)))
- {
- json_decref (root);
- GNUNET_free (ticket_decoded);
- GNUNET_free (ticket);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in data\n");
- return GNUNET_SYSERR;
- }
-
- enc_data_len = GNUNET_STRINGS_base64_decode (enc_data_str,
- strlen (enc_data_str),
- &enc_data);
-
-
- if (GNUNET_OK != ticket_payload_parse (enc_data,
- enc_data_len,
- priv_key,
- (const struct GNUNET_CRYPTO_EcdhePublicKey*)&ticket->ecdh_pubkey,
- &ticket_payload))
- {
- json_decref (root);
- GNUNET_free (enc_data);
- GNUNET_free (ticket_decoded);
- GNUNET_free (ticket);
- return GNUNET_SYSERR;
- }
-
- ticket->payload = ticket_payload;
- purpose =
- GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
- enc_data_len); // E_K (code_str)
- purpose->size =
- htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
- enc_data_len);
- purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
- write_ptr = (char*) &purpose[1];
- GNUNET_memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
- write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
- GNUNET_memcpy (write_ptr, enc_data, enc_data_len);
-
- if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET,
- purpose,
- &ticket->signature,
- &ticket_payload->identity_key))
- {
- ticket_destroy (ticket);
- GNUNET_free (ticket_decoded);
- json_decref (root);
- GNUNET_free (purpose);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error verifying signature for ticket\n");
- return GNUNET_SYSERR;
- }
- *result = ticket;
- GNUNET_free (purpose);
-
- GNUNET_free (enc_data);
- GNUNET_free (ticket_decoded);
- json_decref (root);
- return GNUNET_OK;
-
-}
-
-
-
-/* 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 @@
-/*
- This file is part of GNUnet.
- Copyright (C) 2012-2015 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
- */
-/**
- * @author Martin Schanzenbach
- * @file identity-provider/identity_token.h
- * @brief GNUnet Identity Provider library
- *
- */
-#ifndef IDENTITY_TOKEN_H
-#define IDENTITY_TOKEN_H
-
-#include "gnunet_crypto_lib.h"
-#include <jansson.h>
-
-struct IdentityToken
-{
- /**
- * DLL
- */
- struct TokenAttr *attr_head;
-
- /**
- * DLL
- */
- struct TokenAttr *attr_tail;
-
- /**
- * Token Signature
- */
- struct GNUNET_CRYPTO_EcdsaSignature signature;
-
- /**
- * Audience Pubkey
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
-};
-
-struct TokenAttr
-{
- /**
- * DLL
- */
- struct TokenAttr *next;
-
- /**
- * DLL
- */
- struct TokenAttr *prev;
-
- /**
- * Attribute name
- */
- char *name;
-
- /**
- * Attribute value DLL
- */
- struct TokenAttrValue *val_head;
-
- /**
- * Attribute value DLL
- */
- struct TokenAttrValue *val_tail;
-
-};
-
-struct TokenAttrValue
-{
- /**
- * DLL
- */
- struct TokenAttrValue *next;
-
- /**
- * DLL
- */
- struct TokenAttrValue *prev;
-
- /**
- * Attribute value
- */
- char *value;
-
- /**
- * Attribute int value
- * used if NULL == value
- */
- uint64_t int_value;
-};
-
-struct TokenTicketPayload
-{
- /**
- * Nonce
- */
- uint64_t nonce;
-
- /**
- * Label
- */
- char *label;
-
- /**
- * Issuing Identity
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey identity_key;
-};
-
-
-struct TokenTicket
-{
- /**
- * Meta info
- */
- struct TokenTicketPayload *payload;
-
- /**
- * ECDH Pubkey
- */
- struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
- /**
- * Signature
- */
- struct GNUNET_CRYPTO_EcdsaSignature signature;
-
- /**
- * Target identity
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
-};
-
-
-
-/**
- * Create an identity token
- *
- * @param iss the issuer string for the token
- * @param aud the audience of the token
- *
- * @return a new token
- */
-struct IdentityToken*
-token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *iss,
- const struct GNUNET_CRYPTO_EcdsaPublicKey* aud);
-
-/**
- * Destroy an identity token
- *
- * @param token the token to destroy
- */
-void
-token_destroy (struct IdentityToken*token);
-
-/**
- * Add a new key value pair to the token
- *
- * @param token the token to modify
- * @param key the key
- * @param value the value
- */
-void
-token_add_attr (struct IdentityToken *token,
- const char* key,
- const char* value);
-
-/**
- * Add a new key value pair to the token
- *
- * @param token the token to modify
- * @param key the key
- * @param value the value
- */
-void
-token_add_attr_int (struct IdentityToken *token,
- const char* key,
- uint64_t value);
-
-
-
-/**
- * Add a value to a TokenAttribute
- *
- * @param attr the token attribute
- * @param value value to add
- */
- void
- token_attr_add_value (const struct TokenAttr *attr,
- const char *value);
-
-/**
- * Add a new key value pair to the token with the value as json
- *
- * @param the token to modify
- * @param key the key
- * @param value the value
- *
- */
- void
- token_add_json (const struct IdentityToken *token,
- const char* key,
- json_t* value);
-
-/**
- * Serialize a token. The token will be signed and base64 according to the
- * JWT format. The signature is base32-encoded ECDSA.
- * The resulting JWT is encrypted using
- * ECDHE for the audience and Base64
- * encoded in result. The audience requires the ECDHE public key P
- * to decrypt the token T. The key P is included in the result and prepended
- * before the token
- *
- * @param token the token to serialize
- * @param priv_key the private key used to sign the token
- * @param ecdhe_privkey the ECDHE private key used to encrypt the token
- * @param result P,Base64(E(T))
- *
- * @return GNUNET_OK on success
- */
- int
- token_serialize (const struct IdentityToken*token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
- char **result);
-
-/**
- * Parses the serialized token and returns a token
- *
- * @param data the serialized token
- * @param priv_key the private key of the audience
- * @param result the token
- *
- * @return GNUNET_OK on success
- */
- int
- token_parse (const char* data,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct IdentityToken **result);
-
-/**
- * Parses the serialized token and returns a token
- * This variant is intended for the party that issued the token and also
- * wants to decrypt the serialized token.
- *
- * @param data the serialized token
- * @param priv_key the private (!) ECDHE key
- * @param aud_key the identity of the audience
- * @param result the token
- *
- * @return GNUNET_OK on success
- */
-int
-token_parse2 (const char* data,
- const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
- struct IdentityToken **result);
-
-
-/**
- *
- * Returns a JWT-string representation of the token
- *
- * @param token the token
- * @param priv_key the private key used to sign the JWT
- * @param result the JWT
- *
- * @return GNUNET_OK on success
- */
- int
- token_to_string (const struct IdentityToken *token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result);
-
-/**
- *
- * Creates a ticket that can be exchanged by the audience for
- * the token. The token must be placed under the label
- *
- * @param nonce nonce provided by the audience that requested the ticket
- * @param iss_pkey the issuer pubkey used to sign the ticket
- * @param label the label encoded in the ticket
- * @param aud_ley the audience pubkey used to encrypt the ticket payload
- *
- * @return the ticket
- */
-struct TokenTicket*
-ticket_create (uint64_t nonce,
- const struct GNUNET_CRYPTO_EcdsaPublicKey* iss_pkey,
- const char* lbl_str,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key);
-
-/**
- * Serialize a ticket. Returns the Base64 representation of the ticket.
- * Format: Base64( { payload: E(Payload), ecdhe: K, signature: signature } )
- *
- * @param ticket the ticket to serialize
- * @param priv_key the issuer private key to sign the ticket payload
- * @param result the serialized ticket
- *
- * @return GNUNET_OK on success
- */
- int
- ticket_serialize (struct TokenTicket *ticket,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result);
-
-/**
- * Destroys a ticket
- *
- * @param the ticket to destroy
- */
-void
-ticket_destroy (struct TokenTicket *ticket);
-
-/**
- * Parses a serialized ticket
- *
- * @param data the serialized ticket
- * @param priv_key the audience private key
- * @param ticket the ticket
- *
- * @return GNUNET_OK on success
- */
-int
-ticket_parse (const char* raw_data,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct TokenTicket **ticket);
-
-#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 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2010-2015 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file identity-provider/jwt.c
+ * @brief helper library for JSON-Web-Tokens
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_identity_attribute_lib.h"
+#include <jansson.h>
+
+
+#define JWT_ALG "alg"
+
+/*TODO is this the correct way to define new algs? */
+#define JWT_ALG_VALUE "ED512"
+
+#define JWT_TYP "typ"
+
+#define JWT_TYP_VALUE "jwt"
+
+static char*
+create_jwt_header(void)
+{
+ json_t *root;
+ char *json_str;
+
+ root = json_object ();
+ json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
+ json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
+
+ json_str = json_dumps (root, JSON_INDENT(1));
+ json_decref (root);
+ return json_str;
+}
+
+/**
+ * Create a JWT from attributes
+ *
+ * @param sub_key the public of the subject
+ * @param attrs the attribute list
+ * @param priv_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char*
+jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key)
+{
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+ struct GNUNET_CRYPTO_EcdsaPublicKey iss_key;
+ struct GNUNET_CRYPTO_EcdsaSignature signature;
+ struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+ char* audience;
+ char* issuer;
+ char* header;
+ char* padding;
+ char* body_str;
+ char* result;
+ char* header_base64;
+ char* body_base64;
+ char* signature_target;
+ char* signature_base64;
+ char* attr_val_str;
+ json_t* body;
+
+ GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &iss_key);
+ /* TODO maybe we should use a local identity here */
+ issuer = GNUNET_STRINGS_data_to_string_alloc (&iss_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ audience = GNUNET_STRINGS_data_to_string_alloc (sub_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ header = create_jwt_header ();
+ body = json_object ();
+ /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */
+ json_object_set_new (body,
+ "iss", json_string (issuer));
+ json_object_set_new (body,
+ "sub", json_string (issuer));
+ /* TODO what should be in here exactly? */
+ json_object_set_new (body,
+ "aud", json_string (audience));
+ for (le = attrs->list_head; NULL != le; le = le->next)
+ {
+ /**
+ * TODO here we should have a function that
+ * calls the Attribute plugins to create a
+ * json representation for its value
+ */
+ attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type,
+ le->claim->data,
+ le->claim->data_size);
+ json_object_set_new (body,
+ le->claim->name,
+ json_string (attr_val_str));
+ GNUNET_free (attr_val_str);
+ }
+ body_str = json_dumps (body, JSON_INDENT(0));
+ json_decref (body);
+
+ GNUNET_STRINGS_base64_encode (header,
+ strlen (header),
+ &header_base64);
+ //Remove GNUNET padding of base64
+ padding = strtok(header_base64, "=");
+ while (NULL != padding)
+ padding = strtok(NULL, "=");
+
+ GNUNET_STRINGS_base64_encode (body_str,
+ strlen (body_str),
+ &body_base64);
+
+ //Remove GNUNET padding of base64
+ padding = strtok(body_base64, "=");
+ while (NULL != padding)
+ padding = strtok(NULL, "=");
+
+ GNUNET_free (issuer);
+ GNUNET_free (audience);
+
+ /**
+ * TODO
+ * Creating the JWT signature. This might not be
+ * standards compliant, check.
+ */
+ GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64);
+
+ purpose =
+ GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+ strlen (signature_target));
+ purpose->size =
+ htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
+ purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
+ GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
+ if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
+ purpose,
+ (struct GNUNET_CRYPTO_EcdsaSignature *)&signature))
+ {
+ GNUNET_free (signature_target);
+ GNUNET_free (body_str);
+ GNUNET_free (body_base64);
+ GNUNET_free (header_base64);
+ GNUNET_free (purpose);
+ return NULL;
+ }
+ GNUNET_STRINGS_base64_encode ((const char*)&signature,
+ sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+ &signature_base64);
+ GNUNET_asprintf (&result, "%s.%s.%s",
+ header_base64, body_base64, signature_base64);
+
+ GNUNET_free (signature_target);
+ GNUNET_free (header);
+ GNUNET_free (body_str);
+ GNUNET_free (signature_base64);
+ GNUNET_free (body_base64);
+ GNUNET_free (header_base64);
+ GNUNET_free (purpose);
+ return result;
+}
diff --git a/src/identity/plugin_gnsrecord_identity.c b/src/identity-provider/plugin_gnsrecord_identity_provider.c
index c26c04074..6ed0b0852 100644
--- a/src/identity/plugin_gnsrecord_identity.c
+++ b/src/identity-provider/plugin_gnsrecord_identity_provider.c
@@ -19,9 +19,9 @@
*/
/**
- * @file identity/plugin_gnsrecord_identity.c
+ * @file identity-provider/plugin_gnsrecord_identity_provider.c
* @brief gnsrecord plugin to provide the API for identity records
- * @author Christian Grothoff
+ * @author Martin Schanzenbach
*/
#include "platform.h"
#include "gnunet_util_lib.h"
@@ -54,9 +54,13 @@ value_to_string (void *cls,
switch (type)
{
case GNUNET_GNSRECORD_TYPE_ID_ATTR:
- case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
+ return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
+ case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED
return GNUNET_strndup (data, data_size);
- case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
+ case GNUNET_GNSRECORD_TYPE_ABE_KEY:
+ case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
+ return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
+ case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED
ecdhe_privkey = data;
audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
scopes = (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
@@ -106,12 +110,22 @@ string_to_value (void *cls,
switch (type)
{
case GNUNET_GNSRECORD_TYPE_ID_ATTR:
+ return GNUNET_STRINGS_string_to_data (s,
+ strlen (s),
+ *data,
+ *data_size);
case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
*data = GNUNET_strdup (s);
*data_size = strlen (s);
return GNUNET_OK;
+ case GNUNET_GNSRECORD_TYPE_ABE_KEY:
+ case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
+ return GNUNET_STRINGS_string_to_data (s,
+ strlen (s),
+ *data,
+ *data_size);
case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
- tmp_tok = GNUNET_strdup (s);
+ tmp_tok = GNUNET_strdup (s);
ecdhe_str = strtok (tmp_tok, ";");
if (NULL == ecdhe_str)
{
@@ -160,15 +174,17 @@ string_to_value (void *cls,
* Mapping of record type numbers to human-readable
* record type names.
*/
- static struct {
- const char *name;
- uint32_t number;
- } name_map[] = {
- { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
- { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
- { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
- { NULL, UINT32_MAX }
- };
+static struct {
+ const char *name;
+ uint32_t number;
+} name_map[] = {
+ { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
+ { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
+ { "ABE_KEY", GNUNET_GNSRECORD_TYPE_ABE_KEY },
+ { "ABE_MASTER", GNUNET_GNSRECORD_TYPE_ABE_MASTER },
+ { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
+ { NULL, UINT32_MAX }
+};
/**
@@ -220,7 +236,7 @@ number_to_typename (void *cls,
* @return the exported block API
*/
void *
-libgnunet_plugin_gnsrecord_identity_init (void *cls)
+libgnunet_plugin_gnsrecord_identity_provider_init (void *cls)
{
struct GNUNET_GNSRECORD_PluginFunctions *api;
@@ -240,7 +256,7 @@ libgnunet_plugin_gnsrecord_identity_init (void *cls)
* @return NULL
*/
void *
-libgnunet_plugin_gnsrecord_identity_done (void *cls)
+libgnunet_plugin_gnsrecord_identity_provider_done (void *cls)
{
struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
diff --git a/src/identity-provider/plugin_identity_provider_sqlite.c b/src/identity-provider/plugin_identity_provider_sqlite.c
new file mode 100644
index 000000000..0071528b9
--- /dev/null
+++ b/src/identity-provider/plugin_identity_provider_sqlite.c
@@ -0,0 +1,736 @@
+ /*
+ * This file is part of GNUnet
+ * Copyright (C) 2009-2017 GNUnet e.V.
+ *
+ * GNUnet is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 3, or (at your
+ * option) any later version.
+ *
+ * GNUnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNUnet; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file identity-provider/plugin_identity_provider_sqlite.c
+ * @brief sqlite-based idp backend
+ * @author Martin Schanzenbach
+ */
+
+#include "platform.h"
+#include "gnunet_identity_provider_service.h"
+#include "gnunet_identity_provider_plugin.h"
+#include "gnunet_identity_attribute_lib.h"
+#include "gnunet_sq_lib.h"
+#include <sqlite3.h>
+
+/**
+ * After how many ms "busy" should a DB operation fail for good? A
+ * low value makes sure that we are more responsive to requests
+ * (especially PUTs). A high value guarantees a higher success rate
+ * (SELECTs in iterate can take several seconds despite LIMIT=1).
+ *
+ * The default value of 1s should ensure that users do not experience
+ * huge latencies while at the same time allowing operations to
+ * succeed with reasonable probability.
+ */
+#define BUSY_TIMEOUT_MS 1000
+
+
+/**
+ * Log an error message at log-level 'level' that indicates
+ * a failure of the command 'cmd' on file 'filename'
+ * with the message given by strerror(errno).
+ */
+#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)
+
+#define LOG(kind,...) GNUNET_log_from (kind, "identity-provider-sqlite", __VA_ARGS__)
+
+
+/**
+ * Context for all functions in this plugin.
+ */
+struct Plugin
+{
+
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Database filename.
+ */
+ char *fn;
+
+ /**
+ * Native SQLite database handle.
+ */
+ sqlite3 *dbh;
+
+ /**
+ * Precompiled SQL to store ticket.
+ */
+ sqlite3_stmt *store_ticket;
+
+ /**
+ * Precompiled SQL to delete existing ticket.
+ */
+ sqlite3_stmt *delete_ticket;
+
+ /**
+ * Precompiled SQL to iterate tickets.
+ */
+ sqlite3_stmt *iterate_tickets;
+
+ /**
+ * Precompiled SQL to get ticket attributes.
+ */
+ sqlite3_stmt *get_ticket_attrs;
+
+ /**
+ * Precompiled SQL to iterate tickets by audience.
+ */
+ sqlite3_stmt *iterate_tickets_by_audience;
+};
+
+
+/**
+ * @brief Prepare a SQL statement
+ *
+ * @param dbh handle to the database
+ * @param zSql SQL statement, UTF-8 encoded
+ * @param ppStmt set to the prepared statement
+ * @return 0 on success
+ */
+static int
+sq_prepare (sqlite3 *dbh,
+ const char *zSql,
+ sqlite3_stmt **ppStmt)
+{
+ char *dummy;
+ int result;
+
+ result =
+ sqlite3_prepare_v2 (dbh,
+ zSql,
+ strlen (zSql),
+ ppStmt,
+ (const char **) &dummy);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Prepared `%s' / %p: %d\n",
+ zSql,
+ *ppStmt,
+ result);
+ return result;
+}
+
+/**
+ * Create our database indices.
+ *
+ * @param dbh handle to the database
+ */
+static void
+create_indices (sqlite3 * dbh)
+{
+ /* create indices */
+ if ( (SQLITE_OK !=
+ sqlite3_exec (dbh,
+ "CREATE INDEX IF NOT EXISTS identity_reverse ON identity001tickets (identity,audience)",
+ NULL, NULL, NULL)) ||
+ (SQLITE_OK !=
+ sqlite3_exec (dbh,
+ "CREATE INDEX IF NOT EXISTS it_iter ON identity001tickets (rnd)",
+ NULL, NULL, NULL)) )
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to create indices: %s\n",
+ sqlite3_errmsg (dbh));
+}
+
+
+
+#if 0
+#define CHECK(a) GNUNET_break(a)
+#define ENULL NULL
+#else
+#define ENULL &e
+#define ENULL_DEFINED 1
+#define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
+#endif
+
+
+/**
+ * Initialize the database connections and associated
+ * data structures (create tables and indices
+ * as needed as well).
+ *
+ * @param plugin the plugin context (state for this module)
+ * @return #GNUNET_OK on success
+ */
+static int
+database_setup (struct Plugin *plugin)
+{
+ sqlite3_stmt *stmt;
+ char *afsdir;
+#if ENULL_DEFINED
+ char *e;
+#endif
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
+ "identity-provider-sqlite",
+ "FILENAME",
+ &afsdir))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "identity-provider-sqlite",
+ "FILENAME");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_test (afsdir))
+ {
+ if (GNUNET_OK !=
+ GNUNET_DISK_directory_create_for_file (afsdir))
+ {
+ GNUNET_break (0);
+ GNUNET_free (afsdir);
+ return GNUNET_SYSERR;
+ }
+ }
+ /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
+ plugin->fn = afsdir;
+
+ /* Open database and precompile statements */
+ if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Unable to initialize SQLite: %s.\n"),
+ sqlite3_errmsg (plugin->dbh));
+ return GNUNET_SYSERR;
+ }
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA temp_store=MEMORY", NULL, NULL,
+ ENULL));
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA synchronous=NORMAL", NULL, NULL,
+ ENULL));
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA legacy_file_format=OFF", NULL, NULL,
+ ENULL));
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA auto_vacuum=INCREMENTAL", NULL,
+ NULL, ENULL));
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA encoding=\"UTF-8\"", NULL,
+ NULL, ENULL));
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
+ ENULL));
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA page_size=4092", NULL, NULL,
+ ENULL));
+
+ CHECK (SQLITE_OK ==
+ sqlite3_busy_timeout (plugin->dbh,
+ BUSY_TIMEOUT_MS));
+
+
+ /* Create table */
+ CHECK (SQLITE_OK ==
+ sq_prepare (plugin->dbh,
+ "SELECT 1 FROM sqlite_master WHERE tbl_name = 'identity001tickets'",
+ &stmt));
+ if ((sqlite3_step (stmt) == SQLITE_DONE) &&
+ (sqlite3_exec
+ (plugin->dbh,
+ "CREATE TABLE identity001tickets ("
+ " identity BLOB NOT NULL DEFAULT '',"
+ " audience BLOB NOT NULL DEFAULT '',"
+ " rnd INT8 NOT NULL DEFAULT '',"
+ " attributes BLOB NOT NULL DEFAULT ''"
+ ")",
+ NULL, NULL, NULL) != SQLITE_OK))
+ {
+ LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR,
+ "sqlite3_exec");
+ sqlite3_finalize (stmt);
+ return GNUNET_SYSERR;
+ }
+ sqlite3_finalize (stmt);
+
+ create_indices (plugin->dbh);
+
+ if ( (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "INSERT INTO identity001tickets (identity, audience, rnd, attributes)"
+ " VALUES (?, ?, ?, ?)",
+ &plugin->store_ticket)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "DELETE FROM identity001tickets WHERE identity=? AND rnd=?",
+ &plugin->delete_ticket)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "SELECT identity,audience,rnd,attributes"
+ " FROM identity001tickets WHERE identity=? AND rnd=?",
+ &plugin->get_ticket_attrs)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "SELECT identity,audience,rnd,attributes"
+ " FROM identity001tickets WHERE identity=?"
+ " ORDER BY rnd LIMIT 1 OFFSET ?",
+ &plugin->iterate_tickets)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "SELECT identity,audience,rnd,attributes"
+ " FROM identity001tickets WHERE audience=?"
+ " ORDER BY rnd LIMIT 1 OFFSET ?",
+ &plugin->iterate_tickets_by_audience)) )
+ {
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR,
+ "precompiling");
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Shutdown database connection and associate data
+ * structures.
+ * @param plugin the plugin context (state for this module)
+ */
+static void
+database_shutdown (struct Plugin *plugin)
+{
+ int result;
+ sqlite3_stmt *stmt;
+
+ if (NULL != plugin->store_ticket)
+ sqlite3_finalize (plugin->store_ticket);
+ if (NULL != plugin->delete_ticket)
+ sqlite3_finalize (plugin->delete_ticket);
+ if (NULL != plugin->iterate_tickets)
+ sqlite3_finalize (plugin->iterate_tickets);
+ if (NULL != plugin->iterate_tickets_by_audience)
+ sqlite3_finalize (plugin->iterate_tickets_by_audience);
+ if (NULL != plugin->get_ticket_attrs)
+ sqlite3_finalize (plugin->get_ticket_attrs);
+ result = sqlite3_close (plugin->dbh);
+ if (result == SQLITE_BUSY)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ _("Tried to close sqlite without finalizing all prepared statements.\n"));
+ stmt = sqlite3_next_stmt (plugin->dbh,
+ NULL);
+ while (NULL != stmt)
+ {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "sqlite",
+ "Closing statement %p\n",
+ stmt);
+ result = sqlite3_finalize (stmt);
+ if (result != SQLITE_OK)
+ GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
+ "sqlite",
+ "Failed to close statement %p: %d\n",
+ stmt,
+ result);
+ stmt = sqlite3_next_stmt (plugin->dbh,
+ NULL);
+ }
+ result = sqlite3_close (plugin->dbh);
+ }
+ if (SQLITE_OK != result)
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR,
+ "sqlite3_close");
+
+ GNUNET_free_non_null (plugin->fn);
+}
+
+
+/**
+ * Store a ticket in the database.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param ticket the ticket to persist
+ * @param attrs the attributes associated with the ticket
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+identity_provider_sqlite_store_ticket (void *cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+ struct Plugin *plugin = cls;
+ size_t attrs_len;
+ char *attrs_ser;
+ int n;
+
+ {
+ /* First delete duplicates */
+ struct GNUNET_SQ_QueryParam dparams[] = {
+ GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+ GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+ GNUNET_SQ_query_param_end
+ };
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->delete_ticket,
+ dparams))
+ {
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_bind_XXXX");
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->delete_ticket);
+ return GNUNET_SYSERR;
+ }
+ n = sqlite3_step (plugin->delete_ticket);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->delete_ticket);
+
+ attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
+ attrs_ser = GNUNET_malloc (attrs_len);
+ GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
+ attrs_ser);
+ struct GNUNET_SQ_QueryParam sparams[] = {
+ GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+ GNUNET_SQ_query_param_auto_from_type (&ticket->audience),
+ GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+ GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len),
+ GNUNET_SQ_query_param_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->store_ticket,
+ sparams))
+ {
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_bind_XXXX");
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->store_ticket);
+ return GNUNET_SYSERR;
+ }
+ n = sqlite3_step (plugin->store_ticket);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->store_ticket);
+ GNUNET_free (attrs_ser);
+ }
+ switch (n)
+ {
+ case SQLITE_DONE:
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "sqlite",
+ "Ticket stored\n");
+ return GNUNET_OK;
+ case SQLITE_BUSY:
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_step");
+ return GNUNET_NO;
+ default:
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_step");
+ return GNUNET_SYSERR;
+ }
+}
+
+
+/**
+ * Store a ticket in the database.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param ticket the ticket to delete
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+identity_provider_sqlite_delete_ticket (void *cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
+{
+ struct Plugin *plugin = cls;
+ int n;
+
+ {
+ struct GNUNET_SQ_QueryParam sparams[] = {
+ GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+ GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+ GNUNET_SQ_query_param_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->delete_ticket,
+ sparams))
+ {
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_bind_XXXX");
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->store_ticket);
+ return GNUNET_SYSERR;
+ }
+ n = sqlite3_step (plugin->delete_ticket);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->delete_ticket);
+ }
+ switch (n)
+ {
+ case SQLITE_DONE:
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "sqlite",
+ "Ticket deleted\n");
+ return GNUNET_OK;
+ case SQLITE_BUSY:
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_step");
+ return GNUNET_NO;
+ default:
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_step");
+ return GNUNET_SYSERR;
+ }
+}
+
+
+/**
+ * The given 'sqlite' statement has been prepared to be run.
+ * It will return a record which should be given to the iterator.
+ * Runs the statement and parses the returned record.
+ *
+ * @param plugin plugin context
+ * @param stmt to run (and then clean up)
+ * @param iter iterator to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
+ */
+static int
+get_ticket_and_call_iterator (struct Plugin *plugin,
+ sqlite3_stmt *stmt,
+ GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
+ void *iter_cls)
+{
+ struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+ struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+ int ret;
+ int sret;
+ size_t attrs_len;
+ char *attrs_ser;
+
+ ret = GNUNET_NO;
+ if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
+ {
+ struct GNUNET_SQ_ResultSpec rs[] = {
+ GNUNET_SQ_result_spec_auto_from_type (&ticket.identity),
+ GNUNET_SQ_result_spec_auto_from_type (&ticket.audience),
+ GNUNET_SQ_result_spec_uint64 (&ticket.rnd),
+ GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser,
+ &attrs_len),
+ GNUNET_SQ_result_spec_end
+
+ };
+ ret = GNUNET_SQ_extract_result (stmt,
+ rs);
+ if (GNUNET_OK != ret)
+ {
+ GNUNET_break (0);
+ ret = GNUNET_SYSERR;
+ }
+ else
+ {
+ attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (attrs_ser,
+ attrs_len);
+ if (NULL != iter)
+ iter (iter_cls,
+ &ticket,
+ attrs);
+ GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
+ ret = GNUNET_YES;
+ }
+ GNUNET_SQ_cleanup_result (rs);
+ }
+ else
+ {
+ if (SQLITE_DONE != sret)
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR,
+ "sqlite_step");
+ }
+ GNUNET_SQ_reset (plugin->dbh,
+ stmt);
+ return ret;
+}
+
+
+/**
+ * Lookup tickets in the datastore.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param ticket the ticket to retrieve attributes for
+ * @param iter function to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+identity_provider_sqlite_ticket_get_attrs (void *cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+ GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
+ void *iter_cls)
+{
+ struct Plugin *plugin = cls;
+ struct GNUNET_SQ_QueryParam params[] = {
+ GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+ GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+ GNUNET_SQ_query_param_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->get_ticket_attrs,
+ params))
+ {
+ LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_bind_XXXX");
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_ticket_attrs);
+ return GNUNET_SYSERR;
+ }
+ return get_ticket_and_call_iterator (plugin,
+ plugin->get_ticket_attrs,
+ iter,
+ iter_cls);
+}
+
+
+/**
+ * Iterate over the results for a particular key and zone in the
+ * datastore. Will return at most one result to the iterator.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param identity the issuing identity or audience (depending on audience switch)
+ * @param audience GNUNET_YES if identity is audience
+ * @param offset offset in the list of all matching records
+ * @param iter function to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
+ */
+static int
+identity_provider_sqlite_iterate_tickets (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+ int audience,
+ uint64_t offset,
+ GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
+ void *iter_cls)
+{
+ struct Plugin *plugin = cls;
+ sqlite3_stmt *stmt;
+ int err;
+
+ if (NULL == identity)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ struct GNUNET_SQ_QueryParam params[] = {
+ GNUNET_SQ_query_param_auto_from_type (identity),
+ GNUNET_SQ_query_param_uint64 (&offset),
+ GNUNET_SQ_query_param_end
+ };
+ if (GNUNET_YES == audience)
+ {
+ stmt = plugin->iterate_tickets_by_audience;
+ err = GNUNET_SQ_bind (stmt,
+ params);
+ }
+ else
+ {
+ stmt = plugin->iterate_tickets;
+ err = GNUNET_SQ_bind (stmt,
+ params);
+ }
+ if (GNUNET_OK != err)
+ {
+ LOG_SQLITE (plugin,
+ GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_bind_XXXX");
+ GNUNET_SQ_reset (plugin->dbh,
+ stmt);
+ return GNUNET_SYSERR;
+ }
+ return get_ticket_and_call_iterator (plugin,
+ stmt,
+ iter,
+ iter_cls);
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls the "struct GNUNET_IDENTITY_PROVIDER_PluginEnvironment*"
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_identity_provider_sqlite_init (void *cls)
+{
+ static struct Plugin plugin;
+ const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+ struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api;
+
+ if (NULL != plugin.cfg)
+ return NULL; /* can only initialize once! */
+ memset (&plugin, 0, sizeof (struct Plugin));
+ plugin.cfg = cfg;
+ if (GNUNET_OK != database_setup (&plugin))
+ {
+ database_shutdown (&plugin);
+ return NULL;
+ }
+ api = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_PluginFunctions);
+ api->cls = &plugin;
+ api->store_ticket = &identity_provider_sqlite_store_ticket;
+ api->delete_ticket = &identity_provider_sqlite_delete_ticket;
+ api->iterate_tickets = &identity_provider_sqlite_iterate_tickets;
+ api->get_ticket_attributes = &identity_provider_sqlite_ticket_get_attrs;
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ _("Sqlite database running\n"));
+ return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_identity_provider_sqlite_done (void *cls)
+{
+ struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api = cls;
+ struct Plugin *plugin = api->cls;
+
+ database_shutdown (plugin);
+ plugin->cfg = NULL;
+ GNUNET_free (api);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "sqlite plugin is finished\n");
+ return NULL;
+}
+
+/* end of plugin_identity_provider_sqlite.c */
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c
index 907b28ba9..6eb856435 100644
--- a/src/identity-provider/plugin_rest_identity_provider.c
+++ b/src/identity-provider/plugin_rest_identity_provider.c
@@ -37,6 +37,7 @@
#include <jansson.h>
#include <inttypes.h>
#include "gnunet_signatures.h"
+#include "gnunet_identity_attribute_lib.h"
#include "gnunet_identity_provider_service.h"
/**
@@ -45,39 +46,40 @@
#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp"
/**
- * Issue namespace
+ * Attribute namespace
*/
-#define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/idp/issue"
+#define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes"
/**
- * Check namespace TODO
+ * Ticket namespace
*/
-#define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/idp/check"
+#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets"
/**
- * Token namespace
+ * Revoke namespace
*/
-#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token"
+#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke"
/**
- * The parameter name in which the ticket must be provided
+ * Revoke namespace
*/
-#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket"
+#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume"
/**
- * The parameter name in which the expected nonce must be provided
+ * Attribute key
*/
-#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce"
+#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute"
/**
- * The parameter name in which the ticket must be provided
+ * Ticket key
*/
-#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token"
+#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
+
/**
- * The URL parameter name in which the nonce must be provided
+ * Value key
*/
-#define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce"
+#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value"
/**
* State while collecting all egos
@@ -89,41 +91,6 @@
*/
#define ID_REST_STATE_POST_INIT 1
-/**
- * Resource type
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
-
-/**
- * URL parameter to create a GNUid token for a specific audience
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
-
-/**
- * URL parameter to create a GNUid token for a specific issuer (EGO)
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
-
-/**
- * Attributes passed to issue request
- */
-#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
-
-/**
- * Token expiration string
- */
-#define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
-
-/**
- * Error messages
- */
-#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
-#define GNUNET_REST_ERROR_NO_DATA "No data"
-
-/**
- * GNUid token lifetime
- */
-#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
/**
* The configuration handle
@@ -198,11 +165,6 @@ struct RequestHandle
const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
/**
- * Handle to the rest connection
- */
- struct GNUNET_REST_RequestHandle *conndata_handle;
-
- /**
* The processing state
*/
int state;
@@ -213,6 +175,12 @@ struct RequestHandle
struct GNUNET_IDENTITY_Handle *identity_handle;
/**
+ * Rest connection
+ */
+ struct GNUNET_REST_RequestHandle *rest_handle;
+
+
+ /**
* IDENTITY Operation
*/
struct GNUNET_IDENTITY_Operation *op;
@@ -228,19 +196,14 @@ struct RequestHandle
struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
/**
- * Handle to NS service
- */
- struct GNUNET_NAMESTORE_Handle *ns_handle;
-
- /**
- * NS iterator
+ * Attribute iterator
*/
- struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+ struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
/**
- * NS Handle
+ * Ticket iterator
*/
- struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+ struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
/**
* Desired timeout for the lookup (default is no timeout).
@@ -285,6 +248,7 @@ struct RequestHandle
};
+
/**
* Cleanup lookup handle
* @param handle Handle to clean up
@@ -302,14 +266,12 @@ cleanup_handle (struct RequestHandle *handle)
GNUNET_SCHEDULER_cancel (handle->timeout_task);
if (NULL != handle->identity_handle)
GNUNET_IDENTITY_disconnect (handle->identity_handle);
+ if (NULL != handle->attr_it)
+ GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it);
+ if (NULL != handle->ticket_it)
+ GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it);
if (NULL != handle->idp)
GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
- if (NULL != handle->ns_it)
- GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
- if (NULL != handle->ns_qe)
- GNUNET_NAMESTORE_cancel (handle->ns_qe);
- if (NULL != handle->ns_handle)
- GNUNET_NAMESTORE_disconnect (handle->ns_handle);
if (NULL != handle->url)
GNUNET_free (handle->url);
if (NULL != handle->emsg)
@@ -326,6 +288,12 @@ cleanup_handle (struct RequestHandle *handle)
GNUNET_free (handle);
}
+static void
+cleanup_handle_delayed (void *cls)
+{
+ cleanup_handle (cls);
+}
+
/**
* Task run on error, sends error message. Cleans up everything.
@@ -363,622 +331,663 @@ do_timeout (void *cls)
}
-/**
- * Task run on shutdown. Cleans up everything.
- *
- * @param cls unused
- */
static void
-do_cleanup_handle_delayed (void *cls)
+collect_error_cb (void *cls)
{
struct RequestHandle *handle = cls;
- cleanup_handle (handle);
+ do_error (handle);
}
-
-/**
- * Get a ticket for identity
- * @param cls the handle
- * @param ticket the ticket returned from the idp
- */
static void
-token_creat_cont (void *cls,
- const char *label,
- const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
- const struct GNUNET_IDENTITY_PROVIDER_Token *token)
+finished_cont (void *cls,
+ int32_t success,
+ const char *emsg)
{
- struct GNUNET_JSONAPI_Resource *json_resource;
struct RequestHandle *handle = cls;
struct MHD_Response *resp;
- json_t *ticket_json;
- json_t *token_json;
- char *ticket_str;
- char *token_str;
- char *result_str;
- if (NULL == ticket)
+ resp = GNUNET_REST_create_response (emsg);
+ if (GNUNET_OK != success)
{
- handle->emsg = GNUNET_strdup ("Error in token issue");
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+ GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+}
- handle->resp_object = GNUNET_JSONAPI_document_new ();
- json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
- label);
- ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
- token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
- ticket_json = json_string (ticket_str);
- token_json = json_string (token_str);
- GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
- ticket_json);
- GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN,
- token_json);
- GNUNET_free (ticket_str);
- GNUNET_free (token_str);
- json_decref (ticket_json);
- json_decref (token_json);
- GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+/**
+ * Return attributes for identity
+ *
+ * @param cls the request handle
+ */
+static void
+return_response (void *cls)
+{
+ char* result_str;
+ struct RequestHandle *handle = cls;
+ struct MHD_Response *resp;
GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
resp = GNUNET_REST_create_response (result_str);
handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
GNUNET_free (result_str);
- GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle);
+ cleanup_handle (handle);
+}
+
+
+static void
+collect_finished_cb (void *cls)
+{
+ struct RequestHandle *handle = cls;
+ //Done
+ handle->attr_it = NULL;
+ handle->ticket_it = NULL;
+ GNUNET_SCHEDULER_add_now (&return_response, handle);
}
/**
- * Continueationf for token issue request
+ * Collect all attributes for an ego
*
- * @param con the Rest handle
- * @param url the requested url
- * @param cls the request handle
*/
static void
-issue_token_cont (struct GNUNET_REST_RequestHandle *con,
- const char *url,
- void *cls)
+ticket_collect (void *cls,
+ const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
{
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
- const char *egoname;
+ struct GNUNET_JSONAPI_Resource *json_resource;
+ struct RequestHandle *handle = cls;
+ json_t *value;
+ char* tmp;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
+ tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+ sizeof (uint64_t));
+ json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET,
+ tmp);
+ GNUNET_free (tmp);
+ GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+ tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ value = json_string (tmp);
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ "issuer",
+ value);
+ GNUNET_free (tmp);
+ json_decref (value);
+ tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ value = json_string (tmp);
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ "audience",
+ value);
+ GNUNET_free (tmp);
+ json_decref (value);
+ tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+ sizeof (uint64_t));
+ value = json_string (tmp);
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ "rnd",
+ value);
+ GNUNET_free (tmp);
+ json_decref (value);
+ GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (handle->ticket_it);
+}
+
+
+/**
+ * List tickets for identity request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char* url,
+ void *cls)
+{
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
struct RequestHandle *handle = cls;
struct EgoEntry *ego_entry;
- struct GNUNET_HashCode key;
- struct MHD_Response *resp;
- struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
- struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
- struct GNUNET_TIME_Relative etime_rel;
- struct GNUNET_TIME_Absolute exp_time;
- char *ego_val;
- char *audience;
- char *exp_str;
- char *nonce_str;
- char *scopes;
- uint64_t time;
- uint64_t nonce;
-
- if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
- GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
- resp = GNUNET_REST_create_response (NULL);
- handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
- cleanup_handle (handle);
- return;
- }
- egoname = NULL;
- ego_entry = NULL;
- GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
- strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
- &key);
- if ( GNUNET_YES !=
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
- &key) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Issuer not found\n");
- GNUNET_SCHEDULER_add_now (&do_error, handle);
- return;
- }
- ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
- if (NULL == ego_val)
+ char *identity;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
+ handle->url);
+ if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
+ strlen (handle->url))
{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
GNUNET_SCHEDULER_add_now (&do_error, handle);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Ego invalid: %s\n",
- ego_val);
return;
}
+ identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
+
for (ego_entry = handle->ego_head;
NULL != ego_entry;
ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
+ handle->resp_object = GNUNET_JSONAPI_document_new ();
+
+ if (NULL == ego_entry)
{
- if (0 != strcmp (ego_val, ego_entry->identifier))
- continue;
- egoname = ego_entry->identifier;
- break;
- }
- if ( (NULL == egoname) ||
- (NULL == ego_entry) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Ego not found: %s\n",
- ego_val);
- GNUNET_SCHEDULER_add_now (&do_error, handle);
+ //Done
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
+ identity);
+ GNUNET_SCHEDULER_add_now (&return_response, handle);
return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Ego to issue token for: %s\n",
- egoname);
+ priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+ handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
+ handle->ticket_it = GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (handle->idp,
+ priv_key,
+ &collect_error_cb,
+ handle,
+ &ticket_collect,
+ handle,
+ &collect_finished_cb,
+ handle);
+}
- //Meta info
- GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST,
- strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST),
- &key);
+static void
+add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char* url,
+ void *cls)
+{
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+ const char* identity;
+ const char* name_str;
+ const char* value_str;
- scopes = NULL;
- if ( GNUNET_YES !=
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
- &key) )
+ struct RequestHandle *handle = cls;
+ struct EgoEntry *ego_entry;
+ struct MHD_Response *resp;
+ struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attribute;
+ struct GNUNET_JSONAPI_Document *json_obj;
+ struct GNUNET_JSONAPI_Resource *json_res;
+ char term_data[handle->rest_handle->data_size+1];
+ json_t *value_json;
+ json_t *data_json;
+ json_error_t err;
+ struct GNUNET_JSON_Specification docspec[] = {
+ GNUNET_JSON_spec_jsonapi_document (&json_obj),
+ GNUNET_JSON_spec_end()
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
+ handle->url);
+ if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
+ strlen (handle->url))
{
- handle->emsg = GNUNET_strdup ("Scopes missing!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
-
-
- //Token audience
- GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
- strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
- &key);
- audience = NULL;
- if ( GNUNET_YES !=
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
- &key) )
+ identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
+
+ for (ego_entry = handle->ego_head;
+ NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
+
+ if (NULL == ego_entry)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Audience missing!\n");
- GNUNET_SCHEDULER_add_now (&do_error, handle);
+ "Identity unknown (%s)\n", identity);
+ GNUNET_JSONAPI_document_delete (json_obj);
return;
}
- audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Audience to issue token for: %s\n",
- audience);
-
- priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
- GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
- &pub_key);
- GNUNET_STRINGS_string_to_data (audience,
- strlen (audience),
- &aud_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
- //Remote nonce
- nonce_str = NULL;
- GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
- strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
- &key);
- if ( GNUNET_YES !=
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
- &key) )
+ if (0 >= handle->rest_handle->data_size)
{
- handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
- GNUNET_assert (NULL != nonce_str);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Request nonce: %s\n",
- nonce_str);
- GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce));
-
- //Get expiration for token from URL parameter
- GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
- strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING),
- &key);
-
- exp_str = NULL;
- if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
- &key))
+
+ term_data[handle->rest_handle->data_size] = '\0';
+ GNUNET_memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_json = json_loads (term_data,
+ JSON_DECODE_ANY,
+ &err);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (data_json, docspec,
+ NULL, NULL));
+ json_decref (data_json);
+ if (NULL == json_obj)
{
- exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
- }
- if (NULL == exp_str) {
- handle->emsg = GNUNET_strdup ("No expiration given!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse JSONAPI Object from %s\n",
+ term_data);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
-
- if (GNUNET_OK !=
- GNUNET_STRINGS_fancy_time_to_relative (exp_str,
- &etime_rel))
+ if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
{
- handle->emsg = GNUNET_strdup ("Expiration invalid!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Cannot create more than 1 resource! (Got %d)\n",
+ GNUNET_JSONAPI_document_resource_count (json_obj));
+ GNUNET_JSONAPI_document_delete (json_obj);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- time = GNUNET_TIME_absolute_get().abs_value_us;
- exp_time.abs_value_us = time + etime_rel.rel_value_us;
-
+ json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+ if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+ GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unsupported JSON data type\n");
+ GNUNET_JSONAPI_document_delete (json_obj);
+ resp = GNUNET_REST_create_response (NULL);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+ cleanup_handle (handle);
+ return;
+ }
+ name_str = GNUNET_JSONAPI_resource_get_id (json_res);
+ value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+ "value");
+ value_str = json_string_value (value_json);
+ attribute = GNUNET_IDENTITY_ATTRIBUTE_claim_new (name_str,
+ GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
+ value_str,
+ strlen (value_str) + 1);
handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
- handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp,
- priv_key,
- &aud_key,
- scopes,
- exp_time,
- nonce,
- &token_creat_cont,
- handle);
-
-}
-
-
-/**
- * Build a GNUid token for identity
- *
- * @param cls the request handle
- */
-static void
-return_token_list (void *cls)
-{
- char* result_str;
- struct RequestHandle *handle = cls;
- struct MHD_Response *resp;
-
- GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
- resp = GNUNET_REST_create_response (result_str);
- handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
- GNUNET_free (result_str);
- cleanup_handle (handle);
+ handle->idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (handle->idp,
+ identity_priv,
+ attribute,
+ &finished_cont,
+ handle);
+ GNUNET_free (attribute);
+ GNUNET_JSONAPI_document_delete (json_obj);
}
-static void
-token_collect_error_cb (void *cls)
-{
- struct RequestHandle *handle = cls;
-
- do_error (handle);
-}
-
/**
- * Collect all tokens for an ego
- *
- * TODO move this into the identity-provider service
+ * Collect all attributes for an ego
*
*/
static void
-token_collect (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
- const char *label,
- unsigned int rd_count,
- const struct GNUNET_GNSRECORD_Data *rd);
-
-
-static void
-token_collect_finished_cb (void *cls)
+attr_collect (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
{
+ struct GNUNET_JSONAPI_Resource *json_resource;
struct RequestHandle *handle = cls;
- struct EgoEntry *ego_tmp;
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-
- ego_tmp = handle->ego_head;
- GNUNET_CONTAINER_DLL_remove (handle->ego_head,
- handle->ego_tail,
- ego_tmp);
- GNUNET_free (ego_tmp->identifier);
- GNUNET_free (ego_tmp->keystring);
- GNUNET_free (ego_tmp);
-
- if (NULL == handle->ego_head)
+ json_t *value;
+
+ if ((NULL == attr->name) || (NULL == attr->data))
{
- //Done
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
- handle->ns_it = NULL;
- GNUNET_SCHEDULER_add_now (&return_token_list, handle);
+ GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Next ego: %s\n",
- handle->ego_head->identifier);
- priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
- handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
- priv_key,
- &token_collect_error_cb,
- handle,
- &token_collect,
- handle,
- &token_collect_finished_cb,
- handle);
-}
-
-
-/**
- * Collect all tokens for an ego
- *
- * TODO move this into the identity-provider service
- *
- */
-static void
-token_collect (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
- const char *label,
- unsigned int rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
-{
- struct RequestHandle *handle = cls;
- int i;
- char* data;
- struct GNUNET_JSONAPI_Resource *json_resource;
- json_t *issuer;
- json_t *token;
-
- for (i = 0; i < rd_count; i++)
- {
- if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
- {
- data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
- rd[i].data,
- rd[i].data_size);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
- json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
- label);
- issuer = json_string (handle->ego_head->identifier);
- GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
- issuer);
- json_decref (issuer);
- token = json_string (data);
- GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
- token);
- json_decref (token);
-
- GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
- GNUNET_free (data);
- }
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
+ attr->name);
+ json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
+ attr->name);
+ GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
- GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+ value = json_string (attr->data);
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ "value",
+ value);
+ json_decref (value);
+ GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
}
/**
- * Respond to OPTIONS request
+ * List attributes for identity request
*
* @param con_handle the connection handle
* @param url the url
* @param cls the RequestHandle
*/
static void
-list_token_cont (struct GNUNET_REST_RequestHandle *con_handle,
- const char* url,
- void *cls)
+list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char* url,
+ void *cls)
{
- char* ego_val;
- struct GNUNET_HashCode key;
const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
struct RequestHandle *handle = cls;
struct EgoEntry *ego_entry;
- struct EgoEntry *ego_tmp;
+ char *identity;
- GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
- strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
- &key);
-
- if ( GNUNET_YES !=
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
- &key) )
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
+ handle->url);
+ if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
+ strlen (handle->url))
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No issuer given.\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
- GNUNET_assert (NULL != ego_val);
- //Remove non-matching egos
+ identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
+
for (ego_entry = handle->ego_head;
- NULL != ego_entry;)
- {
- ego_tmp = ego_entry;
- ego_entry = ego_entry->next;
- if (0 != strcmp (ego_val, ego_tmp->identifier))
- {
- GNUNET_CONTAINER_DLL_remove (handle->ego_head,
- handle->ego_tail,
- ego_tmp);
- GNUNET_free (ego_tmp->identifier);
- GNUNET_free (ego_tmp->keystring);
- GNUNET_free (ego_tmp);
- }
- }
+ NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ if (0 == strcmp (identity, ego_entry->identifier))
+ break;
handle->resp_object = GNUNET_JSONAPI_document_new ();
- if (NULL == handle->ego_head)
+
+
+ if (NULL == ego_entry)
{
//Done
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n");
- GNUNET_SCHEDULER_add_now (&return_token_list, handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
+ identity);
+ GNUNET_SCHEDULER_add_now (&return_response, handle);
return;
}
- priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
- handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
- handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
- priv_key,
- &token_collect_error_cb,
- handle,
- &token_collect,
- handle,
- &token_collect_finished_cb,
- handle);
-
+ priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+ handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
+ handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (handle->idp,
+ priv_key,
+ &collect_error_cb,
+ handle,
+ &attr_collect,
+ handle,
+ &collect_finished_cb,
+ handle);
}
-/**
- * Return token to requestor
- *
- * @param cls request handle
- * @param token the token
- */
+
static void
-exchange_cont (void *cls,
- const struct GNUNET_IDENTITY_PROVIDER_Token *token,
- uint64_t ticket_nonce)
+revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char* url,
+ void *cls)
{
- json_t *root;
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+ const char* identity_str;
+ const char* audience_str;
+ const char* rnd_str;
+
struct RequestHandle *handle = cls;
+ struct EgoEntry *ego_entry;
struct MHD_Response *resp;
- struct GNUNET_HashCode key;
- char* result;
- char* token_str;
- char* nonce_str;
- uint64_t expected_nonce;
-
- //Get nonce
- GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE,
- strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE),
- &key);
-
- if ( GNUNET_NO ==
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
- &key) )
+ struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+ struct GNUNET_JSONAPI_Document *json_obj;
+ struct GNUNET_JSONAPI_Resource *json_res;
+ struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+ char term_data[handle->rest_handle->data_size+1];
+ json_t *rnd_json;
+ json_t *identity_json;
+ json_t *audience_json;
+ json_t *data_json;
+ json_error_t err;
+ struct GNUNET_JSON_Specification docspec[] = {
+ GNUNET_JSON_spec_jsonapi_document (&json_obj),
+ GNUNET_JSON_spec_end()
+ };
+
+ if (0 >= handle->rest_handle->data_size)
{
- handle->emsg = GNUNET_strdup ("No nonce given.");
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
- GNUNET_assert (NULL != nonce_str);
- GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
- if (ticket_nonce != expected_nonce)
+ term_data[handle->rest_handle->data_size] = '\0';
+ GNUNET_memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_json = json_loads (term_data,
+ JSON_DECODE_ANY,
+ &err);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (data_json, docspec,
+ NULL, NULL));
+ json_decref (data_json);
+ if (NULL == json_obj)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse JSONAPI Object from %s\n",
+ term_data);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Ticket nonce %"SCNu64" does not match expected nonce %"SCNu64"\n",
- ticket_nonce, expected_nonce);
- handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n");
+ "Cannot create more than 1 resource! (Got %d)\n",
+ GNUNET_JSONAPI_document_resource_count (json_obj));
+ GNUNET_JSONAPI_document_delete (json_obj);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
+ json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+ if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+ GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unsupported JSON data type\n");
+ GNUNET_JSONAPI_document_delete (json_obj);
+ resp = GNUNET_REST_create_response (NULL);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+ cleanup_handle (handle);
+ return;
+ }
+ rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+ "rnd");
+ identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+ "identity");
+ audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+ "audience");
+ rnd_str = json_string_value (rnd_json);
+ identity_str = json_string_value (identity_json);
+ audience_str = json_string_value (audience_json);
+
+ GNUNET_STRINGS_string_to_data (rnd_str,
+ strlen (rnd_str),
+ &ticket.rnd,
+ sizeof (uint64_t));
+ GNUNET_STRINGS_string_to_data (identity_str,
+ strlen (identity_str),
+ &ticket.identity,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ GNUNET_STRINGS_string_to_data (audience_str,
+ strlen (audience_str),
+ &ticket.audience,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- root = json_object ();
- token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
- json_object_set_new (root, "token", json_string (token_str));
- json_object_set_new (root, "token_type", json_string ("jwt"));
- GNUNET_free (token_str);
+ for (ego_entry = handle->ego_head;
+ NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ {
+ GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+ &tmp_pk);
+ if (0 == memcmp (&ticket.identity,
+ &tmp_pk,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ break;
+ }
+ if (NULL == ego_entry)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Identity unknown (%s)\n", identity_str);
+ GNUNET_JSONAPI_document_delete (json_obj);
+ return;
+ }
+ identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
- result = json_dumps (root, JSON_INDENT(1));
- resp = GNUNET_REST_create_response (result);
- GNUNET_free (result);
- handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
- cleanup_handle (handle);
- json_decref (root);
+ handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
+ handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp,
+ identity_priv,
+ &ticket,
+ &finished_cont,
+ handle);
+ GNUNET_JSONAPI_document_delete (json_obj);
}
-
-/**
- *
- * Callback called when identity for token exchange has been found
- *
- * @param cls request handle
- * @param ego the identity to use as issuer
- * @param ctx user context
- * @param name identity name
- *
- */
static void
-exchange_token_ticket_cb (void *cls,
- struct GNUNET_IDENTITY_Ego *ego,
- void **ctx,
- const char *name)
+consume_cont (void *cls,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+ const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
{
struct RequestHandle *handle = cls;
- struct GNUNET_HashCode key;
- struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
- char* ticket_str;
+ struct GNUNET_JSONAPI_Resource *json_resource;
+ json_t *value;
- handle->op = NULL;
+ if (NULL == identity)
+ {
+ GNUNET_SCHEDULER_add_now (&return_response, handle);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
+ attr->name);
+ json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
+ attr->name);
+ GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+ value = json_string (attr->data);
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
+ "value",
+ value);
+ json_decref (value);
+}
- if (NULL == ego)
+static void
+consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+ const char* url,
+ void *cls)
+{
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+ const char* identity_str;
+ const char* audience_str;
+ const char* rnd_str;
+
+ struct RequestHandle *handle = cls;
+ struct EgoEntry *ego_entry;
+ struct MHD_Response *resp;
+ struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+ struct GNUNET_JSONAPI_Document *json_obj;
+ struct GNUNET_JSONAPI_Resource *json_res;
+ struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+ char term_data[handle->rest_handle->data_size+1];
+ json_t *rnd_json;
+ json_t *identity_json;
+ json_t *audience_json;
+ json_t *data_json;
+ json_error_t err;
+ struct GNUNET_JSON_Specification docspec[] = {
+ GNUNET_JSON_spec_jsonapi_document (&json_obj),
+ GNUNET_JSON_spec_end()
+ };
+
+ if (0 >= handle->rest_handle->data_size)
{
- handle->emsg = GNUNET_strdup ("No identity found.");
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- //Get ticket
- GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
- strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET),
- &key);
-
- if ( GNUNET_NO ==
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
- &key) )
+ term_data[handle->rest_handle->data_size] = '\0';
+ GNUNET_memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_json = json_loads (term_data,
+ JSON_DECODE_ANY,
+ &err);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (data_json, docspec,
+ NULL, NULL));
+ json_decref (data_json);
+ if (NULL == json_obj)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse JSONAPI Object from %s\n",
+ term_data);
+ GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
+ }
+ if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
{
- handle->emsg = GNUNET_strdup ("No ticket given.");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Cannot create more than 1 resource! (Got %d)\n",
+ GNUNET_JSONAPI_document_resource_count (json_obj));
+ GNUNET_JSONAPI_document_delete (json_obj);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- ticket_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
- handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego);
- GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str,
- &ticket);
+ json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+ if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+ GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unsupported JSON data type\n");
+ GNUNET_JSONAPI_document_delete (json_obj);
+ resp = GNUNET_REST_create_response (NULL);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+ cleanup_handle (handle);
+ return;
+ }
+ rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+ "rnd");
+ identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+ "identity");
+ audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+ "audience");
+ rnd_str = json_string_value (rnd_json);
+ identity_str = json_string_value (identity_json);
+ audience_str = json_string_value (audience_json);
+
+ GNUNET_STRINGS_string_to_data (rnd_str,
+ strlen (rnd_str),
+ &ticket.rnd,
+ sizeof (uint64_t));
+ GNUNET_STRINGS_string_to_data (identity_str,
+ strlen (identity_str),
+ &ticket.identity,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ GNUNET_STRINGS_string_to_data (audience_str,
+ strlen (audience_str),
+ &ticket.audience,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ for (ego_entry = handle->ego_head;
+ NULL != ego_entry;
+ ego_entry = ego_entry->next)
+ {
+ GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+ &tmp_pk);
+ if (0 == memcmp (&ticket.audience,
+ &tmp_pk,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ break;
+ }
+ if (NULL == ego_entry)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Identity unknown (%s)\n", identity_str);
+ GNUNET_JSONAPI_document_delete (json_obj);
+ return;
+ }
+ identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+ handle->resp_object = GNUNET_JSONAPI_document_new ();
handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
- handle->idp_op = GNUNET_IDENTITY_PROVIDER_exchange_ticket (handle->idp,
- ticket,
- handle->priv_key,
- &exchange_cont,
- handle);
- GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket);
-
+ handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (handle->idp,
+ identity_priv,
+ &ticket,
+ &consume_cont,
+ handle);
+ GNUNET_JSONAPI_document_delete (json_obj);
}
/**
- * Respond to issue request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
- const char* url,
- void *cls)
-{
- struct RequestHandle *handle = cls;
-
- //Get token from GNS
- handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
- "gns-master",
- &exchange_token_ticket_cb,
- handle);
-}
-
-/**
* Respond to OPTIONS request
*
* @param con_handle the connection handle
@@ -1013,15 +1022,17 @@ init_cont (struct RequestHandle *handle)
{
struct GNUNET_REST_RequestHandlerError err;
static const struct GNUNET_REST_RequestHandler handlers[] = {
- {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont},
- //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont},
- {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont},
- {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &options_cont},
- {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_ticket_cont},
+ {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont},
+ {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont},
+ {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
+ {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
+ {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
+ {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER,
+ &options_cont},
GNUNET_REST_HANDLER_END
};
- if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle,
+ if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
handlers,
&err,
handle))
@@ -1092,19 +1103,8 @@ list_ego (void *cls,
}
-/**
- * Function processing the REST call
- *
- * @param method HTTP method
- * @param url URL of the HTTP request
- * @param data body of the HTTP request (optional)
- * @param data_size length of the body
- * @param proc callback function for the result
- * @param proc_cls closure for callback function
- * @return GNUNET_OK if request accepted
- */
static void
-rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
GNUNET_REST_ResultProcessor proc,
void *proc_cls)
{
@@ -1114,10 +1114,9 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
handle->proc_cls = proc_cls;
handle->proc = proc;
handle->state = ID_REST_STATE_INIT;
- handle->conndata_handle = conndata_handle;
+ handle->rest_handle = rest_handle;
-
- handle->url = GNUNET_strdup (conndata_handle->url);
+ handle->url = GNUNET_strdup (rest_handle->url);
if (handle->url[strlen (handle->url)-1] == '/')
handle->url[strlen (handle->url)-1] = '\0';
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1162,8 +1161,8 @@ libgnunet_plugin_rest_identity_provider_init (void *cls)
MHD_HTTP_METHOD_DELETE,
MHD_HTTP_METHOD_OPTIONS);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Identity Token REST API initialized\n"));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _("Identity Provider REST API initialized\n"));
return api;
}
@@ -1184,8 +1183,8 @@ libgnunet_plugin_rest_identity_provider_done (void *cls)
GNUNET_free_non_null (allow_methods);
GNUNET_free (api);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Identity Token REST plugin is finished\n");
+ "Identity Provider REST plugin is finished\n");
return NULL;
}
-/* end of plugin_rest_gns.c */
+/* 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 @@
+@INLINE@ test_idp_defaults.conf
+
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-gnunet-idp-peer-1/
+
+[dht]
+AUTOSTART = YES
+
+[rest]
+AUTOSTART = YES
+#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
+
+[transport]
+PLUGINS =
+
+[identity-provider]
+AUTOSTART = YES
+#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=/tmp/idplog
+
+[gns]
+#PREFIX = valgrind --leak-check=full --track-origins=yes
+AUTOSTART = YES
+AUTO_IMPORT_PKEY = YES
+MAX_PARALLEL_BACKGROUND_QUERIES = 10
+DEFAULT_LOOKUP_TIMEOUT = 15 s
+RECORD_PUT_INTERVAL = 1 h
+ZONE_PUBLISH_TIME_WINDOW = 1 h
+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 @@
+#!/bin/bash
+#trap "gnunet-arm -e -c test_idp_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+gnunet-identity -C testego -c test_idp.conf
+valgrind gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
+gnunet-idp -e testego -a name -V John -c test_idp.conf
+gnunet-idp -e testego -D -c test_idp.conf
+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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_idp.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+#gnunet-arm -i rest -c test_idp.conf
+gnunet-identity -C testego -c test_idp.conf
+gnunet-identity -C rpego -c test_idp.conf
+TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
+gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
+gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
+if test $? != 0
+then
+ echo "Failed."
+ exit 1
+fi
+
+#curl localhost:7776/idp/attributes/testego
+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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_idp.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+#gnunet-arm -i rest -c test_idp.conf
+gnunet-identity -C testego -c test_idp.conf
+gnunet-identity -C rpego -c test_idp.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}')
+TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
+gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
+gnunet-idp -e testego -a name -V John -c test_idp.conf
+TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf | awk '{print $1}')
+gnunet-idp -e rpego -C $TICKET -c test_idp.conf > /dev/null 2>&1
+
+if test $? != 0
+then
+ "Failed."
+ exit 1
+fi
+#curl http://localhost:7776/idp/tickets/testego
+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 @@
+@INLINE@ ../../contrib/no_forcestart.conf
+
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-gnunet-idp-testing/
+
+[namestore-sqlite]
+FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
+
+[namecache-sqlite]
+FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db
+
+[identity]
+# Directory where we store information about our egos
+EGODIR = $GNUNET_TEST_HOME/identity/egos/
+
+[dhtcache]
+DATABASE = heap
+
+[transport]
+PLUGINS = tcp
+
+[transport-tcp]
+BINDTO = 127.0.0.1
+
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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_idp.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+#gnunet-arm -i rest -c test_idp.conf
+gnunet-identity -C testego -c test_idp.conf
+gnunet-identity -C rpego -c test_idp.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}')
+TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
+gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf > /dev/null 2>&1
+gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
+#gnunet-idp -e testego -D -c test_idp.conf
+gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf > /dev/null 2>&1
+if test $? != 0
+then
+ echo "Failed."
+ exit 1
+fi
+#curl http://localhost:7776/idp/attributes/testego
+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 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_idp.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+ LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+ echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+ exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+# (1) PKEY1.user -> PKEY2.resu.user
+# (2) PKEY2.resu -> PKEY3
+# (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+gnunet-identity -C alice -c test_idp.conf
+gnunet-identity -C bob -c test_idp.conf
+gnunet-identity -C eve -c test_idp.conf
+ALICE_KEY=$(gnunet-identity -d -c test_idp.conf | grep alice | awk '{print $3}')
+BOB_KEY=$(gnunet-identity -d -c test_idp.conf | grep bob | awk '{print $3}')
+EVE_KEY=$(gnunet-identity -d -c test_idp.conf | grep eve | awk '{print $3}')
+
+gnunet-idp -e alice -a email -V john@doe.gnu -c test_idp.conf
+gnunet-idp -e alice -a name -V John -c test_idp.conf
+TICKET_BOB=$(gnunet-idp -e alice -i "email,name" -r $BOB_KEY -c test_idp.conf | awk '{print $1}')
+#gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf
+TICKET_EVE=$(gnunet-idp -e alice -i "email" -r $EVE_KEY -c test_idp.conf | awk '{print $1}')
+
+
+#echo "Consuming $TICKET"
+#gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf
+gnunet-idp -e alice -R $TICKET_EVE -c test_idp.conf
+
+gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf > /dev/null 2>&1
+if test $? == 0
+then
+ echo "Eve can still resolve attributes..."
+ gnunet-arm -e -c test_idp.conf
+ exit 1
+fi
+gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf > /dev/null 2>&1
+if test $? != 0
+then
+ echo "Bob cannot resolve attributes..."
+ gnunet-arm -e -c test_idp.conf
+ exit 1
+fi
+
+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 = \
if HAVE_MHD
if HAVE_JSON
plugin_LTLIBRARIES = \
- libgnunet_plugin_rest_identity.la \
- libgnunet_plugin_gnsrecord_identity.la
+ libgnunet_plugin_rest_identity.la
endif
endif
@@ -55,14 +54,6 @@ gnunet_service_identity_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(GN_LIBINTL)
-libgnunet_plugin_gnsrecord_identity_la_SOURCES = \
- plugin_gnsrecord_identity.c
-libgnunet_plugin_gnsrecord_identity_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(LTLIBINTL)
-libgnunet_plugin_gnsrecord_identity_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
libgnunet_plugin_rest_identity_la_SOURCES = \
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,
continue;
json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO,
ego_entry->keystring);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Egoname: %s\n",
- ego_entry->identifier);
name_str = json_string (ego_entry->identifier);
GNUNET_JSONAPI_resource_add_attr (
json_resource,
diff --git a/src/include/gnunet_abe_lib.h b/src/include/gnunet_abe_lib.h
new file mode 100644
index 000000000..f73ea2431
--- /dev/null
+++ b/src/include/gnunet_abe_lib.h
@@ -0,0 +1,193 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2001-2018 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file include/gnunet_abe_lib.h
+ * @brief Attribute-Based Encryption primitives for GNUnet
+ *
+ * @author Martin Schanzenbach
+ *
+ * @defgroup abe ABE Crypto library: Attribute-Based Encryption operations
+ *
+ */
+#ifndef GNUNET_ABE_LIB_H
+#define GNUNET_ABE_LIB_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0 /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_common.h"
+#include <gcrypt.h>
+
+/**
+ * @brief type for ABE master keys
+ */
+struct GNUNET_CRYPTO_AbeMasterKey;
+
+/**
+ * @brief type for ABE keys
+ */
+struct GNUNET_CRYPTO_AbeKey;
+
+
+
+/**
+ * @ingroup abe
+ * Create a new CP-ABE master key. Caller must free return value.
+ *
+ * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
+ */
+struct GNUNET_ABE_AbeMasterKey *
+GNUNET_ABE_cpabe_create_master_key (void);
+
+/**
+ * @ingroup abe
+ * Delete a CP-ABE master key.
+ *
+ * @param key the master key
+ * @return fresh private key; free using #GNUNET_free
+ */
+void
+GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key);
+
+/**
+ * @ingroup abe
+ * Create a new CP-ABE key. Caller must free return value.
+ *
+ * @param key the master key
+ * @param attrs the attributes to append to the key
+ * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
+ */
+struct GNUNET_ABE_AbeKey *
+GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
+ char **attrs);
+
+/**
+ * @ingroup abe
+ * Delete a CP-ABE key.
+ *
+ * @param key the key to delete
+ * @param delete_pub GNUNE_YES if the public key should also be freed (bug in gabe)
+ * @return fresh private key; free using #GNUNET_free
+ */
+void
+GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
+ int delete_pub);
+
+
+/**
+ * @ingroup abe
+ * Encrypt a block using sessionkey.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param policy the ABE policy
+ * @param key the key used to encrypt
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_encrypt (const void *block,
+ size_t size,
+ const char *policy,
+ const struct GNUNET_ABE_AbeMasterKey *key,
+ void **result);
+
+/**
+ * @ingroup abe
+ * Decrypt a block using the ABE key.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param key the key used to decrypt
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_decrypt (const void *block,
+ size_t size,
+ const struct GNUNET_ABE_AbeKey *key,
+ void **result);
+
+/**
+ * @ingroup abe
+ * Serialize an ABE key.
+ *
+ * @param key the key to serialize
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
+ void **result);
+
+/**
+ * @ingroup abe
+ * Deserialize a serialized ABE key.
+ *
+ * @param data the data to deserialize
+ * @param len the length of the data.
+ * @return the ABE key. NULL of unsuccessful
+ */
+struct GNUNET_ABE_AbeKey*
+GNUNET_ABE_cpabe_deserialize_key (const void *data,
+ size_t len);
+
+/**
+ * @ingroup abe
+ * Serialize an ABE master key.
+ *
+ * @param key the key to serialize
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_serialize_master_key (const struct GNUNET_ABE_AbeMasterKey *key,
+ void **result);
+
+/**
+ * @ingroup abe
+ * Deserialize an ABE master key.
+ *
+ * @param data the data to deserialize
+ * @param len the length of the data.
+ * @return the ABE key. NULL of unsuccessful
+ */
+struct GNUNET_ABE_AbeMasterKey*
+GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
+ size_t len);
+
+
+#if 0 /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ifndef GNUNET_ABE_LIB_H */
+#endif
+/* end of gnunet_abe_lib.h */
diff --git a/src/include/gnunet_credential_service.h b/src/include/gnunet_credential_service.h
index 9e765c12b..7d6f9e973 100644
--- a/src/include/gnunet_credential_service.h
+++ b/src/include/gnunet_credential_service.h
@@ -34,6 +34,7 @@
#include "gnunet_util_lib.h"
#include "gnunet_gns_service.h"
+#include "gnunet_identity_service.h"
#ifdef __cplusplus
extern "C"
@@ -52,7 +53,157 @@ struct GNUNET_CREDENTIAL_Handle;
/**
* Handle to control a lookup operation.
*/
-struct GNUNET_CREDENTIAL_LookupRequest;
+struct GNUNET_CREDENTIAL_Request;
+
+/*
+* Enum used for checking whether the issuer has the authority to issue credentials or is just a subject
+*/
+enum GNUNET_CREDENTIAL_CredentialFlags {
+
+ //Subject had credentials before, but have been revoked now
+ GNUNET_CREDENTIAL_FLAG_REVOKED=0,
+
+ //Subject flag indicates that the subject is a holder of this credential and may present it as such
+ GNUNET_CREDENTIAL_FLAG_SUBJECT=1,
+
+ //Issuer flag is used to signify that the subject is allowed to issue this credential and delegate issuance
+ GNUNET_CREDENTIAL_FLAG_ISSUER=2
+
+};
+
+GNUNET_NETWORK_STRUCT_BEGIN
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationRecord {
+
+ /**
+ * Number of delegation sets in this record
+ */
+ uint32_t set_count;
+
+ /**
+ * Length of delegation sets
+ */
+ uint64_t data_size;
+ /**
+ * Followed by set_count DelegationSetRecords
+ *
+ */
+};
+
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationRecordSet {
+
+ /**
+ * Public key of the subject this attribute was delegated to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Length of attribute, may be 0
+ */
+ uint32_t subject_attribute_len;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationSet {
+
+ /**
+ * Public key of the subject this attribute was delegated to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ uint32_t subject_attribute_len;
+
+ /**
+ * The subject attribute
+ */
+ const char *subject_attribute;
+};
+
+
+/**
+ * A delegation
+ */
+struct GNUNET_CREDENTIAL_Delegation {
+
+ /**
+ * The issuer of the delegation
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Public key of the subject this attribute was delegated to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Length of the attribute
+ */
+ uint32_t issuer_attribute_len;
+
+ /**
+ * The attribute
+ */
+ const char *issuer_attribute;
+
+ /**
+ * Length of the attribute
+ */
+ uint32_t subject_attribute_len;
+
+ /**
+ * The attribute
+ */
+ const char *subject_attribute;
+};
+
+
+/**
+ * A credential
+ */
+struct GNUNET_CREDENTIAL_Credential {
+
+ /**
+ * The issuer of the credential
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+ /**
+ * Public key of the subject this credential was issued to
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+ /**
+ * Signature of this credential
+ */
+ struct GNUNET_CRYPTO_EcdsaSignature signature;
+
+ /**
+ * Expiration of this credential
+ */
+ struct GNUNET_TIME_Absolute expiration;
+
+ /**
+ * Length of the attribute
+ */
+ uint32_t issuer_attribute_len;
+
+ /**
+ * The attribute
+ */
+ const char *issuer_attribute;
+
+};
+
/**
@@ -61,7 +212,7 @@ struct GNUNET_CREDENTIAL_LookupRequest;
* @param cfg configuration to use
* @return handle to the Credential service, or NULL on error
*/
-struct GNUNET_Credential_Handle *
+struct GNUNET_CREDENTIAL_Handle *
GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
@@ -75,73 +226,131 @@ GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle);
/**
- * Iterator called on obtained result for a Credential lookup.
+ * Iterator called on obtained result for an attribute verification.
+ *
+ * @param cls closure
+ * @param d_count the number of delegations processed
+ * @param delegation_chain the delegations processed
+ * @param c_count the number of credentials found
+ * @param credential the credentials
+ */
+typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *credential);
+
+/**
+ * Iterator called on obtained result for an attribute delegation.
+ *
+ * @param cls closure
+ * @param success GNUNET_YES if successful
+ * @param result the record data that can be handed to the subject
+ */
+typedef void (*GNUNET_CREDENTIAL_DelegateResultProcessor) (void *cls,
+ uint32_t success);
+
+/**
+ * Iterator called on obtained result for an attribute delegation removal.
*
* @param cls closure
- * @param issuer the issuer chain
- * @param issuer_len length of issuer chain
- * @param value the value returned
+ * @param success GNUNET_YES if successful
+ * @param result the record data that can be handed to the subject
*/
-typedef void
-(*GNUNET_CREDENTIAL_LookupResultProcessor) (void *cls,
- struct GNUNET_IDENTITY_Ego *issuer,
- uint16_t issuer_len,
- const struct GNUNET_CREDENTIAL_Value *value);
+typedef void (*GNUNET_CREDENTIAL_RemoveDelegateResultProcessor) (void *cls,
+ uint32_t success);
/**
- * Perform an asynchronous lookup operation for a credential.
+ * Performs attribute verification.
+ * Checks if there is a delegation chain from
+ * attribute ``issuer_attribute'' issued by the issuer
+ * with public key ``issuer_key'' maps to the attribute
+ * ``subject_attribute'' claimed by the subject with key
+ * ``subject_key''
*
* @param handle handle to the Credential service
- * @param credential the credential to look up
- * @param subject Ego to check the credential for
+ * @param issuer_key the issuer public key
+ * @param issuer_attribute the issuer attribute
+ * @param subject_key the subject public key
+ * @param credential_count number of credentials
+ * @param credentials the subject credentials
* @param proc function to call on result
* @param proc_cls closure for processor
* @return handle to the queued request
*/
-struct GNUNET_CREDENTIAL_LookupRequest *
-GNUNET_CREDENTIAL_lookup (struct GNUNET_CREDENTIAL_Handle *handle,
- const char *credential,
- const struct GNUNET_IDENTITY_Ego *subject,
- GNUNET_CREDENTIAL_LookupResultProcessor proc,
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const char *issuer_attribute,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
+ uint32_t credential_count,
+ const struct GNUNET_CREDENTIAL_Credential *credentials,
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc,
void *proc_cls);
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const char *issuer_attribute,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
+ GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+ void *proc_cls);
/**
- * Issue a credential to an identity
+ * Delegate an attribute
*
* @param handle handle to the Credential service
- * @param issuer the identity that issues the credential
- * @param subject the subject of the credential
- * @param credential the name of the credential
- * @param value the value of the credential
+ * @param issuer the ego that should be used to delegate the attribute
+ * @param attribute the name of the attribute to delegate
+ * @param subject the subject of the delegation
+ * @param delegated_attribute the name of the attribute that is delegated to
+ * @param proc the result callback
+ * @param proc_cls the result closure context
* @return handle to the queued request
*/
-struct GNUNET_CREDENTIAL_IssueRequest *
-GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle,
- struct GNUNET_IDENTITY_Ego *issuer,
- struct GNUNET_IDENTITY_Ego *subject,
- const char *credential,
- struct GNUNET_CREDENTIAL_Value *value,
- GNUNET_CREDENTIAL_IssueResultProcessor proc,
- void *proc_cls);
+struct GNUNET_CREDENTIAL_Request *
+GNUNET_CREDENTIAL_add_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
+ struct GNUNET_IDENTITY_Ego *issuer,
+ const char *attribute,
+ struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
+ const char *delegated_attribute,
+ GNUNET_CREDENTIAL_DelegateResultProcessor proc,
+ void *proc_cls);
/**
- * Remove a credential
+ * Remove a delegation
*
* @param handle handle to the Credential service
- * @param issuer the identity that issued the credential
- * @param subject the subject of the credential
- * @param credential the name of the credential
+ * @param issuer the ego that was used to delegate the attribute